Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support on_*_entry, on_*_exit and implicit callback methods being private. #37

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/workflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,15 @@ def run_action(action, *args)
end

def run_action_callback(action_name, *args)
self.send action_name.to_sym, *args if self.respond_to?(action_name.to_sym)
self.send action_name.to_sym, *args if self.respond_to?(action_name.to_sym, true)
end

def run_on_entry(state, prior_state, triggering_event, *args)
if state.on_entry
instance_exec(prior_state.name, triggering_event, *args, &state.on_entry)
else
hook_name = "on_#{state}_entry"
self.send hook_name, prior_state, triggering_event, *args if self.respond_to? hook_name
self.send hook_name, prior_state, triggering_event, *args if self.respond_to?(hook_name, true)
end
end

Expand All @@ -268,7 +268,7 @@ def run_on_exit(state, new_state, triggering_event, *args)
instance_exec(new_state.name, triggering_event, *args, &state.on_exit)
else
hook_name = "on_#{state}_exit"
self.send hook_name, new_state, triggering_event, *args if self.respond_to? hook_name
self.send hook_name, new_state, triggering_event, *args if self.respond_to?(hook_name, true)
end
end
end
Expand Down
113 changes: 78 additions & 35 deletions test/main_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -253,22 +253,17 @@ def assert_state(title, expected_state, klass = Order)

test 'multiple events with the same name and different arguments lists from different states'

test 'implicit transition callback' do
test 'implicit transition callback with a public method' do
args = mock()
args.expects(:my_tran).once # this is validated at the end
c = Class.new
c.class_eval do
include Workflow
def my_transition(args)
args.my_tran
end
workflow do
state :one do
event :my_transition, :transitions_to => :two
end
state :two
end
end
c = transition_callback_class_with_public_method
c.new.my_transition!(args)
end

test 'implicit transition callback with a private method' do
args = mock()
args.expects(:my_tran).once # this is validated at the end
c = transition_callback_class_with_private_method
c.new.my_transition!(args)
end

Expand Down Expand Up @@ -343,29 +338,19 @@ class Problem
#
# If both a function with a name according to naming convention and the
# on_entry/on_exit block are given, then only on_entry/on_exit block is used.
test 'on_entry and on_exit hooks in separate methods' do
c = Class.new
c.class_eval do
include Workflow
attr_reader :history
def initialize
@history = []
end
workflow do
state :new do
event :next, :transitions_to => :next_state
end
state :next_state
end
test 'on_entry and on_exit hooks in separate public methods' do
c = on_entry_and_on_exit_hooks_class_with_public_methods

def on_next_state_entry(prior_state, event, *args)
@history << "on_next_state_entry #{event} #{prior_state} ->"
end
o = c.new
assert_equal 'new', o.current_state.to_s
assert_equal [], o.history
o.next!
assert_equal ['on_new_exit next -> next_state', 'on_next_state_entry next new ->'], o.history

def on_new_exit(new_state, event, *args)
@history << "on_new_exit #{event} -> #{new_state}"
end
end
end

test 'on_entry and on_exit hooks in separate private methods' do
c = on_entry_and_on_exit_hooks_class_with_private_methods

o = c.new
assert_equal 'new', o.current_state.to_s
Expand Down Expand Up @@ -479,5 +464,63 @@ def capture_streams
captured_stdout
end

def transition_callback_class_with_public_method
c = Class.new
c.class_eval do
include Workflow
def my_transition(args)
args.my_tran
end
workflow do
state :one do
event :my_transition, :transitions_to => :two
end
state :two
end
end
c
end

def transition_callback_class_with_private_method
c = transition_callback_class_with_public_method
c.class_eval { private :my_transition }
c
end

def on_entry_and_on_exit_hooks_class_with_public_methods
c = Class.new
c.class_eval do
include Workflow
attr_reader :history
def initialize
@history = []
end
workflow do
state :new do
event :next, :transitions_to => :next_state
end
state :next_state
end

def on_next_state_entry(prior_state, event, *args)
@history << "on_next_state_entry #{event} #{prior_state} ->"
end

def on_new_exit(new_state, event, *args)
@history << "on_new_exit #{event} -> #{new_state}"
end
end
c
end

def on_entry_and_on_exit_hooks_class_with_private_methods
c = on_entry_and_on_exit_hooks_class_with_public_methods
c.class_eval do
private :on_next_state_entry
private :on_new_exit
end
c
end

end