diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index e1e53ec559..af3362fe83 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Allow :include to be used with has_many :through associations #3611 [Michael Schoen] + * PostgreSQL: smarter schema dumps using pk_and_sequence_for(table). #2920 [Blair Zajac] * SQLServer: more compatible limit/offset emulation. #3779 [Tom Ward] diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 0dc03487cb..b8f933ee6c 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1028,7 +1028,7 @@ module ActiveRecord end def construct_finder_sql_with_included_associations(options, schema_abbreviations, reflections) - sql = "SELECT #{column_aliases(schema_abbreviations)} FROM #{table_name} " + sql = "SELECT #{column_aliases(schema_abbreviations)} FROM #{options[:from] || table_name} " sql << reflections.collect { |reflection| association_join(reflection) }.to_s sql << "#{options[:joins]} " if options[:joins] diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index de0854a8cd..413f56857f 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -80,7 +80,7 @@ module ActiveRecord end def construct_from - "#{@reflection.table_name}, #{@owner.class.reflections[@reflection.options[:through]].table_name}" + "#{@owner.class.reflections[@reflection.options[:through]].table_name}, #{@reflection.table_name}" end def construct_select diff --git a/activerecord/test/associations_go_eager_test.rb b/activerecord/test/associations_go_eager_test.rb index a03c201d76..1bc9d9f982 100644 --- a/activerecord/test/associations_go_eager_test.rb +++ b/activerecord/test/associations_go_eager_test.rb @@ -4,10 +4,12 @@ require 'fixtures/comment' require 'fixtures/author' require 'fixtures/category' require 'fixtures/company' +require 'fixtures/person' +require 'fixtures/reader' class EagerAssociationTest < Test::Unit::TestCase fixtures :posts, :comments, :authors, :categories, :categories_posts, - :companies, :accounts + :companies, :accounts, :tags, :people, :readers def test_loading_with_one_association posts = Post.find(:all, :include => :comments) @@ -101,6 +103,15 @@ class EagerAssociationTest < Test::Unit::TestCase assert_equal [], posts end + def test_eager_with_has_many_through + posts_with_comments = people(:michael).posts.find(:all, :include => :comments ) + posts_with_author = people(:michael).posts.find(:all, :include => :author ) + posts_with_comments_and_author = people(:michael).posts.find(:all, :include => [ :comments, :author ]) + assert_equal 2, posts_with_comments.inject(0) { |sum, post| sum += post.comments.size } + assert_equal authors(:david), posts_with_author.first.author + assert_equal authors(:david), posts_with_comments_and_author.first.author + end + def test_eager_with_has_many_and_limit posts = Post.find(:all, :order => 'posts.id asc', :include => [ :author, :comments ], :limit => 2) assert_equal 2, posts.size diff --git a/activerecord/test/fixtures/db_definitions/db2.sql b/activerecord/test/fixtures/db_definitions/db2.sql index 9bb2ad991a..d570f925e9 100644 --- a/activerecord/test/fixtures/db_definitions/db2.sql +++ b/activerecord/test/fixtures/db_definitions/db2.sql @@ -130,6 +130,13 @@ CREATE TABLE people ( PRIMARY KEY (id) ); +CREATE TABLE readers ( + id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), + post_id INT NOT NULL, + person_id INT NOT NULL, + PRIMARY KEY (id) +); + CREATE TABLE binaries ( id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 10000), data BLOB(50000), diff --git a/activerecord/test/fixtures/db_definitions/firebird.sql b/activerecord/test/fixtures/db_definitions/firebird.sql index 28e4c71b71..87eb00c53f 100644 --- a/activerecord/test/fixtures/db_definitions/firebird.sql +++ b/activerecord/test/fixtures/db_definitions/firebird.sql @@ -161,6 +161,15 @@ CREATE TABLE people ( CREATE GENERATOR people_seq; SET GENERATOR people_seq TO 10000; +CREATE TABLE readers ( + id BIGINT NOT NULL, + post_id BIGINT NOT NULL, + person_id BIGINT NOT NULL, + PRIMARY KEY (id) +); +CREATE GENERATOR readers_seq; +SET GENERATOR readers_seq TO 10000; + CREATE TABLE binaries ( id BIGINT NOT NULL, data BLOB, diff --git a/activerecord/test/fixtures/db_definitions/mysql.sql b/activerecord/test/fixtures/db_definitions/mysql.sql index 83479393f4..21c3b0176e 100755 --- a/activerecord/test/fixtures/db_definitions/mysql.sql +++ b/activerecord/test/fixtures/db_definitions/mysql.sql @@ -130,6 +130,12 @@ CREATE TABLE `people` ( `lock_version` INTEGER NOT NULL DEFAULT 0 ) TYPE=InnoDB; +CREATE TABLE `readers` ( + `id` int(11) NOT NULL PRIMARY KEY, + `post_id` INTEGER NOT NULL, + `person_id` INTEGER NOT NULL +) TYPE=InnoDB; + CREATE TABLE `binaries` ( `id` int(11) NOT NULL auto_increment, `data` mediumblob, diff --git a/activerecord/test/fixtures/db_definitions/oci.sql b/activerecord/test/fixtures/db_definitions/oci.sql index 9995f4c85e..760659d1c4 100644 --- a/activerecord/test/fixtures/db_definitions/oci.sql +++ b/activerecord/test/fixtures/db_definitions/oci.sql @@ -187,6 +187,14 @@ create table people ( ); create sequence people_seq minvalue 10000; +create table readers ( + id integer not null, + post_id integer not null, + person_id integer not null, + primary key (id) +); +create sequence readers_seq minvalue 10000; + create table binaries ( id integer not null, data blob null, diff --git a/activerecord/test/fixtures/db_definitions/postgresql.sql b/activerecord/test/fixtures/db_definitions/postgresql.sql index c01afc206d..490f915791 100644 --- a/activerecord/test/fixtures/db_definitions/postgresql.sql +++ b/activerecord/test/fixtures/db_definitions/postgresql.sql @@ -153,6 +153,13 @@ CREATE TABLE people ( PRIMARY KEY (id) ); +CREATE TABLE readers ( + id serial, + post_id integer NOT NULL, + person_id integer NOT NULL, + primary key (id) +); + CREATE TABLE binaries ( id serial , data bytea, diff --git a/activerecord/test/fixtures/db_definitions/sqlite.sql b/activerecord/test/fixtures/db_definitions/sqlite.sql index b66969a40b..685c2abc8b 100644 --- a/activerecord/test/fixtures/db_definitions/sqlite.sql +++ b/activerecord/test/fixtures/db_definitions/sqlite.sql @@ -118,6 +118,12 @@ CREATE TABLE 'people' ( 'lock_version' INTEGER NOT NULL DEFAULT 0 ); +CREATE TABLE 'readers' ( + 'id' INTEGER NOT NULL PRIMARY KEY, + 'post_id' INTEGER NOT NULL, + 'person_id' INTEGER NOT NULL +); + CREATE TABLE 'binaries' ( 'id' INTEGER NOT NULL PRIMARY KEY, 'data' BLOB DEFAULT NULL diff --git a/activerecord/test/fixtures/db_definitions/sqlserver.sql b/activerecord/test/fixtures/db_definitions/sqlserver.sql index 81399b7d26..5999bdd1b4 100644 --- a/activerecord/test/fixtures/db_definitions/sqlserver.sql +++ b/activerecord/test/fixtures/db_definitions/sqlserver.sql @@ -118,6 +118,13 @@ CREATE TABLE people ( PRIMARY KEY (id) ); +CREATE TABLE readers ( + id int NOT NULL IDENTITY(1, 1), + post_id int NOT NULL, + person_id int NOT NULL, + primary key (id) +); + CREATE TABLE binaries ( id int NOT NULL IDENTITY(1, 1) PRIMARY KEY, data image NULL diff --git a/activerecord/test/fixtures/person.rb b/activerecord/test/fixtures/person.rb index 4fa5811c71..7a9666f4eb 100644 --- a/activerecord/test/fixtures/person.rb +++ b/activerecord/test/fixtures/person.rb @@ -1 +1,4 @@ -class Person < ActiveRecord::Base; end +class Person < ActiveRecord::Base + has_many :readers + has_many :posts, :through => :readers +end diff --git a/activerecord/test/fixtures/post.rb b/activerecord/test/fixtures/post.rb index 4c2ccb3f43..7c1f8e1961 100644 --- a/activerecord/test/fixtures/post.rb +++ b/activerecord/test/fixtures/post.rb @@ -28,6 +28,9 @@ class Post < ActiveRecord::Base has_many :categorizations, :foreign_key => :category_id has_many :authors, :through => :categorizations + has_many :readers + has_many :people, :through => :readers + def self.what_are_you 'a post...' end