Skip to content

Commit 49b8e70

Browse files
committed
Do not populate CurrentAttributes#attributes when not using defaults
When using `CurrentAttributes.attribute` without a default value, the `#attributes` method should not populate the hash with the attribute. Closes rails#52901.
1 parent 521030e commit 49b8e70

File tree

2 files changed

+11
-3
lines changed

2 files changed

+11
-3
lines changed

activesupport/lib/active_support/current_attributes.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ class CurrentAttributes
9595

9696
INVALID_ATTRIBUTE_NAMES = [:set, :reset, :resets, :instance, :before_reset, :after_reset, :reset_all, :clear_all] # :nodoc:
9797

98+
NOT_SET = Object.new.freeze # :nodoc:
99+
98100
class << self
99101
# Returns singleton instance for this class in this thread. If none exists, one is created.
100102
def instance
@@ -109,7 +111,7 @@ def instance
109111
# is a proc or lambda, it will be called whenever an instance is
110112
# constructed. Otherwise, the value will be duplicated with +#dup+.
111113
# Default values are re-assigned when the attributes are reset.
112-
def attribute(*names, default: nil)
114+
def attribute(*names, default: NOT_SET)
113115
invalid_attribute_names = names.map(&:to_sym) & INVALID_ATTRIBUTE_NAMES
114116
if invalid_attribute_names.any?
115117
raise ArgumentError, "Restricted attribute names: #{invalid_attribute_names.join(", ")}"
@@ -221,8 +223,10 @@ def reset
221223

222224
private
223225
def resolve_defaults
224-
defaults.transform_values do |value|
225-
Proc === value ? value.call : value.dup
226+
defaults.each_with_object({}) do |(key, value), result|
227+
if value != NOT_SET
228+
result[key] = Proc === value ? value.call : value.dup
229+
end
226230
end
227231
end
228232
end

activesupport/test/current_attributes_test.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ def after_teardown
247247
ActiveSupport::IsolatedExecutionState.isolation_level = previous_level
248248
end
249249

250+
test "CurrentAttributes doesn't populate #attributes when not using defaults" do
251+
assert_equal({ counter_integer: 0, counter_callable: 0 }, Current.attributes)
252+
end
253+
250254
test "CurrentAttributes restricted attribute names" do
251255
assert_raises ArgumentError, match: /Restricted attribute names: reset, set/ do
252256
class InvalidAttributeNames < ActiveSupport::CurrentAttributes

0 commit comments

Comments
 (0)