Skip to content

Commit 72d8359

Browse files
committed
fix(class_methods): define instance reader at declaration time
Moves the instance reader definition for attributes declared with simple_class_attribute out of the singleton setter and into the attribute declaration itself. Earlier behavior: the instance method (e.g., flag) was defined only when the class setter (klass.flag = ...) ran. That caused instances to lack the reader method until the setter had been called. New behavior: when simple_class_attribute :name is declared, the instance reader name is defined immediately (but it still checks an instance ivar first and falls back to the singleton-class value if the ivar isn't set). The class setter now only defines the singleton reader to return the assigned value. Why?: Fixes a NoMethodError in the failing spec where an instance reader is expected to exist even if the class-level setter hasn't been used yet (for example, the test that sets instance.instance_variable_set('@Flag', 'local') and expects instance.flag to return 'local'). Behavior is preserved: instance-level overrides still take precedence (instance ivar wins), and setting the instance ivar does not change the singleton class value.
1 parent 13d9709 commit 72d8359

2 files changed

Lines changed: 16 additions & 12 deletions

File tree

lib/injectable/class_methods.rb

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,26 @@ def simple_class_attribute(*attrs)
2828

2929
ivar = "@#{name}"
3030

31+
# Define the instance reader immediately when this attribute is declared
32+
# so instances always respond to the reader even if the singleton
33+
# class value has not been set yet.
34+
if singleton_class?
35+
class_eval do
36+
define_method(name) do
37+
if instance_variable_defined? ivar
38+
instance_variable_get ivar
39+
else
40+
singleton_class.send name
41+
end
42+
end
43+
end
44+
end
45+
3146
define_singleton_method("#{name}=") do |val|
3247
singleton_class.class_eval do
3348
define_method(name) { val }
3449
end
3550

36-
if singleton_class?
37-
class_eval do
38-
define_method(name) do
39-
if instance_variable_defined? ivar
40-
instance_variable_get ivar
41-
else
42-
singleton_class.send name
43-
end
44-
end
45-
end
46-
end
4751
val
4852
end
4953
end

spec/injectable/class_methods_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def call
2929
expect(instance.flag).to eq('on')
3030
end
3131

32-
it 'allows to modify attribute value on the instance', skip: 'Failing, need to investigate' do
32+
it 'allows to modify attribute value on the instance' do
3333
instance = klass.new
3434
instance.instance_variable_set('@flag', 'local')
3535
expect(instance.flag).to eq('local')

0 commit comments

Comments
 (0)