diff options
3 files changed, 41 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index 25fde49650..582474355e 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -23,8 +23,15 @@ module ActiveRecord # TODO: Conditions on joins def construct_conditions reflection = @reflection.through_reflection_chain.last + + if reflection.macro == :has_and_belongs_to_many + table_alias = table_aliases[reflection].first + else + table_alias = table_aliases[reflection] + end + conditions = construct_quoted_owner_attributes(reflection).map do |attr, value| - "#{table_aliases[reflection]}.#{attr} = #{value}" + "#{table_alias}.#{attr} = #{value}" end conditions << sql_conditions if sql_conditions "(" + conditions.join(') AND (') + ")" @@ -97,12 +104,30 @@ module ActiveRecord source_type_conditions(left) ) when :has_many, :has_one + if right.macro == :has_and_belongs_to_many + join_table, right_table = table_aliases[right] + right_table_and_alias = table_name_and_alias(right.quoted_table_name, right_table) + else + right_table = table_aliases[right] + end + joins << inner_join_sql( right_table_and_alias, - table_aliases[left], left.source_reflection.primary_key_name, - table_aliases[right], right.klass.primary_key, + table_aliases[left], left.source_reflection.primary_key_name, + right_table, right.klass.primary_key, polymorphic_conditions(left, left.source_reflection.options[:as]) ) + + if right.macro == :has_and_belongs_to_many + joins << inner_join_sql( + table_name_and_alias( + quote_table_name(right.options[:join_table]), + join_table + ), + right_table, right.klass.primary_key, + join_table, right.association_foreign_key + ) + end when :has_and_belongs_to_many join_table, left_table = table_aliases[left] diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 964112b006..4e7e766b14 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -169,9 +169,19 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [categories(:general), categories(:cooking)], authors[2].post_categories end - # TODO: has_many through + # has_many through # Source: has_many # Through: has_and_belongs_to_many + def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection + assert_equal [comments(:greetings), comments(:more_greetings)], categories(:technology).post_comments + + categories = Category.joins(:post_comments).where('comments.id' => comments(:more_greetings).id) + assert_equal [categories(:general), categories(:technology)], categories + + # TODO: Make this work + # categories = Category.includes(:post_comments) + # assert_equal [comments(:greetings), comments(:more_greetings)], categories[1].post_comments + end # TODO: has_many through # Source: belongs_to diff --git a/activerecord/test/models/category.rb b/activerecord/test/models/category.rb index 48415846dd..c933943813 100644 --- a/activerecord/test/models/category.rb +++ b/activerecord/test/models/category.rb @@ -23,6 +23,8 @@ class Category < ActiveRecord::Base has_many :categorizations has_many :authors, :through => :categorizations, :select => 'authors.*, categorizations.post_id' + + has_many :post_comments, :through => :posts, :source => :comments end class SpecialCategory < Category |