diff options
author | Matthew Draper <matthew@trebex.net> | 2016-10-05 05:23:48 +1030 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-05 05:23:48 +1030 |
commit | 4d6feef79248a63c4cefde3f9ceb2242925e8d8d (patch) | |
tree | 83724eea7492b2ad61638c0bfa41c9b6411a3ad4 /activesupport | |
parent | 6ecb14715e4d5acb06c282b96b795404e25c7a11 (diff) | |
parent | e8b36e7711d44bf23a39426b3d766c08528573b3 (diff) | |
download | rails-4d6feef79248a63c4cefde3f9ceb2242925e8d8d.tar.gz rails-4d6feef79248a63c4cefde3f9ceb2242925e8d8d.tar.bz2 rails-4d6feef79248a63c4cefde3f9ceb2242925e8d8d.zip |
Merge pull request #26684 from matthewd/executor-serial
Avoid bumping the class serial when invoking executor
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/lib/active_support/execution_wrapper.rb | 33 | ||||
-rw-r--r-- | activesupport/test/executor_test.rb | 55 |
2 files changed, 76 insertions, 12 deletions
diff --git a/activesupport/lib/active_support/execution_wrapper.rb b/activesupport/lib/active_support/execution_wrapper.rb index 4c8b03c9df..3384d12d5b 100644 --- a/activesupport/lib/active_support/execution_wrapper.rb +++ b/activesupport/lib/active_support/execution_wrapper.rb @@ -19,6 +19,23 @@ module ActiveSupport set_callback(:complete, *args, &block) end + class RunHook < Struct.new(:hook) # :nodoc: + def before(target) + hook_state = target.send(:hook_state) + hook_state[hook] = hook.run + end + end + + class CompleteHook < Struct.new(:hook) # :nodoc: + def before(target) + hook_state = target.send(:hook_state) + if hook_state.key?(hook) + hook.complete hook_state[hook] + end + end + alias after before + end + # Register an object to be invoked during both the +run+ and # +complete+ steps. # @@ -29,19 +46,11 @@ module ActiveSupport # invoked in that situation.) def self.register_hook(hook, outer: false) if outer - run_args = [prepend: true] - complete_args = [:after] + to_run RunHook.new(hook), prepend: true + to_complete :after, CompleteHook.new(hook) else - run_args = complete_args = [] - end - - to_run(*run_args) do - hook_state[hook] = hook.run - end - to_complete(*complete_args) do - if hook_state.key?(hook) - hook.complete hook_state[hook] - end + to_run RunHook.new(hook) + to_complete CompleteHook.new(hook) end end diff --git a/activesupport/test/executor_test.rb b/activesupport/test/executor_test.rb index 0b56ea008f..d409216206 100644 --- a/activesupport/test/executor_test.rb +++ b/activesupport/test/executor_test.rb @@ -158,6 +158,61 @@ class ExecutorTest < ActiveSupport::TestCase assert_equal :some_state, supplied_state end + def test_hook_insertion_order + invoked = [] + supplied_state = [] + + hook_class = Class.new do + attr_accessor :letter + + define_method(:initialize) do |letter| + self.letter = letter + end + + define_method(:run) do + invoked << :"run_#{letter}" + :"state_#{letter}" + end + + define_method(:complete) do |state| + invoked << :"complete_#{letter}" + supplied_state << state + end + end + + executor.register_hook(hook_class.new(:a)) + executor.register_hook(hook_class.new(:b)) + executor.register_hook(hook_class.new(:c), outer: true) + executor.register_hook(hook_class.new(:d)) + + executor.wrap {} + + assert_equal [:run_c, :run_a, :run_b, :run_d, :complete_a, :complete_b, :complete_d, :complete_c], invoked + assert_equal [:state_a, :state_b, :state_d, :state_c], supplied_state + end + + def test_class_serial_is_unaffected + hook = Class.new do + define_method(:run) do + nil + end + + define_method(:complete) do |state| + nil + end + end.new + + executor.register_hook(hook) + + before = RubyVM.stat(:class_serial) + executor.wrap {} + executor.wrap {} + executor.wrap {} + after = RubyVM.stat(:class_serial) + + assert_equal before, after + end + def test_separate_classes_can_wrap other_executor = Class.new(ActiveSupport::Executor) |