Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
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...
commit caec63929fabe0368da71128c96e74c174791eb9 1 parent 28f057c
@kuahyeow kuahyeow authored
View
20 activerecord/lib/active_record/associations.rb
@@ -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
View
15 activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -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?
View
5 activerecord/test/cases/associations/join_model_test.rb
@@ -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)
Please sign in to comment.
Something went wrong with that request. Please try again.