Skip to content

Commit b118f24

Browse files
committed
Merge PR gh-227 allow event arguments to be taken into account when selecting event; fix tests
2 parents 9cb38d2 + d53bd7e commit b118f24

File tree

7 files changed

+115
-46
lines changed

7 files changed

+115
-46
lines changed

README.adoc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,8 @@ When calling a `device.can_<fire_event>?` check, or attempting a `device.<event>
407407
* If an `:if` check is present, proceed if it evaluates to true, or drop to the next event.
408408
* If you've run out of events to check (eg. `battery_level == 0`), then the transition isn't possible.
409409
410+
You can also pass additional arguments, which can be evaluated by :if methods or procs. See examples in
411+
[conditionals_test.rb](test/conditionals_test.rb#L45)
410412
411413
### Advanced transition hooks
412414
@@ -513,6 +515,10 @@ end
513515
Changelog
514516
---------
515517
518+
=== New in the version 3.1.0
519+
520+
* gh-227 allow event arguments to be taken into account when selecting the event
521+
516522
=== New in the version 3.0.0
517523
518524
* gh-228 Support for Ruby 3 keyword args, provided by @agirling
@@ -552,7 +558,7 @@ integration with https://github.com/activeadmin/activeadmin[ActiveAdmin].
552558

553559
Author: Vladimir Dobriakov, <https://infrastructure-as-code.de>
554560

555-
Copyright (c) 2010-2022 Vladimir Dobriakov and Contributors
561+
Copyright (c) 2010-2024 Vladimir Dobriakov and Contributors
556562

557563
Copyright (c) 2008-2009 Vodafone
558564

lib/workflow.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ def assign_workflow(specification_object)
6565
process_event!(event_name, *args, **kwargs)
6666
end
6767

68-
define_method "can_#{event_name}?" do
69-
return !!current_state.events.first_applicable(event_name, self)
68+
define_method "can_#{event_name}?".to_sym do |*args, **kwargs|
69+
return !!current_state.events.first_applicable(event_name, self, args)
7070
end
7171
end
7272
end
@@ -95,7 +95,7 @@ def halted_because
9595
end
9696

9797
def process_event!(name, *args, **kwargs)
98-
event = current_state.events.first_applicable(name, self)
98+
event = current_state.events.first_applicable(name, self, args)
9999
raise NoTransitionAllowed.new(
100100
"There is no event #{name.to_sym} defined for the #{current_state} state") \
101101
if event.nil?

lib/workflow/event.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ def initialize(name, transitions_to, condition = nil, meta = {}, &action)
1515
end
1616
end
1717

18-
def condition_applicable?(object)
18+
def condition_applicable?(object, event_arguments)
1919
if condition
2020
if condition.is_a?(Symbol)
21-
object.send(condition)
21+
object.send(condition, *event_arguments)
2222
else
23-
condition.call(object)
23+
condition.call(object, *event_arguments)
2424
end
2525
else
2626
true

lib/workflow/event_collection.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ def include?(name_or_obj)
2626
end
2727
end
2828

29-
def first_applicable(name, object_context)
29+
def first_applicable(name, object_context, event_arguments)
3030
(self[name] || []).detect do |event|
31-
event.condition_applicable?(object_context) && event
31+
event.condition_applicable?(object_context, event_arguments) && event
3232
end
3333
end
3434

lib/workflow/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module Workflow
2-
VERSION = "3.0.0"
2+
VERSION = "3.1.0"
33
end

test/conditionals_test.rb

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
require File.join(File.dirname(__FILE__), 'test_helper')
2+
3+
$VERBOSE = false
4+
require 'workflow'
5+
require 'mocha/minitest'
6+
7+
class ConditionalsTest < Minitest::Test
8+
9+
test 'can_<fire_event>? with conditions' do
10+
c = Class.new do
11+
include Workflow
12+
workflow do
13+
state :off do
14+
event :turn_on, :transitions_to => :on, :if => :sufficient_battery_level?
15+
event :turn_on, :transitions_to => :low_battery, :if => proc { |obj| obj.battery > 0 }
16+
end
17+
state :on
18+
state :low_battery
19+
end
20+
attr_reader :battery
21+
def initialize(battery)
22+
@battery = battery
23+
end
24+
25+
def sufficient_battery_level?
26+
@battery > 10
27+
end
28+
end
29+
30+
device = c.new 0
31+
assert_equal false, device.can_turn_on?
32+
33+
device = c.new 5
34+
assert device.can_turn_on?
35+
device.turn_on!
36+
assert device.low_battery?
37+
assert_equal false, device.on?
38+
39+
device = c.new 50
40+
assert device.can_turn_on?
41+
device.turn_on!
42+
assert device.on?
43+
end
44+
45+
test 'gh-227 allow event arguments in conditions - test with proc' do
46+
c = Class.new do
47+
include Workflow
48+
# define more advanced workflow, where event methods allow arguments
49+
workflow do
50+
state :off do
51+
# turn_on accepts additional argument `power_adapter`
52+
event :turn_on, :transitions_to => :on, :if => :sufficient_battery_level?
53+
event :turn_on, :transitions_to => :low_battery # otherwise
54+
end
55+
state :on
56+
state :low_battery
57+
end
58+
attr_reader :battery
59+
def initialize(battery)
60+
@battery = battery
61+
end
62+
63+
def sufficient_battery_level?(power_adapter=false)
64+
power_adapter || @battery > 10
65+
end
66+
end
67+
68+
# test for conditions in a proc
69+
device = c.new 5
70+
device.turn_on!(true) # case with event arguments to be taken into account
71+
assert device.on?
72+
end
73+
74+
test 'gh-227 allow event arguments in conditions - test with a method' do
75+
c = Class.new do
76+
include Workflow
77+
# define more advanced workflow, where event methods allow arguments
78+
workflow do
79+
state :off do
80+
# turn_on accepts additional argument `power_adapter`
81+
event :turn_on, :transitions_to => :on, :if => proc { |obj, power_adapter| power_adapter || obj.battery > 10 }
82+
event :turn_on, :transitions_to => :low_battery # otherwise
83+
end
84+
state :on
85+
state :low_battery
86+
end
87+
attr_reader :battery
88+
def initialize(battery)
89+
@battery = battery
90+
end
91+
end
92+
93+
device = c.new 5
94+
device.turn_on!(true) # case with event arguments to be taken into account
95+
assert device.on?
96+
end
97+
98+
end
99+

test/main_test.rb

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -328,42 +328,6 @@ def reject(reason)
328328
assert_equal false, human.can_go_to_college?
329329
end
330330

331-
test 'can_<fire_event>? with conditions' do
332-
c = Class.new do
333-
include Workflow
334-
workflow do
335-
state :off do
336-
event :turn_on, :transitions_to => :on, :if => :sufficient_battery_level?
337-
event :turn_on, :transitions_to => :low_battery, :if => proc { |obj| obj.battery > 0 }
338-
end
339-
state :on
340-
state :low_battery
341-
end
342-
attr_reader :battery
343-
def initialize(battery)
344-
@battery = battery
345-
end
346-
347-
def sufficient_battery_level?
348-
@battery > 10
349-
end
350-
end
351-
352-
device = c.new 0
353-
assert_equal false, device.can_turn_on?
354-
355-
device = c.new 5
356-
assert device.can_turn_on?
357-
device.turn_on!
358-
assert device.low_battery?
359-
assert_equal false, device.on?
360-
361-
device = c.new 50
362-
assert device.can_turn_on?
363-
device.turn_on!
364-
assert device.on?
365-
end
366-
367331
test 'workflow graph generation' do
368332
require 'workflow/draw'
369333
Dir.chdir('/tmp') do

0 commit comments

Comments
 (0)