mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #27368 from matthewd/doubled-callbacks
Support double-yield inside an around callback
This commit is contained in:
commit
a47efcfcae
2 changed files with 77 additions and 18 deletions
|
@ -109,16 +109,22 @@ module ActiveSupport
|
||||||
invoke_sequence = Proc.new do
|
invoke_sequence = Proc.new do
|
||||||
skipped = nil
|
skipped = nil
|
||||||
while true
|
while true
|
||||||
current, next_sequence = next_sequence, next_sequence.nested
|
current = next_sequence
|
||||||
current.invoke_before(env)
|
current.invoke_before(env)
|
||||||
if current.final?
|
if current.final?
|
||||||
env.value = !env.halted && (!block_given? || yield)
|
env.value = !env.halted && (!block_given? || yield)
|
||||||
elsif current.skip?(env)
|
elsif current.skip?(env)
|
||||||
(skipped ||= []) << current
|
(skipped ||= []) << current
|
||||||
|
next_sequence = next_sequence.nested
|
||||||
next
|
next
|
||||||
else
|
else
|
||||||
|
next_sequence = next_sequence.nested
|
||||||
|
begin
|
||||||
target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
|
target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
|
||||||
target.send(method, *arguments, &block)
|
target.send(method, *arguments, &block)
|
||||||
|
ensure
|
||||||
|
next_sequence = current
|
||||||
|
end
|
||||||
end
|
end
|
||||||
current.invoke_after(env)
|
current.invoke_after(env)
|
||||||
skipped.pop.invoke_after(env) while skipped && skipped.first
|
skipped.pop.invoke_after(env) while skipped && skipped.first
|
||||||
|
|
|
@ -224,10 +224,51 @@ module CallbacksTest
|
||||||
define_callbacks :save
|
define_callbacks :save
|
||||||
end
|
end
|
||||||
|
|
||||||
class AroundPerson < MySuper
|
class MySlate < MySuper
|
||||||
attr_reader :history
|
attr_reader :history
|
||||||
attr_accessor :save_fails
|
attr_accessor :save_fails
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@history = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def save
|
||||||
|
run_callbacks :save do
|
||||||
|
raise "inside save" if save_fails
|
||||||
|
@history << "running"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def no; false; end
|
||||||
|
def yes; true; end
|
||||||
|
|
||||||
|
def method_missing(sym, *)
|
||||||
|
case sym
|
||||||
|
when /^log_(.*)/
|
||||||
|
@history << $1
|
||||||
|
nil
|
||||||
|
when /^wrap_(.*)/
|
||||||
|
@history << "wrap_#$1"
|
||||||
|
yield
|
||||||
|
@history << "unwrap_#$1"
|
||||||
|
nil
|
||||||
|
when /^double_(.*)/
|
||||||
|
@history << "first_#$1"
|
||||||
|
yield
|
||||||
|
@history << "second_#$1"
|
||||||
|
yield
|
||||||
|
@history << "third_#$1"
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def respond_to_missing?(sym)
|
||||||
|
sym =~ /^(log|wrap)_/ || super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class AroundPerson < MySlate
|
||||||
set_callback :save, :before, :nope, if: :no
|
set_callback :save, :before, :nope, if: :no
|
||||||
set_callback :save, :before, :nope, unless: :yes
|
set_callback :save, :before, :nope, unless: :yes
|
||||||
set_callback :save, :after, :tweedle
|
set_callback :save, :after, :tweedle
|
||||||
|
@ -242,9 +283,6 @@ module CallbacksTest
|
||||||
set_callback :save, :around, :w0tno, if: :no
|
set_callback :save, :around, :w0tno, if: :no
|
||||||
set_callback :save, :around, :tweedle_deedle
|
set_callback :save, :around, :tweedle_deedle
|
||||||
|
|
||||||
def no; false; end
|
|
||||||
def yes; true; end
|
|
||||||
|
|
||||||
def nope
|
def nope
|
||||||
@history << "boom"
|
@history << "boom"
|
||||||
end
|
end
|
||||||
|
@ -283,17 +321,6 @@ module CallbacksTest
|
||||||
yield
|
yield
|
||||||
@history << "tweedle deedle post"
|
@history << "tweedle deedle post"
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize
|
|
||||||
@history = []
|
|
||||||
end
|
|
||||||
|
|
||||||
def save
|
|
||||||
run_callbacks :save do
|
|
||||||
raise "inside save" if save_fails
|
|
||||||
@history << "running"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class AroundPersonResult < MySuper
|
class AroundPersonResult < MySuper
|
||||||
|
@ -408,6 +435,32 @@ module CallbacksTest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class DoubleYieldTest < ActiveSupport::TestCase
|
||||||
|
class DoubleYieldModel < MySlate
|
||||||
|
set_callback :save, :around, :wrap_outer
|
||||||
|
set_callback :save, :around, :double_trouble
|
||||||
|
set_callback :save, :around, :wrap_inner
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_double_save
|
||||||
|
double = DoubleYieldModel.new
|
||||||
|
double.save
|
||||||
|
assert_equal [
|
||||||
|
"wrap_outer",
|
||||||
|
"first_trouble",
|
||||||
|
"wrap_inner",
|
||||||
|
"running",
|
||||||
|
"unwrap_inner",
|
||||||
|
"second_trouble",
|
||||||
|
"wrap_inner",
|
||||||
|
"running",
|
||||||
|
"unwrap_inner",
|
||||||
|
"third_trouble",
|
||||||
|
"unwrap_outer",
|
||||||
|
], double.history
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class CallStackTest < ActiveSupport::TestCase
|
class CallStackTest < ActiveSupport::TestCase
|
||||||
def test_tidy_call_stack
|
def test_tidy_call_stack
|
||||||
around = AroundPerson.new
|
around = AroundPerson.new
|
||||||
|
|
Loading…
Reference in a new issue