From 56b870f243c1a73a1d15638500e5aa5e7ae9a1cc Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 15 Aug 2017 21:39:40 +0900 Subject: Through scope should not be affected by scoping Follow up of #29834. Fixes #30266. --- .../associations/preloader/association.rb | 12 +----------- .../active_record/associations/through_association.rb | 2 +- activerecord/lib/active_record/reflection.rb | 9 ++------- activerecord/lib/active_record/scoping/named.rb | 10 ++++++++++ .../has_many_through_associations_test.rb | 19 +++++++++++++++++++ 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index 5ba03c555a..4915a37f06 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -116,18 +116,8 @@ module ActiveRecord @reflection_scope ||= reflection.scope_for(klass) end - def klass_scope - current_scope = klass.current_scope - - if current_scope && current_scope.empty_scope? - klass.unscoped - else - klass.default_scoped - end - end - def build_scope - scope = klass_scope + scope = klass.scope_for_association if reflection.type scope.where!(reflection.type => model.base_class.sti_name) diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb index 76237c4a0c..cba565448f 100644 --- a/activerecord/lib/active_record/associations/through_association.rb +++ b/activerecord/lib/active_record/associations/through_association.rb @@ -15,7 +15,7 @@ module ActiveRecord def target_scope scope = super reflection.chain.drop(1).each do |reflection| - relation = reflection.klass.all + relation = reflection.klass.scope_for_association scope.merge!( relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load) ) diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index b2c62cd686..b847933b2e 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -221,13 +221,8 @@ module ActiveRecord end def klass_join_scope(table, predicate_builder) # :nodoc: - current_scope = klass.current_scope - - if current_scope && current_scope.empty_scope? - build_scope(table, predicate_builder) - else - klass.default_scoped(build_scope(table, predicate_builder)) - end + relation = build_scope(table, predicate_builder) + klass.scope_for_association(relation) end def constraints diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb index 43cce19c1f..6fa096c1fe 100644 --- a/activerecord/lib/active_record/scoping/named.rb +++ b/activerecord/lib/active_record/scoping/named.rb @@ -31,6 +31,16 @@ module ActiveRecord end end + def scope_for_association(scope = relation) # :nodoc: + current_scope = self.current_scope + + if current_scope && current_scope.empty_scope? + scope + else + default_scoped(scope) + end + end + def default_scoped(scope = relation) # :nodoc: build_default_scope(scope) || scope end diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 968c0eb944..f8ea51225a 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -1261,6 +1261,25 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal 0, users[2].family_members.to_a.size end + def test_through_scope_is_affected_by_unscoping + author = authors(:david) + + expected = author.comments.to_a + FirstPost.unscoped do + assert_equal expected.sort_by(&:id), author.comments_on_first_posts.sort_by(&:id) + end + end + + def test_through_scope_isnt_affected_by_scoping + author = authors(:david) + + expected = author.comments_on_first_posts.to_a + FirstPost.where(id: 2).scoping do + author.comments_on_first_posts.reset + assert_equal expected.sort_by(&:id), author.comments_on_first_posts.sort_by(&:id) + end + end + def test_incorrectly_ordered_through_associations assert_raises(ActiveRecord::HasManyThroughOrderError) do DeveloperWithIncorrectlyOrderedHasManyThrough.create( -- cgit v1.2.3