1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Use methods to get ScopeRegistry values rather than symbols

We're spending time validating symbol parameters of the ScopeRegistry.
It's an internal class, and we can stop validating symbols by converting
to methods (you'll automatically get an error if you try to call a
method that doesn't exist).  Second, since we only have 3 things to keep
track of, rather than keep those things in a hash, just break it out in
to 3 instance variables.  (This is absolutely not a memory bottleneck,
but technically this patch will save some memory as the 3 ivars will be
embedded in the object rather than require a full st_table for the
original wrapper hash)
This commit is contained in:
Aaron Patterson 2021-04-02 12:14:57 -07:00
parent bcf3752247
commit 73c18888ad
No known key found for this signature in database
GPG key ID: 953170BCB4FFAFC6
3 changed files with 37 additions and 27 deletions

View file

@ -24,19 +24,23 @@ module ActiveRecord
end end
def current_scope(skip_inherited_scope = false) def current_scope(skip_inherited_scope = false)
ScopeRegistry.value_for(:current_scope, self, skip_inherited_scope) ScopeRegistry.current_scope(self, skip_inherited_scope)
end end
def current_scope=(scope) def current_scope=(scope)
ScopeRegistry.set_value_for(:current_scope, self, scope) ScopeRegistry.set_current_scope(self, scope)
end end
def global_current_scope(skip_inherited_scope = false) def global_current_scope(skip_inherited_scope = false)
ScopeRegistry.value_for(:global_current_scope, self, skip_inherited_scope) ScopeRegistry.global_current_scope(self, skip_inherited_scope)
end end
def global_current_scope=(scope) def global_current_scope=(scope)
ScopeRegistry.set_value_for(:global_current_scope, self, scope) ScopeRegistry.set_global_current_scope(self, scope)
end
def scope_registry
ScopeRegistry.instance
end end
end end
@ -80,34 +84,40 @@ module ActiveRecord
VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope, :global_current_scope] VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope, :global_current_scope]
def initialize def initialize
@registry = Hash.new { |hash, key| hash[key] = {} } @current_scope = {}
@ignore_default_scope = {}
@global_current_scope = {}
end end
# Obtains the value for a given +scope_type+ and +model+. VALID_SCOPE_TYPES.each do |type|
def value_for(scope_type, model, skip_inherited_scope = false) class_eval <<-eorb, __FILE__, __LINE__
raise_invalid_scope_type!(scope_type) def #{type}(model, skip_inherited_scope = false)
return @registry[scope_type][model.name] if skip_inherited_scope value_for(@#{type}, model, skip_inherited_scope)
klass = model
base = model.base_class
while klass <= base
value = @registry[scope_type][klass.name]
return value if value
klass = klass.superclass
end end
end
# Sets the +value+ for a given +scope_type+ and +model+. def set_#{type}(model, value)
def set_value_for(scope_type, model, value) set_value_for(@#{type}, model, value)
raise_invalid_scope_type!(scope_type) end
@registry[scope_type][model.name] = value eorb
end end
private private
def raise_invalid_scope_type!(scope_type) # Obtains the value for a given +scope_type+ and +model+.
if !VALID_SCOPE_TYPES.include?(scope_type) def value_for(scope_type, model, skip_inherited_scope = false)
raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES" return scope_type[model.name] if skip_inherited_scope
klass = model
base = model.base_class
while klass <= base
value = scope_type[klass.name]
return value if value
klass = klass.superclass
end end
end end
# Sets the +value+ for a given +scope_type+ and +model+.
def set_value_for(scope_type, model, value)
scope_type[model.name] = value
end
end end
end end
end end

View file

@ -173,11 +173,11 @@ module ActiveRecord
end end
def ignore_default_scope? def ignore_default_scope?
ScopeRegistry.value_for(:ignore_default_scope, base_class) ScopeRegistry.ignore_default_scope(base_class)
end end
def ignore_default_scope=(ignore) def ignore_default_scope=(ignore)
ScopeRegistry.set_value_for(:ignore_default_scope, base_class, ignore) ScopeRegistry.set_ignore_default_scope(base_class, ignore)
end end
# The ignore_default_scope flag is used to prevent an infinite recursion # The ignore_default_scope flag is used to prevent an infinite recursion

View file

@ -1259,9 +1259,9 @@ class BasicsTest < ActiveRecord::TestCase
UnloadablePost.unloadable UnloadablePost.unloadable
klass = UnloadablePost klass = UnloadablePost
assert_not_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, klass) assert_not_nil ActiveRecord::Scoping::ScopeRegistry.current_scope(klass)
ActiveSupport::Dependencies.remove_unloadable_constants! ActiveSupport::Dependencies.remove_unloadable_constants!
assert_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, klass) assert_nil ActiveRecord::Scoping::ScopeRegistry.current_scope(klass)
ensure ensure
Object.class_eval { remove_const :UnloadablePost } if defined?(UnloadablePost) Object.class_eval { remove_const :UnloadablePost } if defined?(UnloadablePost)
end end