end_state 0.10.1 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +27 -20
- data/examples/example1.rb +2 -2
- data/lib/end_state/concluder.rb +0 -4
- data/lib/end_state/concluders/persistence.rb +0 -4
- data/lib/end_state/errors.rb +1 -6
- data/lib/end_state/graph.rb +4 -4
- data/lib/end_state/state_machine.rb +50 -33
- data/lib/end_state/transition.rb +0 -6
- data/lib/end_state/version.rb +1 -1
- data/spec/end_state/action_spec.rb +2 -2
- data/spec/end_state/concluders/persistence_spec.rb +2 -2
- data/spec/end_state/state_machine_spec.rb +80 -39
- data/spec/end_state/transition_spec.rb +16 -16
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd8b390f8750c3af0948f56fa4e7471f5d4dfce8
|
4
|
+
data.tar.gz: ed30307b64e15e69829f25f61dcd883f3ce42fc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d00715edd410e6dcffba526a15a5a5ad9475ce70665363423751a08b0a70912024b8c433126c8e11231b045d7278ee00821f3afb8845f1e3b578aaf56f01cad2
|
7
|
+
data.tar.gz: f4139a6f1fca2ca85e3883885d48106f293d0e7605060863cfd4ca6b7b350f24bfc8d10f6b65786329ebd6338c669e11bd9de2f34bc0f22c359c2eb08f7d3591
|
data/README.md
CHANGED
@@ -51,15 +51,17 @@ machine = Machine.new(StatefulObject.new(:a))
|
|
51
51
|
machine.transition :b # => true
|
52
52
|
machine.state # => :b
|
53
53
|
machine.b? # => true
|
54
|
-
machine.c
|
54
|
+
machine.transition :c # => true
|
55
55
|
machine.state # => :c
|
56
56
|
machine.can_transition? :b # => false
|
57
57
|
machine.can_transition? :a # => true
|
58
|
-
machine.b
|
59
|
-
machine.
|
58
|
+
machine.transition :b # => false
|
59
|
+
machine.transition! :b # => raises InvalidTransition
|
60
|
+
machine.transition :a # => true
|
60
61
|
machine.state # => :a
|
61
|
-
machine.go
|
62
|
+
machine.go # => true
|
62
63
|
machine.state # => :b
|
64
|
+
machine.go! # => raises InvalidTransition
|
63
65
|
```
|
64
66
|
|
65
67
|
## Initial State
|
@@ -86,13 +88,13 @@ class Machine < EndState::StateMachine
|
|
86
88
|
end
|
87
89
|
|
88
90
|
machine = Machine.new(StatefulObject.new(:a))
|
89
|
-
machine.d
|
90
|
-
machine.state
|
91
|
+
machine.transition :d # true
|
92
|
+
machine.state # :d
|
91
93
|
|
92
94
|
machine = Machine.new(StatefulObject.new(:a))
|
93
|
-
machine.b
|
94
|
-
machine.d
|
95
|
-
machine.state
|
95
|
+
machine.transition :b # true
|
96
|
+
machine.transition :d # true
|
97
|
+
machine.state # :d
|
96
98
|
```
|
97
99
|
|
98
100
|
## Guards
|
@@ -234,10 +236,11 @@ end
|
|
234
236
|
By using the `as` option in a transition definition you are creating an event representing that transition.
|
235
237
|
This can allow you to exercise the machine in a more natural "verb" style interaction. When using `as` event
|
236
238
|
definitions you can optionally set a `blocked` message on the transition. When the event is executed, if the
|
237
|
-
machine is not in
|
238
|
-
array on the machine.
|
239
|
+
machine is not in the initial state of the event, the message is added to the `failure_messages`
|
240
|
+
array on the machine. Events, like `transition` have both a standard and a bang (`!`) style. The bang style
|
241
|
+
will raise an exception if there is a problem.
|
239
242
|
|
240
|
-
```
|
243
|
+
```ruby
|
241
244
|
class Machine < EndState::StateMachine
|
242
245
|
transition a: :b, as: :go do |t|
|
243
246
|
t.blocked 'Cannot go!'
|
@@ -246,10 +249,11 @@ end
|
|
246
249
|
|
247
250
|
machine = Machine.new(StatefulObject.new(:a))
|
248
251
|
|
249
|
-
machine.go
|
252
|
+
machine.go # => true
|
250
253
|
machine.state # => :b
|
251
|
-
machine.go
|
254
|
+
machine.go # => false
|
252
255
|
machine.failure_messages # => ['Cannot go!']
|
256
|
+
machine.go! # => raises InvalidTransition
|
253
257
|
```
|
254
258
|
|
255
259
|
## Parameters
|
@@ -261,25 +265,28 @@ When defining a transition you can indicate what parameters you are expecting wi
|
|
261
265
|
If you require any params then attempting to transition without them provided will raise an error. Specifying allowed
|
262
266
|
params is purely for documentation purposes.
|
263
267
|
|
264
|
-
```
|
268
|
+
```ruby
|
265
269
|
class Machine < EndState::StateMachine
|
266
|
-
transition a: :b do |t|
|
270
|
+
transition a: :b, as: :go do |t|
|
267
271
|
t.allow_params :foo, :bar
|
268
272
|
end
|
269
273
|
end
|
270
274
|
```
|
271
275
|
|
272
|
-
```
|
276
|
+
```ruby
|
273
277
|
class Machine < EndState::StateMachine
|
274
|
-
transition a: :b do |t|
|
278
|
+
transition a: :b, as: :go do |t|
|
275
279
|
t.require_params :foo, :bar
|
276
280
|
end
|
277
281
|
end
|
278
282
|
|
279
283
|
machine = Machine.new(StatefulObject.new(:a))
|
284
|
+
machine.transition :b # => error raised: 'Missing params: foo, bar'
|
285
|
+
machine.transition :b, foo: 1, bar: 'value' # => true
|
280
286
|
|
281
|
-
machine
|
282
|
-
machine.
|
287
|
+
machine = Machine.new(StatefulObject.new(:a))
|
288
|
+
machine.go # => error raised: 'Missing params: foo, bar'
|
289
|
+
machine.go foo: 1, bar: 'value' # => true
|
283
290
|
```
|
284
291
|
|
285
292
|
## State storage
|
data/examples/example1.rb
CHANGED
@@ -25,7 +25,7 @@ end
|
|
25
25
|
|
26
26
|
class Machine < EndState::StateMachine
|
27
27
|
transition a: :b do |t|
|
28
|
-
t.guard Easy
|
28
|
+
t.guard Easy
|
29
29
|
t.persistence_on
|
30
30
|
end
|
31
31
|
|
@@ -35,7 +35,7 @@ class Machine < EndState::StateMachine
|
|
35
35
|
end
|
36
36
|
|
37
37
|
transition [:b, :c] => :a do |t|
|
38
|
-
t.concluder NoOp
|
38
|
+
t.concluder NoOp
|
39
39
|
t.persistence_on
|
40
40
|
end
|
41
41
|
end
|
data/lib/end_state/concluder.rb
CHANGED
data/lib/end_state/errors.rb
CHANGED
@@ -1,12 +1,7 @@
|
|
1
1
|
module EndState
|
2
2
|
class Error < StandardError; end
|
3
3
|
class UnknownState < Error; end
|
4
|
-
class
|
5
|
-
class InvalidEvent < Error; end
|
4
|
+
class InvalidTransition < Error; end
|
6
5
|
class GuardFailed < Error; end
|
7
6
|
class ConcluderFailed < Error; end
|
8
|
-
|
9
|
-
# Backward compatibility
|
10
|
-
# Finalizer is deprecated
|
11
|
-
FinalizerFailed = ConcluderFailed
|
12
7
|
end
|
data/lib/end_state/graph.rb
CHANGED
@@ -12,9 +12,9 @@ module EndState
|
|
12
12
|
def draw
|
13
13
|
machine.transitions.keys.each do |t|
|
14
14
|
left, right = t.to_a.flatten
|
15
|
-
nodes[left] ||=
|
16
|
-
nodes[right] ||=
|
17
|
-
edge =
|
15
|
+
nodes[left] ||= add_nodes(left.to_s)
|
16
|
+
nodes[right] ||= add_nodes(right.to_s)
|
17
|
+
edge = add_edges nodes[left], nodes[right]
|
18
18
|
if event_labels
|
19
19
|
event = machine.events.detect do |event, transition|
|
20
20
|
transition.include? t
|
@@ -25,4 +25,4 @@ module EndState
|
|
25
25
|
self
|
26
26
|
end
|
27
27
|
end
|
28
|
-
end
|
28
|
+
end
|
@@ -80,8 +80,8 @@ module EndState
|
|
80
80
|
def can_transition?(state, params = {})
|
81
81
|
previous_state = self.state.to_sym
|
82
82
|
state = state.to_sym
|
83
|
-
transition =
|
84
|
-
return
|
83
|
+
transition = __sm_transition_for(previous_state, state)
|
84
|
+
return __sm_block_transistion(transition, state, :soft) unless transition
|
85
85
|
transition.will_allow? state, params
|
86
86
|
end
|
87
87
|
|
@@ -90,11 +90,12 @@ module EndState
|
|
90
90
|
@success_messages = []
|
91
91
|
previous_state = self.state ? self.state.to_sym : self.state
|
92
92
|
state = state.to_sym
|
93
|
-
transition =
|
94
|
-
|
95
|
-
return
|
93
|
+
transition = __sm_transition_for(previous_state, state)
|
94
|
+
mode = __sm_actual_mode(mode)
|
95
|
+
return __sm_block_transistion(transition, state, mode) unless transition
|
96
|
+
return __sm_guard_failed(state, mode) unless transition.allowed?(self, params)
|
96
97
|
return false unless transition.action.new(self, state).call
|
97
|
-
return
|
98
|
+
return __sm_conclude_failed(state, mode) unless transition.conclude(self, previous_state, params)
|
98
99
|
true
|
99
100
|
end
|
100
101
|
|
@@ -103,62 +104,78 @@ module EndState
|
|
103
104
|
end
|
104
105
|
|
105
106
|
def method_missing(method, *args, &block)
|
106
|
-
|
107
|
-
return
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
if method.to_s.end_with?('!')
|
112
|
-
transition check_state, (args[0] || {})
|
113
|
-
else
|
114
|
-
super
|
115
|
-
end
|
107
|
+
return super unless __sm_predicate_or_event?(method)
|
108
|
+
return __sm_current_state?(method) if __sm_state_predicate(method)
|
109
|
+
new_state, mode = __sm_event(method)
|
110
|
+
return false if new_state == :__invalid_event__
|
111
|
+
transition new_state, (args[0] || {}), mode
|
116
112
|
end
|
117
113
|
|
118
114
|
private
|
119
115
|
|
120
|
-
def
|
121
|
-
|
116
|
+
def __sm_predicate_or_event?(method)
|
117
|
+
__sm_state_predicate(method) ||
|
118
|
+
__sm_event(method)
|
119
|
+
end
|
120
|
+
|
121
|
+
def __sm_state_predicate(method)
|
122
|
+
state = method.to_s[0..-2].to_sym
|
123
|
+
return unless self.class.states.include?(state) && method.to_s.end_with?('?')
|
124
|
+
state
|
125
|
+
end
|
126
|
+
|
127
|
+
def __sm_event(method)
|
128
|
+
event = __sm_state_for_event(method.to_sym, __sm_actual_mode(:soft))
|
129
|
+
return event, __sm_actual_mode(:soft) if event
|
130
|
+
return unless method.to_s.end_with?('!')
|
131
|
+
event = __sm_state_for_event(method.to_s[0..-2].to_sym, :hard)
|
132
|
+
return event, :hard if event
|
133
|
+
nil
|
134
|
+
end
|
135
|
+
|
136
|
+
def __sm_actual_mode(mode)
|
137
|
+
return :hard if self.class.mode == :hard
|
138
|
+
mode
|
122
139
|
end
|
123
140
|
|
124
|
-
def
|
125
|
-
state.to_sym ==
|
141
|
+
def __sm_current_state?(method)
|
142
|
+
state.to_sym == __sm_state_predicate(method)
|
126
143
|
end
|
127
144
|
|
128
|
-
def
|
145
|
+
def __sm_state_for_event(event, mode)
|
129
146
|
transitions = self.class.events[event]
|
130
147
|
return false unless transitions
|
131
148
|
start_states = transitions.map { |t| t.keys.first }
|
132
|
-
return
|
149
|
+
return __sm_invalid_event(event, mode) unless start_states.include?(state.to_sym) || start_states.include?(:any_state)
|
133
150
|
transitions.first.values.first
|
134
151
|
end
|
135
152
|
|
136
|
-
def
|
137
|
-
|
138
|
-
self.class.transitions[{ any_state: to }]
|
139
|
-
end
|
140
|
-
|
141
|
-
def invalid_event(event)
|
142
|
-
fail InvalidEvent, "Transition by event: #{event} is invalid." if self.class.mode == :hard
|
153
|
+
def __sm_invalid_event(event, mode)
|
154
|
+
fail InvalidTransition, "Transition by event: #{event} is invalid." if mode == :hard
|
143
155
|
message = self.class.transitions[self.class.events[event].first].blocked_event_message
|
144
156
|
@failure_messages = [message] if message
|
145
157
|
:__invalid_event__
|
146
158
|
end
|
147
159
|
|
148
|
-
def
|
160
|
+
def __sm_transition_for(from, to)
|
161
|
+
self.class.transitions[{ from => to }] ||
|
162
|
+
self.class.transitions[{ any_state: to }]
|
163
|
+
end
|
164
|
+
|
165
|
+
def __sm_block_transistion(transition, state, mode)
|
149
166
|
if self.class.end_states.include? state
|
150
|
-
fail
|
167
|
+
fail InvalidTransition, "The transition: #{object.state} => #{state} is invalid." if mode == :hard
|
151
168
|
return false
|
152
169
|
end
|
153
170
|
fail UnknownState, "The state: #{state} is unknown."
|
154
171
|
end
|
155
172
|
|
156
|
-
def
|
173
|
+
def __sm_guard_failed(state, mode)
|
157
174
|
return false unless mode == :hard
|
158
175
|
fail GuardFailed, "The transition to #{state} was blocked: #{failure_messages.join(', ')}"
|
159
176
|
end
|
160
177
|
|
161
|
-
def
|
178
|
+
def __sm_conclude_failed(state, mode)
|
162
179
|
return false unless mode == :hard
|
163
180
|
fail ConcluderFailed, "The transition to #{state} was rolled back: #{failure_messages.join(', ')}"
|
164
181
|
end
|
data/lib/end_state/transition.rb
CHANGED
@@ -63,12 +63,6 @@ module EndState
|
|
63
63
|
@blocked_event_message = message
|
64
64
|
end
|
65
65
|
|
66
|
-
# Backward compatibility
|
67
|
-
# Finalizer is deprecated
|
68
|
-
alias_method :finalizers, :concluders
|
69
|
-
alias_method :finalize, :conclude
|
70
|
-
alias_method :finalizer, :concluder
|
71
|
-
|
72
66
|
private
|
73
67
|
|
74
68
|
def rollback(concluded, object, previous_state, params)
|
data/lib/end_state/version.rb
CHANGED
@@ -6,7 +6,7 @@ module EndState
|
|
6
6
|
let(:object) { OpenStruct.new(state: nil) }
|
7
7
|
let(:state) { :a }
|
8
8
|
|
9
|
-
before { object.
|
9
|
+
before { allow(object).to receive_message_chain(:class, store_states_as_strings: false) }
|
10
10
|
|
11
11
|
describe '#call' do
|
12
12
|
it 'changes the state to the new state' do
|
@@ -22,4 +22,4 @@ module EndState
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
@@ -18,7 +18,7 @@ module EndState
|
|
18
18
|
let(:object) { Object.new }
|
19
19
|
|
20
20
|
it 'returns false' do
|
21
|
-
expect(concluder.call).to
|
21
|
+
expect(concluder.call).to be false
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -33,7 +33,7 @@ module EndState
|
|
33
33
|
let(:object) { Object.new }
|
34
34
|
|
35
35
|
it 'returns true' do
|
36
|
-
expect(concluder.rollback).to
|
36
|
+
expect(concluder.rollback).to be true
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -23,7 +23,7 @@ module EndState
|
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'does not require a block' do
|
26
|
-
expect
|
26
|
+
expect { StateMachine.transition(b: :c) }.not_to raise_error
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'adds the transition to the state machine' do
|
@@ -89,13 +89,13 @@ module EndState
|
|
89
89
|
describe '.store_states_as_strings!' do
|
90
90
|
it 'sets the flag' do
|
91
91
|
StateMachine.store_states_as_strings!
|
92
|
-
expect(StateMachine.store_states_as_strings).to
|
92
|
+
expect(StateMachine.store_states_as_strings).to be true
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
96
|
describe '#store_states_as_strings' do
|
97
97
|
it 'is false by default' do
|
98
|
-
expect(StateMachine.store_states_as_strings).to
|
98
|
+
expect(StateMachine.store_states_as_strings).to be false
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
@@ -136,15 +136,15 @@ module EndState
|
|
136
136
|
context 'when the object has state :a' do
|
137
137
|
let(:object) { OpenStruct.new(state: :a) }
|
138
138
|
|
139
|
-
specify { expect(machine.a?).to
|
140
|
-
specify { expect(machine.b?).to
|
139
|
+
specify { expect(machine.a?).to be true }
|
140
|
+
specify { expect(machine.b?).to be false }
|
141
141
|
end
|
142
142
|
|
143
143
|
context 'when the object has state :b' do
|
144
144
|
let(:object) { OpenStruct.new(state: :b) }
|
145
145
|
|
146
|
-
specify { expect(machine.b?).to
|
147
|
-
specify { expect(machine.a?).to
|
146
|
+
specify { expect(machine.b?).to be true }
|
147
|
+
specify { expect(machine.a?).to be false }
|
148
148
|
end
|
149
149
|
|
150
150
|
context 'when the state shares a name with an event' do
|
@@ -153,7 +153,7 @@ module EndState
|
|
153
153
|
context 'and the object, in that state, cannot transition on the event' do
|
154
154
|
let(:object) { OpenStruct.new(state: :stop) }
|
155
155
|
|
156
|
-
specify { expect(machine.stop?).to
|
156
|
+
specify { expect(machine.stop?).to be true }
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
@@ -170,7 +170,7 @@ module EndState
|
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
173
|
-
describe '#{
|
173
|
+
describe '#{event}' do
|
174
174
|
let(:object) { OpenStruct.new(state: :a) }
|
175
175
|
before do
|
176
176
|
StateMachine.transition a: :b, as: :go do |t|
|
@@ -179,49 +179,90 @@ module EndState
|
|
179
179
|
end
|
180
180
|
|
181
181
|
it 'transitions the state' do
|
182
|
-
machine.
|
182
|
+
machine.go
|
183
183
|
expect(machine.state).to eq :b
|
184
184
|
end
|
185
185
|
|
186
186
|
it 'accepts params' do
|
187
|
-
machine.
|
188
|
-
machine.
|
189
|
-
expect(machine).to have_received(:transition).with(:b, { foo: 'bar', bar: 'foo' })
|
187
|
+
allow(machine).to receive(:transition)
|
188
|
+
machine.go foo: 'bar', bar: 'foo'
|
189
|
+
expect(machine).to have_received(:transition).with(:b, { foo: 'bar', bar: 'foo' }, :soft)
|
190
190
|
end
|
191
191
|
|
192
192
|
it 'defaults params to {}' do
|
193
|
-
machine.
|
194
|
-
machine.
|
195
|
-
expect(machine).to have_received(:transition).with(:b, {})
|
196
|
-
end
|
197
|
-
|
198
|
-
it 'works with an event' do
|
199
|
-
machine.go!
|
200
|
-
expect(machine.state).to eq :b
|
193
|
+
allow(machine).to receive(:transition)
|
194
|
+
machine.go
|
195
|
+
expect(machine).to have_received(:transition).with(:b, {}, :soft)
|
201
196
|
end
|
202
197
|
|
203
198
|
context 'when the intial state is :c' do
|
204
199
|
let(:object) { OpenStruct.new(state: :c) }
|
205
200
|
|
206
201
|
it 'blocks invalid events' do
|
207
|
-
machine.go
|
202
|
+
machine.go
|
208
203
|
expect(machine.state).to eq :c
|
209
204
|
end
|
210
205
|
|
211
206
|
it 'adds a failure message specified by blocked' do
|
212
|
-
machine.go
|
207
|
+
machine.go
|
213
208
|
expect(machine.failure_messages).to eq ['Invalid event!']
|
214
209
|
end
|
215
210
|
|
216
211
|
context 'and all transitions are forced to run in :hard mode' do
|
217
212
|
before { machine.class.treat_all_transitions_as_hard! }
|
218
213
|
|
219
|
-
it 'raises an
|
220
|
-
expect { machine.go
|
214
|
+
it 'raises an InvalidTransition error' do
|
215
|
+
expect { machine.go }.to raise_error(InvalidTransition)
|
221
216
|
end
|
222
217
|
end
|
223
218
|
end
|
224
219
|
|
220
|
+
context 'when using any_state with an event' do
|
221
|
+
before do
|
222
|
+
StateMachine.transition any_state: :end, as: :jump_to_end
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'transitions the state to :end' do
|
226
|
+
machine.jump_to_end
|
227
|
+
expect(machine.state).to eq :end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe '#{event}!' do
|
233
|
+
let(:object) { OpenStruct.new(state: :a) }
|
234
|
+
before do
|
235
|
+
StateMachine.transition a: :b, as: :go do |t|
|
236
|
+
t.blocked 'Invalid event!'
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'transitions the state' do
|
241
|
+
machine.go!
|
242
|
+
expect(machine.state).to eq :b
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'accepts params' do
|
246
|
+
allow(machine).to receive(:transition)
|
247
|
+
machine.go! foo: 'bar', bar: 'foo'
|
248
|
+
expect(machine).to have_received(:transition).with(:b, { foo: 'bar', bar: 'foo' }, :hard)
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'defaults params to {}' do
|
252
|
+
allow(machine).to receive(:transition)
|
253
|
+
machine.go!
|
254
|
+
expect(machine).to have_received(:transition).with(:b, {}, :hard)
|
255
|
+
end
|
256
|
+
|
257
|
+
context 'when the intial state is :c' do
|
258
|
+
let(:object) { OpenStruct.new(state: :c) }
|
259
|
+
|
260
|
+
it 'blocks invalid events' do
|
261
|
+
expect { machine.go! }.to raise_error
|
262
|
+
expect(machine.state).to eq :c
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
225
266
|
context 'when using any_state with an event' do
|
226
267
|
before do
|
227
268
|
StateMachine.transition any_state: :end, as: :jump_to_end
|
@@ -242,11 +283,11 @@ module EndState
|
|
242
283
|
end
|
243
284
|
|
244
285
|
context 'when asking about an allowed transition' do
|
245
|
-
specify { expect(machine.can_transition? :b).to
|
286
|
+
specify { expect(machine.can_transition? :b).to be true }
|
246
287
|
end
|
247
288
|
|
248
289
|
context 'when asking about a disallowed transition' do
|
249
|
-
specify { expect(machine.can_transition? :c).to
|
290
|
+
specify { expect(machine.can_transition? :c).to be false }
|
250
291
|
end
|
251
292
|
|
252
293
|
context 'when using :any_state' do
|
@@ -255,13 +296,13 @@ module EndState
|
|
255
296
|
context 'and the initial state is :a' do
|
256
297
|
let(:object) { OpenStruct.new(state: :a) }
|
257
298
|
|
258
|
-
specify { expect(machine.can_transition? :d).to
|
299
|
+
specify { expect(machine.can_transition? :d).to be true }
|
259
300
|
end
|
260
301
|
|
261
302
|
context 'and the initial state is :b' do
|
262
303
|
let(:object) { OpenStruct.new(state: :b) }
|
263
304
|
|
264
|
-
specify { expect(machine.can_transition? :d).to
|
305
|
+
specify { expect(machine.can_transition? :d).to be true }
|
265
306
|
end
|
266
307
|
end
|
267
308
|
end
|
@@ -276,7 +317,7 @@ module EndState
|
|
276
317
|
before { StateMachine.transition a: :b }
|
277
318
|
|
278
319
|
it 'returns false' do
|
279
|
-
expect(machine.transition(:b)).to
|
320
|
+
expect(machine.transition(:b)).to be false
|
280
321
|
end
|
281
322
|
end
|
282
323
|
end
|
@@ -335,7 +376,7 @@ module EndState
|
|
335
376
|
|
336
377
|
context 'and the object satisfies the guard' do
|
337
378
|
before do
|
338
|
-
guard_instance.
|
379
|
+
allow(guard_instance).to receive(:allowed?).and_return(true)
|
339
380
|
object.state = :a
|
340
381
|
end
|
341
382
|
|
@@ -347,7 +388,7 @@ module EndState
|
|
347
388
|
|
348
389
|
context 'and the object does not satisfy the guard' do
|
349
390
|
before do
|
350
|
-
guard_instance.
|
391
|
+
allow(guard_instance).to receive(:allowed?).and_return(false)
|
351
392
|
object.state = :a
|
352
393
|
end
|
353
394
|
|
@@ -377,7 +418,7 @@ module EndState
|
|
377
418
|
|
378
419
|
context 'and the concluder is successful' do
|
379
420
|
before do
|
380
|
-
concluder_instance.
|
421
|
+
allow(concluder_instance).to receive(:call).and_return(true)
|
381
422
|
end
|
382
423
|
|
383
424
|
it 'transitions the state' do
|
@@ -388,7 +429,7 @@ module EndState
|
|
388
429
|
|
389
430
|
context 'and the concluder fails' do
|
390
431
|
before do
|
391
|
-
concluder_instance.
|
432
|
+
allow(concluder_instance).to receive(:call).and_return(false)
|
392
433
|
end
|
393
434
|
|
394
435
|
it 'does not transition the state' do
|
@@ -410,7 +451,7 @@ module EndState
|
|
410
451
|
before { StateMachine.transition a: :b }
|
411
452
|
|
412
453
|
it 'returns false' do
|
413
|
-
expect { machine.transition!(:b) }.to raise_error(
|
454
|
+
expect { machine.transition!(:b) }.to raise_error(InvalidTransition)
|
414
455
|
end
|
415
456
|
end
|
416
457
|
end
|
@@ -437,7 +478,7 @@ module EndState
|
|
437
478
|
|
438
479
|
context 'and the object satisfies the guard' do
|
439
480
|
before do
|
440
|
-
guard_instance.
|
481
|
+
allow(guard_instance).to receive(:allowed?).and_return(true)
|
441
482
|
object.state = :a
|
442
483
|
end
|
443
484
|
|
@@ -449,7 +490,7 @@ module EndState
|
|
449
490
|
|
450
491
|
context 'and the object does not satisfy the guard' do
|
451
492
|
before do
|
452
|
-
guard_instance.
|
493
|
+
allow(guard_instance).to receive(:allowed?).and_return(false)
|
453
494
|
object.state = :a
|
454
495
|
end
|
455
496
|
|
@@ -471,7 +512,7 @@ module EndState
|
|
471
512
|
|
472
513
|
context 'and the concluder is successful' do
|
473
514
|
before do
|
474
|
-
concluder_instance.
|
515
|
+
allow(concluder_instance).to receive(:call).and_return(true)
|
475
516
|
end
|
476
517
|
|
477
518
|
it 'transitions the state' do
|
@@ -482,7 +523,7 @@ module EndState
|
|
482
523
|
|
483
524
|
context 'and the concluder fails' do
|
484
525
|
before do
|
485
|
-
concluder_instance.
|
526
|
+
allow(concluder_instance).to receive(:call).and_return(false)
|
486
527
|
end
|
487
528
|
|
488
529
|
it 'does not transition the state' do
|
@@ -42,9 +42,9 @@ module EndState
|
|
42
42
|
before { transition.guards << guard }
|
43
43
|
|
44
44
|
context 'when all guards pass' do
|
45
|
-
before { guard_instance.
|
45
|
+
before { allow(guard_instance).to receive(:allowed?).and_return(true) }
|
46
46
|
|
47
|
-
specify { expect(transition.allowed? object).to
|
47
|
+
specify { expect(transition.allowed? object).to be true }
|
48
48
|
|
49
49
|
context 'when params are provided' do
|
50
50
|
it 'creates the guard with the params' do
|
@@ -62,16 +62,16 @@ module EndState
|
|
62
62
|
end
|
63
63
|
|
64
64
|
context 'and all required are provided' do
|
65
|
-
specify { expect(transition.allowed? object, foo: 1, bar: 2).to
|
65
|
+
specify { expect(transition.allowed? object, foo: 1, bar: 2).to be true }
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
71
|
context 'when not all guards pass' do
|
72
|
-
before { guard_instance.
|
72
|
+
before { allow(guard_instance).to receive(:allowed?).and_return(false) }
|
73
73
|
|
74
|
-
specify { expect(transition.allowed? object).to
|
74
|
+
specify { expect(transition.allowed? object).to be false }
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
@@ -82,9 +82,9 @@ module EndState
|
|
82
82
|
before { transition.guards << guard }
|
83
83
|
|
84
84
|
context 'when all guards pass' do
|
85
|
-
before { guard_instance.
|
85
|
+
before { allow(guard_instance).to receive(:will_allow?).and_return(true) }
|
86
86
|
|
87
|
-
specify { expect(transition.will_allow? object).to
|
87
|
+
specify { expect(transition.will_allow? object).to be true }
|
88
88
|
|
89
89
|
context 'when params are provided' do
|
90
90
|
it 'creates the guard with the params' do
|
@@ -96,20 +96,20 @@ module EndState
|
|
96
96
|
before { transition.require_params :foo, :bar }
|
97
97
|
|
98
98
|
context 'and not all required are provided' do
|
99
|
-
specify { expect(transition.will_allow? object).to
|
99
|
+
specify { expect(transition.will_allow? object).to be false }
|
100
100
|
end
|
101
101
|
|
102
102
|
context 'and all required are provided' do
|
103
|
-
specify { expect(transition.will_allow? object, foo: 1, bar: 2).to
|
103
|
+
specify { expect(transition.will_allow? object, foo: 1, bar: 2).to be true }
|
104
104
|
end
|
105
105
|
end
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
109
|
context 'when not all guards pass' do
|
110
|
-
before { guard_instance.
|
110
|
+
before { allow(guard_instance).to receive(:will_allow?).and_return(false) }
|
111
111
|
|
112
|
-
specify { expect(transition.will_allow? object).to
|
112
|
+
specify { expect(transition.will_allow? object).to be false }
|
113
113
|
end
|
114
114
|
|
115
115
|
context 'when params are provided' do
|
@@ -160,20 +160,20 @@ module EndState
|
|
160
160
|
let(:concluder_instance) { double :concluder_instance, call: nil, rollback: nil }
|
161
161
|
let(:object) { OpenStruct.new(state: :b) }
|
162
162
|
before do
|
163
|
-
object.
|
163
|
+
allow(object).to receive_message_chain(:class, store_states_as_strings: false)
|
164
164
|
transition.concluders << concluder
|
165
165
|
end
|
166
166
|
|
167
167
|
context 'when all concluders succeed' do
|
168
|
-
before { concluder_instance.
|
168
|
+
before { allow(concluder_instance).to receive(:call).and_return(true) }
|
169
169
|
|
170
|
-
specify { expect(transition.conclude object, :a).to
|
170
|
+
specify { expect(transition.conclude object, :a).to be true }
|
171
171
|
end
|
172
172
|
|
173
173
|
context 'when not all concluders succeed' do
|
174
|
-
before { concluder_instance.
|
174
|
+
before { allow(concluder_instance).to receive(:call).and_return(false) }
|
175
175
|
|
176
|
-
specify { expect(transition.conclude object, :a).to
|
176
|
+
specify { expect(transition.conclude object, :a).to be false }
|
177
177
|
|
178
178
|
it 'rolls them back' do
|
179
179
|
transition.conclude object, :a
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: end_state
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- alexpeachey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|