mirror of https://github.com/rails/rails
Merge pull request #50677 from seanpdoyle/current-attributes-defaults
Add `default:` support for `ActiveSupport::CurrentAttributes.attribute`
This commit is contained in:
commit
1db9705396
|
@ -1,3 +1,13 @@
|
|||
* Add `default:` support for `ActiveSupport::CurrentAttributes.attribute`
|
||||
|
||||
```ruby
|
||||
class Current < ActiveSupport::CurrentAttributes
|
||||
attribute :counter, default: 0
|
||||
end
|
||||
```
|
||||
|
||||
*Sean Doyle*
|
||||
|
||||
* Yield instance to `Object#with` block
|
||||
|
||||
```ruby
|
||||
|
|
|
@ -102,7 +102,14 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
# Declares one or more attributes that will be given both class and instance accessor methods.
|
||||
def attribute(*names)
|
||||
#
|
||||
# ==== Options
|
||||
#
|
||||
# * <tt>:default</tt> - The default value for the attributes. If the value
|
||||
# is a proc or lambda, it will be called whenever an instance is
|
||||
# constructed. Otherwise, the value will be duplicated with +#dup+.
|
||||
# Default values are re-assigned when the attributes are reset.
|
||||
def attribute(*names, default: nil)
|
||||
invalid_attribute_names = names.map(&:to_sym) & INVALID_ATTRIBUTE_NAMES
|
||||
if invalid_attribute_names.any?
|
||||
raise ArgumentError, "Restricted attribute names: #{invalid_attribute_names.join(", ")}"
|
||||
|
@ -126,6 +133,8 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
singleton_class.delegate(*names.flat_map { |name| [name, "#{name}="] }, to: :instance, as: self)
|
||||
|
||||
defaults.merge! names.index_with { default }
|
||||
end
|
||||
|
||||
# Calls this callback before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
|
||||
|
@ -177,10 +186,12 @@ module ActiveSupport
|
|||
end
|
||||
end
|
||||
|
||||
class_attribute :defaults, instance_writer: false, default: {}
|
||||
|
||||
attr_accessor :attributes
|
||||
|
||||
def initialize
|
||||
@attributes = {}
|
||||
@attributes = merge_defaults!({})
|
||||
end
|
||||
|
||||
# Expose one or more attributes within a block. Old values are returned after the block concludes.
|
||||
|
@ -200,7 +211,20 @@ module ActiveSupport
|
|||
# Reset all attributes. Should be called before and after actions, when used as a per-request singleton.
|
||||
def reset
|
||||
run_callbacks :reset do
|
||||
self.attributes = {}
|
||||
self.attributes = merge_defaults!({})
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def merge_defaults!(attributes)
|
||||
defaults.each_with_object(attributes) do |(name, default), values|
|
||||
value =
|
||||
case default
|
||||
when Proc then default.call
|
||||
else default.dup
|
||||
end
|
||||
|
||||
values[name] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,6 +11,8 @@ class CurrentAttributesTest < ActiveSupport::TestCase
|
|||
Person = Struct.new(:id, :name, :time_zone)
|
||||
|
||||
class Current < ActiveSupport::CurrentAttributes
|
||||
attribute :counter_integer, default: 0
|
||||
attribute :counter_callable, default: -> { 0 }
|
||||
attribute :world, :account, :person, :request
|
||||
delegate :time_zone, to: :person
|
||||
|
||||
|
@ -86,6 +88,30 @@ class CurrentAttributesTest < ActiveSupport::TestCase
|
|||
assert_equal "world/1", Current.world
|
||||
end
|
||||
|
||||
test "read and write attribute with default value" do
|
||||
assert_equal 0, Current.counter_integer
|
||||
|
||||
Current.counter_integer += 1
|
||||
|
||||
assert_equal 1, Current.counter_integer
|
||||
|
||||
Current.reset
|
||||
|
||||
assert_equal 0, Current.counter_integer
|
||||
end
|
||||
|
||||
test "read attribute with default callable" do
|
||||
assert_equal 0, Current.counter_callable
|
||||
|
||||
Current.counter_callable += 1
|
||||
|
||||
assert_equal 1, Current.counter_callable
|
||||
|
||||
Current.reset
|
||||
|
||||
assert_equal 0, Current.counter_callable
|
||||
end
|
||||
|
||||
test "read overwritten attribute method" do
|
||||
Current.request = "request/1"
|
||||
assert_equal "request/1 something", Current.request
|
||||
|
|
Loading…
Reference in New Issue