Permalink
Browse files

Active scopes apply to child classes, though not parents/siblings

While the commit message (and changelog example) in
5e0b555 talked about sibling classes,
the added test had a child ignore its parent's scoping, which seems less
reasonable.
  • Loading branch information...
matthewd committed Jan 11, 2016
1 parent 179df9d commit 8ce0175d50f7fafe648afb8342e17c0898e0ff7f
@@ -11,11 +11,11 @@ module Scoping
module ClassMethods
def current_scope #:nodoc:
ScopeRegistry.value_for(:current_scope, self.to_s)
ScopeRegistry.value_for(:current_scope, self)
end
def current_scope=(scope) #:nodoc:
ScopeRegistry.set_value_for(:current_scope, self.to_s, scope)
ScopeRegistry.set_value_for(:current_scope, self, scope)
end
# Collects attributes from scopes that should be applied when creating
@@ -53,18 +53,18 @@ def initialize_internals_callback # :nodoc:
# following code:
#
# registry = ActiveRecord::Scoping::ScopeRegistry
# registry.set_value_for(:current_scope, "Board", some_new_scope)
# registry.set_value_for(:current_scope, Board, some_new_scope)
#
# Now when you run:
#
# registry.value_for(:current_scope, "Board")
# registry.value_for(:current_scope, Board)
#
# You will obtain whatever was defined in +some_new_scope+. The #value_for
# and #set_value_for methods are delegated to the current ScopeRegistry
# object, so the above example code can also be called as:
#
# ActiveRecord::Scoping::ScopeRegistry.set_value_for(:current_scope,
# "Board", some_new_scope)
# Board, some_new_scope)
class ScopeRegistry # :nodoc:
extend ActiveSupport::PerThreadRegistry
@@ -74,16 +74,22 @@ def initialize
@registry = Hash.new { |hash, key| hash[key] = {} }
end
# Obtains the value for a given +scope_name+ and +variable_name+.
def value_for(scope_type, variable_name)
# Obtains the value for a given +scope_type+ and +model+.
def value_for(scope_type, model)
raise_invalid_scope_type!(scope_type)
@registry[scope_type][variable_name]
klass = model
base = model.base_class
while klass <= base
value = @registry[scope_type][klass.name]
return value if value
klass = klass.superclass
end
end
# Sets the +value+ for a given +scope_type+ and +variable_name+.
def set_value_for(scope_type, variable_name, value)
# Sets the +value+ for a given +scope_type+ and +model+.
def set_value_for(scope_type, model, value)
raise_invalid_scope_type!(scope_type)
@registry[scope_type][variable_name] = value
@registry[scope_type][model.name] = value
end
private
@@ -1275,9 +1275,10 @@ def test_current_scope_is_reset
UnloadablePost.send(:current_scope=, UnloadablePost.all)
UnloadablePost.unloadable
assert_not_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, "UnloadablePost")
klass = UnloadablePost
assert_not_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, klass)
ActiveSupport::Dependencies.remove_unloadable_constants!
assert_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, "UnloadablePost")
assert_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, klass)
ensure
Object.class_eval{ remove_const :UnloadablePost } if defined?(UnloadablePost)
end
@@ -209,9 +209,23 @@ def test_delete_all_default_scope_filters_on_joins
assert_not_equal [], Developer.all
end
def test_current_scope_does_not_pollute_other_subclasses
Post.none.scoping do
assert StiPost.all.any?
def test_current_scope_does_not_pollute_sibling_subclasses
Comment.none.scoping do
assert_not SpecialComment.all.any?
assert_not VerySpecialComment.all.any?
assert_not SubSpecialComment.all.any?
end
SpecialComment.none.scoping do
assert Comment.all.any?
assert VerySpecialComment.all.any?
assert_not SubSpecialComment.all.any?
end
SubSpecialComment.none.scoping do
assert Comment.all.any?
assert VerySpecialComment.all.any?
assert SpecialComment.all.any?
end
end
end

0 comments on commit 8ce0175

Please sign in to comment.