提交 2ce8455c 编写于 作者: R Rosa Gutierrez

Support before_reset callback in CurrentAttributes

This is useful when we need to do some work associated to `Current.reset`
but that work depends on the values of the current attributes themselves.
This cannot be done in the supported `resets` callback because when the
block is executed, CurrentAttributes's instance has already been reset.

For symmetry, `after_reset` is defined as alias of `resets`.
上级 9bb07b79
* Add `before_reset` callback to `CurrentAttributes` and define `after_reset` as an alias of `resets` for symmetry.
*Rosa Gutierrez*
* Add `ActiveSupport::HashWithIndifferentAccess#assoc`.
`assoc` can now be called with either a string or a symbol.
*Stefan Schüßler*
## Rails 6.0.0.beta1 (January 18, 2019) ##
* Remove deprecated `Module#reachable?` method.
......
......@@ -119,10 +119,16 @@ def attribute(*names)
end
end
# Calls this block before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
def before_reset(&block)
set_callback :reset, :before, &block
end
# Calls this block after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
def resets(&block)
set_callback :reset, :after, &block
end
alias_method :after_reset, :resets
delegate :set, :reset, to: :instance
......
......@@ -3,13 +3,18 @@
require "abstract_unit"
class CurrentAttributesTest < ActiveSupport::TestCase
Person = Struct.new(:name, :time_zone)
Person = Struct.new(:id, :name, :time_zone)
class Current < ActiveSupport::CurrentAttributes
attribute :world, :account, :person, :request
delegate :time_zone, to: :person
resets { Time.zone = "UTC" }
before_reset { Session.previous = person.try(:id) }
resets do
Time.zone = "UTC"
Session.current = nil
end
def account=(account)
super
......@@ -19,6 +24,7 @@ def account=(account)
def person=(person)
super
Time.zone = person.try(:time_zone)
Session.current = person.try(:id)
end
def request
......@@ -30,9 +36,14 @@ def intro
end
end
class Session < ActiveSupport::CurrentAttributes
attribute :current, :previous
end
setup do
@original_time_zone = Time.zone
Current.reset
Session.reset
end
teardown do
......@@ -56,16 +67,28 @@ def intro
end
test "set auxiliary class via overwritten method" do
Current.person = Person.new("David", "Central Time (US & Canada)")
Current.person = Person.new(42, "David", "Central Time (US & Canada)")
assert_equal "Central Time (US & Canada)", Time.zone.name
assert_equal 42, Session.current
end
test "resets auxiliary class via callback" do
Current.person = Person.new("David", "Central Time (US & Canada)")
test "resets auxiliary classes via callback" do
Current.person = Person.new(42, "David", "Central Time (US & Canada)")
assert_equal "Central Time (US & Canada)", Time.zone.name
Current.reset
assert_equal "UTC", Time.zone.name
assert_nil Session.current
end
test "set auxiliary class based on current attributes via before callback" do
Current.person = Person.new(42, "David", "Central Time (US & Canada)")
assert_nil Session.previous
assert_equal 42, Session.current
Current.reset
assert_equal 42, Session.previous
assert_nil Session.current
end
test "set attribute only via scope" do
......@@ -92,13 +115,13 @@ def intro
end
test "delegation" do
Current.person = Person.new("David", "Central Time (US & Canada)")
Current.person = Person.new(42, "David", "Central Time (US & Canada)")
assert_equal "Central Time (US & Canada)", Current.time_zone
assert_equal "Central Time (US & Canada)", Current.instance.time_zone
end
test "all methods forward to the instance" do
Current.person = Person.new("David", "Central Time (US & Canada)")
Current.person = Person.new(42, "David", "Central Time (US & Canada)")
assert_equal "David, in Central Time (US & Canada)", Current.intro
assert_equal "David, in Central Time (US & Canada)", Current.instance.intro
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册