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
def current_scope(skip_inherited_scope = false)
ScopeRegistry.value_for(:current_scope, self, skip_inherited_scope)
ScopeRegistry.current_scope(self, skip_inherited_scope)
end
def current_scope=(scope)
ScopeRegistry.set_value_for(:current_scope, self, scope)
ScopeRegistry.set_current_scope(self, scope)
end
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
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
@ -80,17 +84,31 @@ module ActiveRecord
VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope, :global_current_scope]
def initialize
@registry = Hash.new { |hash, key| hash[key] = {} }
@current_scope = {}
@ignore_default_scope = {}
@global_current_scope = {}
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+.
def value_for(scope_type, model, skip_inherited_scope = false)
raise_invalid_scope_type!(scope_type)
return @registry[scope_type][model.name] if skip_inherited_scope
return scope_type[model.name] if skip_inherited_scope
klass = model
base = model.base_class
while klass <= base
value = @registry[scope_type][klass.name]
value = scope_type[klass.name]
return value if value
klass = klass.superclass
end
@ -98,15 +116,7 @@ module ActiveRecord
# 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][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
scope_type[model.name] = value
end
end
end

View file

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

View file

@ -1259,9 +1259,9 @@ class BasicsTest < ActiveRecord::TestCase
UnloadablePost.unloadable
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!
assert_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, klass)
assert_nil ActiveRecord::Scoping::ScopeRegistry.current_scope(klass)
ensure
Object.class_eval { remove_const :UnloadablePost } if defined?(UnloadablePost)
end