Support thread_mattr_accessor in anonymous classes

This allows `thread_mattr_accessor` to be used with anonymous classes
when e.g. testing.
This commit is contained in:
Jonathan Hefner 2022-09-01 14:37:23 -05:00
parent b8fc7898fe
commit 410c6144c6
2 changed files with 8 additions and 12 deletions

View File

@ -42,12 +42,12 @@ class Module
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
# The following generated method concatenates `name` because we want it
# to work with inheritance via polymorphism.
# The following generated method concatenates `object_id` because we want
# subclasses to maintain independent values.
if default.nil?
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def self.#{sym}
@__thread_mattr_#{sym} ||= "attr_\#{name}_#{sym}"
@__thread_mattr_#{sym} ||= "attr_#{sym}_\#{object_id}"
::ActiveSupport::IsolatedExecutionState[@__thread_mattr_#{sym}]
end
EOS
@ -56,7 +56,7 @@ class Module
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def self.#{sym}
@__thread_mattr_#{sym} ||= "attr_\#{name}_#{sym}"
@__thread_mattr_#{sym} ||= "attr_#{sym}_\#{object_id}"
value = ::ActiveSupport::IsolatedExecutionState[@__thread_mattr_#{sym}]
if value.nil? && !::ActiveSupport::IsolatedExecutionState.key?(@__thread_mattr_#{sym})
@ -101,11 +101,11 @@ class Module
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
# The following generated method concatenates `name` because we want it
# to work with inheritance via polymorphism.
# The following generated method concatenates `object_id` because we want
# subclasses to maintain independent values.
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def self.#{sym}=(obj)
@__thread_mattr_#{sym} ||= "attr_\#{name}_#{sym}"
@__thread_mattr_#{sym} ||= "attr_#{sym}_\#{object_id}"
::ActiveSupport::IsolatedExecutionState[@__thread_mattr_#{sym}] = obj
end
EOS

View File

@ -6,17 +6,13 @@ require "active_support/core_ext/module/attribute_accessors_per_thread"
class ModuleAttributeAccessorPerThreadTest < ActiveSupport::TestCase
setup do
@class = Class.new do
def self.name; "MyClass#{object_id}"; end
thread_mattr_accessor :foo
thread_mattr_accessor :bar, instance_writer: false
thread_mattr_reader :shaq, instance_reader: false
thread_mattr_accessor :camp, instance_accessor: false
end
@subclass = Class.new(@class) do
def self.name; "Sub#{super}"; end
end
@subclass = Class.new(@class)
@object = @class.new
end