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,17 +84,31 @@ 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
VALID_SCOPE_TYPES.each do |type|
class_eval <<-eorb, __FILE__, __LINE__
def #{type}(model, skip_inherited_scope = false)
value_for(@#{type}, model, skip_inherited_scope)
end
def set_#{type}(model, value)
set_value_for(@#{type}, model, value)
end
eorb
end
private
# Obtains the value for a given +scope_type+ and +model+. # Obtains the value for a given +scope_type+ and +model+.
def value_for(scope_type, model, skip_inherited_scope = false) def value_for(scope_type, model, skip_inherited_scope = false)
raise_invalid_scope_type!(scope_type) return scope_type[model.name] if skip_inherited_scope
return @registry[scope_type][model.name] if skip_inherited_scope
klass = model klass = model
base = model.base_class base = model.base_class
while klass <= base while klass <= base
value = @registry[scope_type][klass.name] value = scope_type[klass.name]
return value if value return value if value
klass = klass.superclass klass = klass.superclass
end end
@ -98,15 +116,7 @@ module ActiveRecord
# Sets the +value+ for a given +scope_type+ and +model+. # Sets the +value+ for a given +scope_type+ and +model+.
def set_value_for(scope_type, model, value) def set_value_for(scope_type, model, value)
raise_invalid_scope_type!(scope_type) scope_type[model.name] = value
@registry[scope_type][model.name] = value
end
private
def raise_invalid_scope_type!(scope_type)
if !VALID_SCOPE_TYPES.include?(scope_type)
raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
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