Permalink
Browse files

Fix for 3-0-stable - Conditions specified on through association shou…

…ldn't clobber asssociation join condition.

This fix refactors processing of association join conditions so that both the join condition and the custom condition will be used when called by query_methods.rb, which expects a 1 or 2-sized array (depending on the type of association). Previously, a custom condition specified would create a 2 or 3-sized array which will clobber the association join condition.
  • Loading branch information...
1 parent 28f057c commit caec63929fabe0368da71128c96e74c174791eb9 @kuahyeow kuahyeow committed Jun 21, 2011
@@ -2145,6 +2145,7 @@ def association_join
parent_table = Arel::Table.new(parent.table_name, :as => parent.aliased_table_name,
:engine => arel_engine,
:columns => parent.active_record.columns)
+ as_conditions = reflection.options[:conditions] && process_conditions(reflection.options[:conditions], aliased_table_name)
@join = case reflection.macro
when :has_and_belongs_to_many
@@ -2154,11 +2155,12 @@ def association_join
[
join_table[fk].eq(parent_table[reflection.active_record.primary_key]),
- aliased_table[klass.primary_key].eq(join_table[klass_fk])
+ [aliased_table[klass.primary_key].eq(join_table[klass_fk]), as_conditions].reject{ |x| x.blank? }
]
when :has_many, :has_one
if reflection.options[:through]
join_table = Arel::Table.new(through_reflection.klass.table_name, :as => aliased_join_table_name, :engine => arel_engine)
+ jt_as_conditions = through_reflection.options[:conditions] && process_conditions(through_reflection.options[:conditions], aliased_table_name)
jt_as_extra = jt_source_extra = jt_sti_extra = nil
first_key = second_key = as_extra = nil
@@ -2199,19 +2201,19 @@ def association_join
end
[
- [parent_table[jt_primary_key].eq(join_table[jt_foreign_key]), jt_as_extra, jt_source_extra, jt_sti_extra].reject{|x| x.blank? },
- [aliased_table[first_key].eq(join_table[second_key]), as_extra].reject{ |x| x.blank? }
+ [parent_table[jt_primary_key].eq(join_table[jt_foreign_key]), jt_as_extra, jt_source_extra, jt_sti_extra, jt_as_conditions].reject{|x| x.blank? },
+ [aliased_table[first_key].eq(join_table[second_key]), as_extra, as_conditions].reject{ |x| x.blank? }
]
elsif reflection.options[:as]
id_rel = aliased_table["#{reflection.options[:as]}_id"].eq(parent_table[parent.primary_key])
type_rel = aliased_table["#{reflection.options[:as]}_type"].eq(parent.active_record.base_class.name)
- [id_rel, type_rel]
+ [id_rel, type_rel, as_conditions].reject{ |x| x.blank?}
else
foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key
- [aliased_table[foreign_key].eq(parent_table[reflection.options[:primary_key] || parent.primary_key])]
+ [aliased_table[foreign_key].eq(parent_table[reflection.options[:primary_key] || parent.primary_key]), as_conditions].reject{ |x| x.blank? }
end
when :belongs_to
- [aliased_table[options[:primary_key] || reflection.klass.primary_key].eq(parent_table[options[:foreign_key] || reflection.primary_key_name])]
+ [aliased_table[options[:primary_key] || reflection.klass.primary_key].eq(parent_table[options[:foreign_key] || reflection.primary_key_name]), as_conditions].reject{ |x| x.blank? }
end
unless klass.descends_from_active_record?
@@ -2222,12 +2224,6 @@ def association_join
@join << sti_condition
end
- [through_reflection, reflection].each do |ref|
- if ref && ref.options[:conditions]
- @join << process_conditions(ref.options[:conditions], aliased_table_name)
- end
- end
-
@join
end
@@ -482,6 +482,21 @@ def test_joining_has_many_through_belongs_to
assert_equal [posts(:eager_other)], posts
end
+ def test_join_on_has_many_association_collection_with_conditions
+ posts(:welcome).tags.create!(:name => 'Misc')
+ invalid_posts = Post.joins(:misc_tags).where('posts.id' => posts(:welcome).id).where('taggings.tag_id != tags.id')
+ assert_equal [], invalid_posts
+
+ posts = Post.joins(:misc_tags).where('posts.id' => posts(:welcome).id)
+ assert_equal [posts(:welcome)], posts
+
+ invalid_posts = Post.all(:joins => :misc_tags, :conditions => ['posts.id =? and taggings.tag_id != tags.id', posts(:welcome).id])
+ assert_equal [], invalid_posts
+
+ posts = Post.all(:joins => :misc_tags, :conditions => {:posts => {:id => posts(:welcome).id}})
+ assert_equal [posts(:welcome)], posts
+ end
+
def test_interpolated_conditions
post = posts(:welcome)
assert !post.tags.empty?
@@ -342,6 +342,11 @@ def test_has_many_polymorphic
end
end
+ def test_polymorphic_join_with_conditions
+ assert_equal [], Author.joins(:posts => :invalid_taggings).all
+ assert_equal [], Post.joins(:invalid_taggings).all
+ end
+
def test_has_many_polymorphic_with_source_type
# added sort by ID as otherwise Oracle select sometimes returned rows in different order
assert_equal posts(:welcome, :thinking).sort_by(&:id), tags(:general).tagged_posts.sort_by(&:id)

0 comments on commit caec639

Please sign in to comment.