aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorMatthew Draper <matthew@trebex.net>2016-10-05 05:23:48 +1030
committerGitHub <noreply@github.com>2016-10-05 05:23:48 +1030
commit4d6feef79248a63c4cefde3f9ceb2242925e8d8d (patch)
tree83724eea7492b2ad61638c0bfa41c9b6411a3ad4 /activesupport
parent6ecb14715e4d5acb06c282b96b795404e25c7a11 (diff)
parente8b36e7711d44bf23a39426b3d766c08528573b3 (diff)
downloadrails-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.rb33
-rw-r--r--activesupport/test/executor_test.rb55
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)