Skip to content

Commit

Permalink
Improve backward compatibility for #227 - let :if methods and procs…
Browse files Browse the repository at this point in the history
… ignore additional arguments

In case the method referenced by `:if` does not accept additional
arguments, but the transition action is called with some, avoid
exception "1 argument provided, but 0 were expected" by ignoring
superfluous arguments if needed.
  • Loading branch information
geekq committed May 29, 2024
1 parent 2529e30 commit 5e6849a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
12 changes: 11 additions & 1 deletion lib/workflow/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,18 @@ def initialize(name, transitions_to, condition = nil, meta = {}, &action)
def condition_applicable?(object, event_arguments)
if condition
if condition.is_a?(Symbol)
object.send(condition, *event_arguments)
m = object.method(condition)
# Conditionals can now take the arguments of the trasition action into account #227
# But in case the current conditional wants to ignore any event_argument on its decision -
# does not accept parameters, also support that.
if m.arity == 0 # no additional parameters accepted
object.send(condition)
else
object.send(condition, *event_arguments)
end
else
# since blocks can ignore extra arguments without raising an error in Ruby,
# no `if` is needed - compare with `arity` switch in above methods handling
condition.call(object, *event_arguments)
end
else
Expand Down
26 changes: 21 additions & 5 deletions test/conditionals_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def sufficient_battery_level?
assert device.on?
end

test 'gh-227 allow event arguments in conditions - test with proc' do
test 'gh-227 allow event arguments in conditions - test with a method' do
c = Class.new do
include Workflow
# define more advanced workflow, where event methods allow arguments
Expand All @@ -52,26 +52,36 @@ def sufficient_battery_level?
event :turn_on, :transitions_to => :on, :if => :sufficient_battery_level?
event :turn_on, :transitions_to => :low_battery # otherwise
end
state :on
state :on do
event :check, :transitions_to => :low_battery, :if => :check_low_battery?
event :check, :transitions_to => :on # stay in on state otherwise
end
state :low_battery
end
attr_reader :battery
def initialize(battery)
@battery = battery
end

def sufficient_battery_level?(power_adapter=false)
def sufficient_battery_level?(power_adapter)
power_adapter || @battery > 10
end

def check_low_battery?() # supports no arguments, lets test below, what happens if the action uses addtional args
# 'in check_low_battery? method'
end
end

# test for conditions in a proc
device = c.new 5
device.turn_on!(true) # case with event arguments to be taken into account
assert device.on?
device.check!('foo') # the conditional in the definition above does not support arguments, but make it work
# by ignoring superfluous arguments for compatibility
assert device.on?
end

test 'gh-227 allow event arguments in conditions - test with a method' do
test 'gh-227 allow event arguments in conditions - test with a proc' do
c = Class.new do
include Workflow
# define more advanced workflow, where event methods allow arguments
Expand All @@ -81,7 +91,10 @@ def sufficient_battery_level?(power_adapter=false)
event :turn_on, :transitions_to => :on, :if => proc { |obj, power_adapter| power_adapter || obj.battery > 10 }
event :turn_on, :transitions_to => :low_battery # otherwise
end
state :on
state :on do
event :check, :transitions_to => :low_battery, :if => proc { |obj| return false }
event :check, :transitions_to => :on # stay in on state otherwise
end
state :low_battery
end
attr_reader :battery
Expand All @@ -93,6 +106,9 @@ def initialize(battery)
device = c.new 5
device.turn_on!(true) # case with event arguments to be taken into account
assert device.on?
device.check!('foo') # also ensure that if conditional in the definition above does not support arguments,
# it still works and just ignores superfluous arguments
assert device.on?
end

end
Expand Down

0 comments on commit 5e6849a

Please sign in to comment.