From d9bb13ba048bc215249b13001f16cb2d14e91455 Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Fri, 16 Oct 2015 14:59:19 -0500 Subject: [PATCH 1/3] Reorder application of has_many association constraints. With `unscope!` called last, it undoes `where` constraints of the same value when the `where` is chained after the `unscope`. This is what a `rewhere` does. This is undesirable behavior. The included tests demonstrate both the `unscope(...).where(...)` behavior as well as the direct use of `rewhere(...)`. This is in reference to #21955. --- .../associations/association_scope.rb | 2 +- .../has_many_associations_test.rb | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb index a140dc239c6..48437a1c9e7 100644 --- a/activerecord/lib/active_record/associations/association_scope.rb +++ b/activerecord/lib/active_record/associations/association_scope.rb @@ -147,9 +147,9 @@ module ActiveRecord scope.includes! item.includes_values end + scope.unscope!(*item.unscope_values) scope.where_clause += item.where_clause scope.order_values |= item.order_values - scope.unscope!(*item.unscope_values) end reflection = reflection.next diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index cd19a7a5bc8..eb94870a35b 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -2181,6 +2181,26 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal [bulb1, bulb2], car.all_bulbs.sort_by(&:id) end + test "can unscope and where the default scope of the associated model" do + Car.has_many :other_bulbs, -> { unscope(where: [:name]).where(name: 'other') }, class_name: "Bulb" + car = Car.create! + bulb1 = Bulb.create! name: "defaulty", car: car + bulb2 = Bulb.create! name: "other", car: car + + assert_equal [bulb1], car.bulbs + assert_equal [bulb2], car.other_bulbs + end + + test "can rewhere the default scope of the associated model" do + Car.has_many :old_bulbs, -> { rewhere(name: 'old') }, class_name: "Bulb" + car = Car.create! + bulb1 = Bulb.create! name: "defaulty", car: car + bulb2 = Bulb.create! name: "old", car: car + + assert_equal [bulb1], car.bulbs + assert_equal [bulb2], car.old_bulbs + end + test 'unscopes the default scope of associated model when used with include' do car = Car.create! bulb = Bulb.create! name: "other", car: car From dda4f608902752c5071809cedbe675086f0669be Mon Sep 17 00:00:00 2001 From: kal Date: Fri, 16 Oct 2015 02:18:36 +0000 Subject: [PATCH 2/3] Changed the order of Association constraints from where->order->unscope to unscope->where->order --- .../lib/active_record/associations/association_scope.rb | 2 +- .../test/cases/associations/has_many_associations_test.rb | 4 ++++ activerecord/test/models/post.rb | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb index a140dc239c6..48437a1c9e7 100644 --- a/activerecord/lib/active_record/associations/association_scope.rb +++ b/activerecord/lib/active_record/associations/association_scope.rb @@ -147,9 +147,9 @@ module ActiveRecord scope.includes! item.includes_values end + scope.unscope!(*item.unscope_values) scope.where_clause += item.where_clause scope.order_values |= item.order_values - scope.unscope!(*item.unscope_values) end reflection = reflection.next diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index cd19a7a5bc8..4ecf53e6d16 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -2358,4 +2358,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal [bulb.id], car.bulb_ids assert_no_queries { car.bulb_ids } end + + def test_has_many_association_with_rewhere + assert_equal 'Don\'t think too hard', posts(:welcome).comments_with_rewhere.first.body + end end diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index 81a18188d49..45a379df984 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -67,6 +67,7 @@ class Post < ActiveRecord::Base end has_many :comments_with_extend_2, extend: [NamedExtension, NamedExtension2], class_name: "Comment", foreign_key: "post_id" + has_many :comments_with_rewhere, -> { rewhere(post_id: 2) }, class_name: "Comment" has_many :author_favorites, :through => :author has_many :author_categorizations, :through => :author, :source => :categorizations From 209f3b30af1beffbf1cd2fd933c3453661239b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 20 Oct 2015 15:30:09 -0200 Subject: [PATCH 3/3] Add CHANGELOG entry for fix of #21955 [ci skip] --- activerecord/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 9e44131fa9f..efb3ffebaf3 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,9 @@ +* Fix `rewhere` in a `has_many` association. + + Fixes #21955. + + *Josh Branchaud*, *Kal* + * `where` raises ArgumentError on unsupported types. Fixes #20473.