diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index e232aa814c..3afaba5eb7 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -421,18 +421,20 @@ module ActiveRecord # Please check unscoped if you want to remove all previous scopes (including # the default_scope) during the execution of a block. def scoping(all_queries: nil) - if global_scope? && all_queries == false + registry = klass.scope_registry + if global_scope?(registry) && all_queries == false raise ArgumentError, "Scoping is set to apply to all queries and cannot be unset in a nested block." - elsif already_in_scope? + elsif already_in_scope?(registry) yield else - _scoping(self, all_queries) { yield } + _scoping(self, registry, all_queries) { yield } end end def _exec_scope(*args, &block) # :nodoc: @delegate_to_klass = true - _scoping(nil) { instance_exec(*args, &block) || self } + registry = klass.scope_registry + _scoping(nil, registry) { instance_exec(*args, &block) || self } ensure @delegate_to_klass = false end @@ -831,12 +833,12 @@ module ActiveRecord end private - def already_in_scope? - @delegate_to_klass && klass.current_scope(true) + def already_in_scope?(registry) + @delegate_to_klass && registry.current_scope(klass, true) end - def global_scope? - klass.global_current_scope(true) + def global_scope?(registry) + registry.global_current_scope(klass, true) end def current_scope_restoring_block(&block) @@ -859,16 +861,19 @@ module ActiveRecord klass.create!(attributes, &block) end - def _scoping(scope, all_queries = false) - previous, klass.current_scope = klass.current_scope(true), scope + def _scoping(scope, registry, all_queries = false) + previous = registry.current_scope(klass, true) + registry.set_current_scope(klass, scope) + if all_queries - previous_global, klass.global_current_scope = klass.global_current_scope(true), scope + previous_global = registry.global_current_scope(klass, true) + registry.set_global_current_scope(klass, scope) end yield ensure - klass.current_scope = previous + registry.set_current_scope(klass, previous) if all_queries - klass.global_current_scope = previous_global + registry.set_global_current_scope(klass, previous_global) end end diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 8636b34434..5f3be4733e 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -8,7 +8,7 @@ module ActiveRecord module SpawnMethods # This is overridden by Associations::CollectionProxy def spawn #:nodoc: - already_in_scope? ? klass.all : clone + already_in_scope?(klass.scope_registry) ? klass.all : clone end # Merges in the conditions from other, if other is an ActiveRecord::Relation. diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index d55d1e16ae..15f7f55725 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -324,6 +324,10 @@ class FakeKlass extend ActiveRecord::Delegation::DelegateCache class << self + def scope_registry + ActiveRecord::Scoping::ScopeRegistry.instance + end + def connection Post.connection end