diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 9d4ba329bcec6e02d26b146e0e05d793ab668ace..fb4895433d39a1042381e1a27f14960284d192b1 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1244,7 +1244,7 @@ def instantiate(row) class JoinAssociation < JoinBase attr_reader :reflection, :parent, :aliased_table_name, :aliased_prefix, :aliased_join_table_name, :parent_table_name - delegate :options, :klass, :to => :reflection + delegate :options, :klass, :through_reflection, :source_reflection, :to => :reflection def initialize(reflection, join_dependency, parent = nil) reflection.check_validity! @@ -1291,7 +1291,6 @@ def association_join when :has_many, :has_one case when reflection.macro == :has_many && reflection.options[:through] - through_reflection = parent.active_record.reflect_on_association(reflection.options[:through]) through_conditions = through_reflection.options[:conditions] ? "AND #{interpolate_sql(sanitize_sql(through_reflection.options[:conditions]))}" : '' if through_reflection.options[:as] # has_many :through against a polymorphic join polymorphic_foreign_key = through_reflection.options[:as].to_s + '_id' @@ -1305,16 +1304,26 @@ def association_join " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [table_name_and_alias, aliased_table_name, primary_key, aliased_join_table_name, options[:foreign_key] || reflection.klass.to_s.classify.foreign_key ] - else # has_many :through against a normal join + elsif source_reflection.macro == :belongs_to # has_many :through against a belongs_to " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ table_alias_for(through_reflection.klass.table_name, aliased_join_table_name), aliased_join_table_name, - through_reflection.options[:foreign_key] || through_reflection.active_record.to_s.classify.foreign_key, + through_reflection.primary_key_name, parent.aliased_table_name, parent.primary_key] + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ table_name_and_alias, aliased_table_name, primary_key, aliased_join_table_name, options[:foreign_key] || klass.to_s.classify.foreign_key ] + elsif source_reflection.macro == :has_many # has_many :through against a has_many + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ + table_alias_for(through_reflection.klass.table_name, aliased_join_table_name), aliased_join_table_name, + through_reflection.primary_key_name, + parent.aliased_table_name, parent.primary_key] + + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ + table_name_and_alias, + aliased_table_name, through_reflection.klass.to_s.classify.foreign_key, + aliased_join_table_name, options[:foreign_key] || primary_key + ] end when reflection.macro == :has_many && reflection.options[:as] @@ -1325,6 +1334,7 @@ def association_join aliased_table_name, "#{reflection.options[:as]}_type", klass.quote(parent.active_record.base_class.name) ] + else " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ table_name_and_alias, diff --git a/activerecord/test/associations_join_model_test.rb b/activerecord/test/associations_join_model_test.rb index 4b0f4e4c334841754ec780f7ed23eadbb04ba493..db5f3626105ed8b1f4f1196c9f88eda8de273f11 100644 --- a/activerecord/test/associations_join_model_test.rb +++ b/activerecord/test/associations_join_model_test.rb @@ -231,11 +231,11 @@ def test_has_many_polymorphic end def test_has_many_through_has_many_find_all - assert_equal comments(:greetings), authors(:david).comments.find(:all).first + assert_equal comments(:greetings), authors(:david).comments.find(:all, :order => 'comments.id').first end def test_has_many_through_has_many_find_first - assert_equal comments(:greetings), authors(:david).comments.find(:first) + assert_equal comments(:greetings), authors(:david).comments.find(:first, :order => 'comments.id') end def test_has_many_through_has_many_find_conditions @@ -246,6 +246,14 @@ def test_has_many_through_has_many_find_by_id assert_equal comments(:more_greetings), authors(:david).comments.find(2) end + def test_eager_load_has_many_through_has_many + author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id' + SpecialComment.new; VerySpecialComment.new + assert_no_queries do + assert_equal [1,2,3,5,6,7,8,9,10], author.comments.collect(&:id) + end + end + private # create dynamic Post models to allow different dependency options def find_post_with_dependency(post_id, association, association_name, dependency)