simply_fsm 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +48 -16
- data/lib/simply_fsm/version.rb +1 -1
- data/lib/simply_fsm.rb +104 -14
- data/spec/unit/fail_events_spec.rb +3 -3
- data/spec/unit/guard_events_spec.rb +6 -6
- data/spec/unit/multi_transition_state_machine_spec.rb +87 -0
- data/spec/unit/one_state_machine_spec.rb +3 -3
- data/spec/unit/two_state_machines_spec.rb +4 -4
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eb54d24c49d69bc4cb382e6c4181a586fe9eef471dd1e44bcef0d95555fb33ae
|
|
4
|
+
data.tar.gz: 2f336e971e10827c1b731948376b4f2a177e012093c3f66457380df21c0f110c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9afdd28a4281a6d6c4d40abe7d52e5ab674e9bf1e626a9bc2bf47ee678e047f0fd3c4e5ab3f6857a01fc6fd6647a5eab416a6cc1c03f7ebbbdda1a72b6b1d71b
|
|
7
|
+
data.tar.gz: 21c938cbced1efb61d61c0cc62c4887d1f8084c4b42c6bc2effd0cda358a9cbade73a958250fdb9d81a17a183ed2b092e7d6896ae043fc1dfcc2afa7c9914134
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
- None right now
|
|
4
4
|
|
|
5
|
+
## [0.2.0] - 2022-03-01
|
|
6
|
+
|
|
7
|
+
- *Breaks API* (sorry!)
|
|
8
|
+
- When declaring events in a state machine, use `transitions:` (as in "transitions from X to Y") instead of `transition:`
|
|
9
|
+
- Added support for multiple transitions per event
|
|
10
|
+
|
|
5
11
|
## [0.1.2] - 2022-02-28
|
|
6
12
|
|
|
7
13
|
- Cleaned up source with smaller clearer methods
|
data/README.md
CHANGED
|
@@ -13,6 +13,7 @@ If you need storage/persistence/Rails/etc support, I recommend [AASM](https://gi
|
|
|
13
13
|
- [Multiple state machines](#multiple-state-machines)
|
|
14
14
|
- [Handle failed events](#handle-failed-events)
|
|
15
15
|
- [Guarding events](#guarding-events)
|
|
16
|
+
- [Multiple transitions for an event](#multiple-transitions-for-an-event)
|
|
16
17
|
- [Development](#development)
|
|
17
18
|
- [Contributing](#contributing)
|
|
18
19
|
- [License](#license)
|
|
@@ -49,15 +50,15 @@ class Job
|
|
|
49
50
|
state :running
|
|
50
51
|
state :cleaning
|
|
51
52
|
|
|
52
|
-
event :run,
|
|
53
|
+
event :run, transitions: { from: :sleeping, to: :running } do
|
|
53
54
|
# executed when transition succeeds
|
|
54
55
|
end
|
|
55
56
|
|
|
56
|
-
event :clean,
|
|
57
|
+
event :clean, transitions: { from: :running, to: :cleaning } do
|
|
57
58
|
# do the cleaning since transition succeeded
|
|
58
59
|
end
|
|
59
60
|
|
|
60
|
-
event :sleep,
|
|
61
|
+
event :sleep, transitions: { from: [:running, :cleaning], to: :sleeping }
|
|
61
62
|
end
|
|
62
63
|
end
|
|
63
64
|
```
|
|
@@ -88,16 +89,16 @@ class Player
|
|
|
88
89
|
state :idling, initial: true
|
|
89
90
|
state :walking
|
|
90
91
|
|
|
91
|
-
event :idle,
|
|
92
|
-
event :walk,
|
|
92
|
+
event :idle, transitions: { from: :any, to: :idling }
|
|
93
|
+
event :walk, transitions: { from: :idling, to: :walking }
|
|
93
94
|
end
|
|
94
95
|
|
|
95
96
|
state_machine :action do
|
|
96
97
|
state :ready, initial: true
|
|
97
98
|
state :blocking
|
|
98
99
|
|
|
99
|
-
event :hold,
|
|
100
|
-
event :block,
|
|
100
|
+
event :hold, transitions: { from: :any, to: :ready }
|
|
101
|
+
event :block, transitions: { from: :any, to: :blocking }
|
|
101
102
|
end
|
|
102
103
|
end
|
|
103
104
|
```
|
|
@@ -126,11 +127,11 @@ class JobWithErrors
|
|
|
126
127
|
state :running
|
|
127
128
|
state :cleaning
|
|
128
129
|
|
|
129
|
-
event :sleep,
|
|
130
|
-
event :clean,
|
|
130
|
+
event :sleep, transitions: { from: %i[running cleaning], to: :sleeping }
|
|
131
|
+
event :clean, transitions: { from: :running, to: :cleaning }
|
|
131
132
|
event :run,
|
|
132
133
|
fail: ->(_event) { raise RunError, "Cannot run" },
|
|
133
|
-
|
|
134
|
+
transitions: { from: :sleeping, to: :running }
|
|
134
135
|
end
|
|
135
136
|
|
|
136
137
|
def on_any_fail(event_name)
|
|
@@ -154,9 +155,9 @@ class AgilePlayer
|
|
|
154
155
|
state :walking
|
|
155
156
|
state :running
|
|
156
157
|
|
|
157
|
-
event :idle,
|
|
158
|
-
event :walk,
|
|
159
|
-
event :run,
|
|
158
|
+
event :idle, transitions: { from: :any, to: :idling }
|
|
159
|
+
event :walk, transitions: { from: :any, to: :walking }
|
|
160
|
+
event :run, transitions: { from: :any, to: :running }
|
|
160
161
|
end
|
|
161
162
|
|
|
162
163
|
state_machine :action do
|
|
@@ -164,14 +165,45 @@ class AgilePlayer
|
|
|
164
165
|
state :jumping
|
|
165
166
|
state :leaping
|
|
166
167
|
|
|
167
|
-
event :hold,
|
|
168
|
+
event :hold, transitions: { from: :any, to: :ready }
|
|
168
169
|
event :jump,
|
|
169
170
|
guard: -> { !running? },
|
|
170
|
-
|
|
171
|
+
transitions: { from: :ready, to: :jumping }
|
|
171
172
|
event :leap,
|
|
172
173
|
guard: -> { running? },
|
|
173
174
|
fail: ->(_event) { raise LeapError, "Cannot leap" },
|
|
174
|
-
|
|
175
|
+
transitions: { from: :ready, to: :leaping }
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
```
|
|
179
|
+
### Multiple transitions for an event
|
|
180
|
+
|
|
181
|
+
Sometimes a single event can transition to different end states based on different input states. In those situations you can specify an array of transitions. Consider the following example where the `hunt` event transitions to `walking` or `running` depending on some condition outside the state machine.
|
|
182
|
+
|
|
183
|
+
```ruby
|
|
184
|
+
class Critter
|
|
185
|
+
include SimplyFSM
|
|
186
|
+
|
|
187
|
+
def tired?
|
|
188
|
+
@ate_at <= 12.hours.ago || @slept_at <= 24.hours.ago
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
state_machine :activity do
|
|
192
|
+
state :sleeping, initial: true
|
|
193
|
+
state :running
|
|
194
|
+
state :walking
|
|
195
|
+
state :eating
|
|
196
|
+
|
|
197
|
+
event :eat, transitions: { to: :eating } do
|
|
198
|
+
@ate_at = DateTime.new
|
|
199
|
+
end
|
|
200
|
+
event :sleep, transitions: { from: :eating, to: :sleeping } do
|
|
201
|
+
@slept_at = DateTime.new
|
|
202
|
+
end
|
|
203
|
+
event :hunt, transitions: [
|
|
204
|
+
{ when: -> { tired? }, to: :walking },
|
|
205
|
+
{ to: :running }
|
|
206
|
+
]
|
|
175
207
|
end
|
|
176
208
|
end
|
|
177
209
|
```
|
data/lib/simply_fsm/version.rb
CHANGED
data/lib/simply_fsm.rb
CHANGED
|
@@ -9,6 +9,17 @@ module SimplyFSM
|
|
|
9
9
|
base.extend(ClassMethods)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
def state_match?(from, current)
|
|
13
|
+
return true if from == :any
|
|
14
|
+
return from.include?(current) if from.is_a?(Array)
|
|
15
|
+
|
|
16
|
+
from == current
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def cannot_transition?(from, cond, current)
|
|
20
|
+
(from && !state_match?(from, current)) || (cond && !instance_exec(&cond))
|
|
21
|
+
end
|
|
22
|
+
|
|
12
23
|
##
|
|
13
24
|
# Defines the constructor for defining a state machine
|
|
14
25
|
module ClassMethods
|
|
@@ -55,19 +66,29 @@ module SimplyFSM
|
|
|
55
66
|
end
|
|
56
67
|
|
|
57
68
|
##
|
|
58
|
-
# Define an event by +event_name+
|
|
59
|
-
#
|
|
69
|
+
# Define an event by +event_name+
|
|
70
|
+
#
|
|
71
|
+
# - which +transitions+ as a hash with a +from+ state or array of states and the +to+ state,
|
|
60
72
|
# - an optional +guard+ lambda which must return true for the transition to occur,
|
|
61
73
|
# - an optional +fail+ lambda that is called when the transition fails (overrides top-level fail handler), and
|
|
62
74
|
# - an optional do block that is called +after+ the transition succeeds
|
|
63
|
-
def event(event_name,
|
|
64
|
-
return unless event_exists?(event_name) &&
|
|
75
|
+
def event(event_name, transitions:, guard: nil, fail: nil, &after)
|
|
76
|
+
return unless event_exists?(event_name) && transitions
|
|
65
77
|
|
|
66
78
|
@events << event_name
|
|
67
|
-
to = transition[:to]
|
|
68
79
|
may_event_name = "may_#{event_name}?"
|
|
69
80
|
|
|
70
|
-
|
|
81
|
+
if transitions.is_a?(Array)
|
|
82
|
+
setup_multi_transition_may_event_method transitions: transitions, guard: guard,
|
|
83
|
+
may_event_name: may_event_name
|
|
84
|
+
setup_multi_transition_event_method event_name,
|
|
85
|
+
transitions: transitions, guard: guard,
|
|
86
|
+
var_name: "@#{@name}", fail: fail || @fail_handler
|
|
87
|
+
return
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
to = transitions[:to]
|
|
91
|
+
setup_may_event_method may_event_name, transitions[:from] || :any, transitions[:when], guard
|
|
71
92
|
setup_event_method event_name, var_name: "@#{@name}",
|
|
72
93
|
may_event_name: may_event_name, to: to,
|
|
73
94
|
fail: fail || @fail_handler, &after
|
|
@@ -75,6 +96,41 @@ module SimplyFSM
|
|
|
75
96
|
|
|
76
97
|
private
|
|
77
98
|
|
|
99
|
+
def setup_multi_transition_may_event_method(transitions:, guard:, may_event_name:)
|
|
100
|
+
state_machine_name = @name
|
|
101
|
+
|
|
102
|
+
make_owner_method may_event_name, lambda {
|
|
103
|
+
if !guard || instance_exec(&guard)
|
|
104
|
+
current = send(state_machine_name)
|
|
105
|
+
# Check each transition, and first one that succeeds ends the scan
|
|
106
|
+
transitions.each do |t|
|
|
107
|
+
next if cannot_transition?(t[:from], t[:when], current)
|
|
108
|
+
|
|
109
|
+
return true
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
false
|
|
113
|
+
}
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def setup_multi_transition_event_method(event_name, transitions:, guard:, var_name:, fail:)
|
|
117
|
+
state_machine_name = @name
|
|
118
|
+
make_owner_method event_name, lambda {
|
|
119
|
+
if !guard || instance_exec(&guard)
|
|
120
|
+
current = send(state_machine_name)
|
|
121
|
+
# Check each transition, and first one that succeeds ends the scan
|
|
122
|
+
transitions.each do |t|
|
|
123
|
+
next if cannot_transition?(t[:from], t[:when], current)
|
|
124
|
+
|
|
125
|
+
instance_variable_set(var_name, t[:to])
|
|
126
|
+
return true
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
instance_exec(&fail) if fail
|
|
130
|
+
false
|
|
131
|
+
}
|
|
132
|
+
end
|
|
133
|
+
|
|
78
134
|
def event_exists?(event_name)
|
|
79
135
|
event_name && !@events.include?(event_name)
|
|
80
136
|
end
|
|
@@ -99,23 +155,43 @@ module SimplyFSM
|
|
|
99
155
|
make_owner_method event_name, method_lambda
|
|
100
156
|
end
|
|
101
157
|
|
|
102
|
-
def setup_may_event_method(may_event_name, from,
|
|
158
|
+
def setup_may_event_method(may_event_name, from, cond, guard)
|
|
103
159
|
state_machine_name = @name
|
|
104
160
|
#
|
|
105
161
|
# Instead of one "may_event?" method that checks all variations every time it's called, here we check
|
|
106
162
|
# the event definition and define the most optimal lambda to ensure the check is as fast as possible
|
|
107
|
-
method_lambda = if from == :any
|
|
108
|
-
|
|
109
|
-
elsif from == :any
|
|
110
|
-
guard # guarded transition from any state
|
|
111
|
-
elsif !guard
|
|
112
|
-
guardless_may_event_lambda(from, state_machine_name)
|
|
163
|
+
method_lambda = if from == :any
|
|
164
|
+
from_any_may_event_lambda(guard, cond, state_machine_name)
|
|
113
165
|
else
|
|
114
|
-
|
|
166
|
+
guarded_or_conditional_may_event_lambda(from, guard, cond, state_machine_name)
|
|
115
167
|
end
|
|
116
168
|
make_owner_method may_event_name, method_lambda
|
|
117
169
|
end
|
|
118
170
|
|
|
171
|
+
def from_any_may_event_lambda(guard, cond, _state_machine_name)
|
|
172
|
+
if !guard && !cond
|
|
173
|
+
-> { true } # unguarded transition from any state
|
|
174
|
+
elsif !cond
|
|
175
|
+
guard # guarded transition from any state
|
|
176
|
+
elsif !guard
|
|
177
|
+
cond # conditional unguarded transition from any state
|
|
178
|
+
else
|
|
179
|
+
-> { instance_exec(&guard) && instance_exec(&cond) }
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def guarded_or_conditional_may_event_lambda(from, guard, cond, state_machine_name)
|
|
184
|
+
if !guard && !cond
|
|
185
|
+
guardless_may_event_lambda(from, state_machine_name)
|
|
186
|
+
elsif !cond
|
|
187
|
+
guarded_may_event_lambda(from, guard, state_machine_name)
|
|
188
|
+
elsif !guard
|
|
189
|
+
guarded_may_event_lambda(from, cond, state_machine_name)
|
|
190
|
+
else
|
|
191
|
+
guarded_and_conditional_may_event_lambda(from, guard, cond, state_machine_name)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
119
195
|
def guarded_may_event_lambda(from, guard, state_machine_name)
|
|
120
196
|
if from.is_a?(Array)
|
|
121
197
|
lambda { # guarded transition from choice of states
|
|
@@ -130,6 +206,20 @@ module SimplyFSM
|
|
|
130
206
|
end
|
|
131
207
|
end
|
|
132
208
|
|
|
209
|
+
def guarded_and_conditional_may_event_lambda(from, guard, cond, state_machine_name)
|
|
210
|
+
if from.is_a?(Array)
|
|
211
|
+
lambda { # guarded transition from choice of states
|
|
212
|
+
current = send(state_machine_name)
|
|
213
|
+
from.include?(current) && instance_exec(&guard) && instance_exec(&cond)
|
|
214
|
+
}
|
|
215
|
+
else
|
|
216
|
+
lambda { # guarded transition from one state
|
|
217
|
+
current = send(state_machine_name)
|
|
218
|
+
from == current && instance_exec(&guard) && instance_exec(&cond)
|
|
219
|
+
}
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
133
223
|
def guardless_may_event_lambda(from, state_machine_name)
|
|
134
224
|
if from.is_a?(Array)
|
|
135
225
|
lambda { # unguarded transition from choice of states
|
|
@@ -11,11 +11,11 @@ class FailHandlingStateMachine
|
|
|
11
11
|
state :running
|
|
12
12
|
state :cleaning
|
|
13
13
|
|
|
14
|
-
event :sleep,
|
|
15
|
-
event :clean,
|
|
14
|
+
event :sleep, transitions: { from: %i[running cleaning], to: :sleeping }
|
|
15
|
+
event :clean, transitions: { from: :running, to: :cleaning }
|
|
16
16
|
event :run,
|
|
17
17
|
fail: ->(_event) { raise RunError, "Cannot run" },
|
|
18
|
-
|
|
18
|
+
transitions: { from: :sleeping, to: :running }
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def on_any_fail(event_name)
|
|
@@ -10,9 +10,9 @@ class GuardingEvents
|
|
|
10
10
|
state :walking
|
|
11
11
|
state :running
|
|
12
12
|
|
|
13
|
-
event :idle,
|
|
14
|
-
event :walk,
|
|
15
|
-
event :run,
|
|
13
|
+
event :idle, transitions: { to: :idling }
|
|
14
|
+
event :walk, transitions: { from: :any, to: :walking }
|
|
15
|
+
event :run, transitions: { from: :any, to: :running }
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
state_machine :action do
|
|
@@ -20,14 +20,14 @@ class GuardingEvents
|
|
|
20
20
|
state :jumping
|
|
21
21
|
state :leaping
|
|
22
22
|
|
|
23
|
-
event :hold,
|
|
23
|
+
event :hold, transitions: { to: :ready }
|
|
24
24
|
event :jump,
|
|
25
25
|
guard: -> { !running? },
|
|
26
|
-
|
|
26
|
+
transitions: { from: :ready, to: :jumping }
|
|
27
27
|
event :leap,
|
|
28
28
|
guard: -> { running? },
|
|
29
29
|
fail: ->(_event) { raise LeapError, "Cannot leap" },
|
|
30
|
-
|
|
30
|
+
transitions: { when: -> { ready? }, to: :leaping }
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class MultiTransitionStateMachine
|
|
4
|
+
include SimplyFSM
|
|
5
|
+
|
|
6
|
+
state_machine :activity do
|
|
7
|
+
state :sleeping, initial: true
|
|
8
|
+
state :running
|
|
9
|
+
state :cleaning
|
|
10
|
+
|
|
11
|
+
event :run, transitions: { from: :sleeping, to: :running }
|
|
12
|
+
|
|
13
|
+
event :clean, transitions: [
|
|
14
|
+
{ from: :running, to: :cleaning }
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
event :sleep, transitions: [
|
|
18
|
+
{ from: :running, to: :sleeping },
|
|
19
|
+
{ when: -> { cleaning? }, to: :sleeping }
|
|
20
|
+
]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
RSpec.describe MultiTransitionStateMachine do
|
|
25
|
+
include_examples "state machine basics", :activity,
|
|
26
|
+
initial_state: :sleeping,
|
|
27
|
+
states: %i[sleeping running cleaning],
|
|
28
|
+
events: %i[run clean sleep]
|
|
29
|
+
|
|
30
|
+
describe "#sleep" do
|
|
31
|
+
it "fails if already sleeping" do
|
|
32
|
+
expect(subject.may_sleep?).to be false
|
|
33
|
+
expect(subject.sleep).to be false
|
|
34
|
+
end
|
|
35
|
+
it "succeeds if running" do
|
|
36
|
+
subject.run
|
|
37
|
+
expect(subject.may_sleep?).to be true
|
|
38
|
+
expect(subject.sleep).to be true
|
|
39
|
+
end
|
|
40
|
+
it "succeeds if cleaning" do
|
|
41
|
+
subject.run
|
|
42
|
+
subject.clean
|
|
43
|
+
expect(subject.may_sleep?).to be true
|
|
44
|
+
expect(subject.sleep).to be true
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "#run" do
|
|
49
|
+
it "succeeds if sleeping" do
|
|
50
|
+
expect(subject.may_run?).to be true
|
|
51
|
+
expect(subject.run).to be true
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "fails if already running" do
|
|
55
|
+
subject.run
|
|
56
|
+
expect(subject.may_run?).to be false
|
|
57
|
+
expect(subject.run).to be false
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "fails if cleaning" do
|
|
61
|
+
subject.run
|
|
62
|
+
subject.clean
|
|
63
|
+
expect(subject.may_run?).to be false
|
|
64
|
+
expect(subject.run).to be false
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe "#clean" do
|
|
69
|
+
it "succeeds if running" do
|
|
70
|
+
subject.run
|
|
71
|
+
expect(subject.may_clean?).to be true
|
|
72
|
+
expect(subject.clean).to be true
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "fails if sleeping" do
|
|
76
|
+
expect(subject.may_clean?).to be false
|
|
77
|
+
expect(subject.clean).to be false
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "fails if already cleaning" do
|
|
81
|
+
subject.run
|
|
82
|
+
subject.clean
|
|
83
|
+
expect(subject.may_clean?).to be false
|
|
84
|
+
expect(subject.clean).to be false
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -8,9 +8,9 @@ class OneStateMachine
|
|
|
8
8
|
state :running
|
|
9
9
|
state :cleaning
|
|
10
10
|
|
|
11
|
-
event :run,
|
|
12
|
-
event :clean,
|
|
13
|
-
event :sleep,
|
|
11
|
+
event :run, transitions: { from: :sleeping, to: :running }
|
|
12
|
+
event :clean, transitions: { from: :running, to: :cleaning }
|
|
13
|
+
event :sleep, transitions: { from: %i[running cleaning], to: :sleeping }
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -7,16 +7,16 @@ class TwoStateMachines
|
|
|
7
7
|
state :idling, initial: true
|
|
8
8
|
state :walking
|
|
9
9
|
|
|
10
|
-
event :idle,
|
|
11
|
-
event :walk,
|
|
10
|
+
event :idle, transitions: { from: :any, to: :idling }
|
|
11
|
+
event :walk, transitions: { from: :idling, to: :walking }
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
state_machine :action do
|
|
15
15
|
state :ready, initial: true
|
|
16
16
|
state :blocking
|
|
17
17
|
|
|
18
|
-
event :hold,
|
|
19
|
-
event :block,
|
|
18
|
+
event :hold, transitions: { from: :any, to: :ready }
|
|
19
|
+
event :block, transitions: { from: :any, to: :blocking }
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: simply_fsm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- nogginly
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-03-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rdoc
|
|
@@ -65,6 +65,7 @@ files:
|
|
|
65
65
|
- spec/support/state_machine_examples.rb
|
|
66
66
|
- spec/unit/fail_events_spec.rb
|
|
67
67
|
- spec/unit/guard_events_spec.rb
|
|
68
|
+
- spec/unit/multi_transition_state_machine_spec.rb
|
|
68
69
|
- spec/unit/one_state_machine_spec.rb
|
|
69
70
|
- spec/unit/simply_fsm_spec.rb
|
|
70
71
|
- spec/unit/two_state_machines_spec.rb
|
|
@@ -99,6 +100,7 @@ test_files:
|
|
|
99
100
|
- spec/support/state_machine_examples.rb
|
|
100
101
|
- spec/unit/fail_events_spec.rb
|
|
101
102
|
- spec/unit/guard_events_spec.rb
|
|
103
|
+
- spec/unit/multi_transition_state_machine_spec.rb
|
|
102
104
|
- spec/unit/one_state_machine_spec.rb
|
|
103
105
|
- spec/unit/simply_fsm_spec.rb
|
|
104
106
|
- spec/unit/two_state_machines_spec.rb
|