Skip to content

Commit e34b6f5

Browse files
Edouard-chinbyroot
andcommitted
Fix CurrentAttributes not setting an attribute's default:
- Fix rails#54636 - ### Problem When calling an attribute that has a default, `nil` would be returned instead. ### Context CurrentAttributes uses a cache to store each CurrentAttributes subclasses instance. When the class method `instance` gets called, we instantiate the class and populate the cache. The defaults of each attributes are set when the class is instantiated. This basically means that once we instantiate the class, all attribute having a default would be ignored. ### Details CurrentAttributes has a `method_added` hook which also call the `instance` class method. So depending on how your class is setup (e.g. you define a method and then define an attribute with a default), you'd hit the bug. This is even more sneaky when using a `delgate_to`: ```ruby class Current < CurrentAttributes attribute :user_session delegate :user, to: :user_session # Ends up triggering the `method_added` hook attribute :foo, default: 0 # Default would be ignored. end ``` ### Solution CurrentAttribute: avoid creating the instance in `method_added` hook. Co-authored-by: Jean Boussier <[email protected]>
1 parent a72205e commit e34b6f5

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

activesupport/lib/active_support/current_attributes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def method_added(name)
187187
super
188188
return if name == :initialize
189189
return unless public_method_defined?(name)
190-
return if respond_to?(name, true)
190+
return if singleton_class.method_defined?(name) || singleton_class.private_method_defined?(name)
191191
Delegation.generate(singleton_class, [name], to: :instance, as: self, nilable: false)
192192
end
193193
end

activesupport/test/current_attributes_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,4 +262,18 @@ class InvalidAttributeNames < ActiveSupport::CurrentAttributes
262262
end
263263
end
264264
end
265+
266+
test "method_added hook doesn't reach the instance. Fix for #54646" do
267+
current = Class.new(ActiveSupport::CurrentAttributes) do
268+
def self.name
269+
"MyCurrent"
270+
end
271+
272+
def foo; end # Sets the cache because of a `method_added` hook
273+
274+
attribute :bar, default: {}
275+
end
276+
277+
assert_instance_of(Hash, current.bar)
278+
end
265279
end

0 commit comments

Comments
 (0)