finite_machine 0.6.1 → 0.7.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.
@@ -21,18 +21,21 @@ module FiniteMachine
21
21
 
22
22
  # Extract states from attributes
23
23
  #
24
+ # @param [Proc] block
25
+ #
24
26
  # @example
25
27
  # StateParpser.new(attr).parase_states
26
28
  #
27
29
  # @return [Hash[Symbol]] states
28
30
  #
29
31
  # @api public
30
- def parse_states
31
- if contains_from_to_keys?
32
+ def parse_states(&block)
33
+ transitions = if contains_from_to_keys?
32
34
  convert_from_to_attributes_to_states_hash
33
35
  else
34
36
  convert_attributes_to_states_hash
35
37
  end
38
+ block ? transitions.each(&block) : transitions
36
39
  end
37
40
 
38
41
  # Check if attributes contain :from or :to key
@@ -4,6 +4,7 @@ module FiniteMachine
4
4
  # Class describing a transition associated with a given event
5
5
  class Transition
6
6
  include Threadable
7
+ include Safety
7
8
 
8
9
  attr_threadsafe :name
9
10
 
@@ -37,7 +38,7 @@ module FiniteMachine
37
38
  def initialize(machine, attrs = {})
38
39
  @machine = machine
39
40
  @name = attrs.fetch(:name, DEFAULT_STATE)
40
- @map = FiniteMachine::StateParser.new(attrs).parse_states
41
+ @map = attrs.fetch(:parsed_states, {})
41
42
  @from_states = @map.keys
42
43
  @to_states = @map.values
43
44
  @from_state = @from_states.first
@@ -47,6 +48,25 @@ module FiniteMachine
47
48
  @cancelled = false
48
49
  end
49
50
 
51
+ # Create transition with associated helper methods
52
+ #
53
+ # @param [FiniteMachine::StateMachine] machine
54
+ # @param [Hash] attrs
55
+ #
56
+ # @example
57
+ # Transition.create(machine, {})
58
+ #
59
+ # @return [FiniteMachine::Transition]
60
+ #
61
+ # @api public
62
+ def self.create(machine, attrs = {})
63
+ _transition = self.new(machine, attrs)
64
+ _transition.update_transitions
65
+ _transition.define_state_methods
66
+ _transition.define_event
67
+ _transition
68
+ end
69
+
50
70
  # Decide :to state from available transitions for this event
51
71
  #
52
72
  # @return [Symbol]
@@ -64,7 +84,7 @@ module FiniteMachine
64
84
  @unless.map { |c| Callable.new(c).invert }
65
85
  end
66
86
 
67
- # Check if moved to different state
87
+ # Check if moved to different state or not
68
88
  #
69
89
  # @param [Symbol] state
70
90
  # the current state name
@@ -72,8 +92,23 @@ module FiniteMachine
72
92
  # @return [Boolean]
73
93
  #
74
94
  # @api public
75
- def different?(state)
76
- map[state] == state || map[ANY_STATE] == state
95
+ def same?(state)
96
+ map[state] == state || (map[ANY_STATE] == state && from_state == state)
97
+ end
98
+
99
+ # Check if transition can be performed according to constraints
100
+ #
101
+ # @param [Array] args
102
+ #
103
+ # @param [Proc] block
104
+ #
105
+ # @return [Boolean]
106
+ #
107
+ # @api public
108
+ def valid?(*args, &block)
109
+ conditions.all? do |condition|
110
+ condition.call(machine.target, *args, &block)
111
+ end
77
112
  end
78
113
 
79
114
  # Add transition to the machine
@@ -81,7 +116,7 @@ module FiniteMachine
81
116
  # @return [Transition]
82
117
  #
83
118
  # @api private
84
- def define
119
+ def update_transitions
85
120
  from_states.each do |from|
86
121
  machine.transitions[name][from] = map[from] || ANY_STATE
87
122
  end
@@ -110,24 +145,25 @@ module FiniteMachine
110
145
  #
111
146
  # @api private
112
147
  def define_event
113
- _name = name
114
- bang_name = "#{_name}!"
115
-
116
- machine.singleton_class.class_eval do
117
- undef_method(_name) if method_defined?(_name)
118
- undef_method(bang_name) if method_defined?(bang_name)
148
+ detect_event_conflict!(name)
149
+ if machine.singleton_class.send(:method_defined?, name)
150
+ machine.events_chain[name] << self
151
+ else
152
+ define_event_transition(name)
153
+ define_event_bang(name)
119
154
  end
120
- define_transition(name)
121
- define_event_bang(name)
122
155
  end
123
156
 
124
157
  # Define transition event
125
158
  #
126
159
  # @api private
127
- def define_transition(name)
128
- _transition = self
160
+ def define_event_transition(name)
161
+ _event = FiniteMachine::Event.new(machine, name: name)
162
+ _event << self
163
+ machine.events_chain[name] = _event
164
+
129
165
  machine.send(:define_singleton_method, name) do |*args, &block|
130
- transition(_transition, *args, &block)
166
+ _event.call(*args, &block)
131
167
  end
132
168
  end
133
169
 
@@ -158,6 +194,8 @@ module FiniteMachine
158
194
 
159
195
  # Return transition name
160
196
  #
197
+ # @return [String]
198
+ #
161
199
  # @api public
162
200
  def to_s
163
201
  @name.to_s
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module FiniteMachine
4
- VERSION = "0.6.1"
4
+ VERSION = "0.7.0"
5
5
  end
@@ -79,10 +79,10 @@ describe FiniteMachine, 'async_events' do
79
79
  }
80
80
 
81
81
  callbacks {
82
- on_enter :green, :async do |event| called << 'on_enter_green' end
83
- on_enter :slow, :async do |event| called << 'on_enter_slow' end
84
- on_exit :yellow, :async do |event| called << 'on_exit_yellow' end
85
- on_exit :go, :async do |event| called << 'on_exit_go' end
82
+ on_enter :green, :async do |event| called << 'on_enter_green' end
83
+ on_before :slow, :async do |event| called << 'on_before_slow' end
84
+ on_exit :yellow, :async do |event| called << 'on_exit_yellow' end
85
+ on_after :go, :async do |event| called << 'on_after_go' end
86
86
  }
87
87
  end
88
88
  fsm.slow
@@ -90,8 +90,8 @@ describe FiniteMachine, 'async_events' do
90
90
  sleep 0.1
91
91
  expect(called).to match_array([
92
92
  'on_enter_green',
93
- 'on_enter_slow',
94
- 'on_exit_go',
93
+ 'on_before_slow',
94
+ 'on_after_go',
95
95
  'on_exit_yellow'
96
96
  ])
97
97
  end
@@ -9,26 +9,15 @@ describe FiniteMachine, 'callbacks' do
9
9
  fsm = FiniteMachine.define do
10
10
  initial state: :green, defer: true
11
11
 
12
- events {
13
- event :slow, :green => :yellow
14
- event :stop, :yellow => :red
15
- event :ready, :red => :yellow
16
- event :go, :yellow => :green
17
- }
18
-
19
12
  callbacks {
20
- # generic callbacks
21
- on_enter do |event| called << 'on_enter' end
22
- on_enter_state do |event| called << 'on_enter_state' end
23
- on_enter_event do |event| called << 'on_enter_event' end
24
-
25
- on_transition do |event| called << 'on_transition' end
26
- on_transition_state do |event| called << 'on_transition_state' end
27
- on_transition_event do |event| called << 'on_transition_event' end
28
-
13
+ # generic state callbacks
14
+ on_enter do |event| called << 'on_enter' end
15
+ on_transition do |event| called << 'on_transition' end
29
16
  on_exit do |event| called << 'on_exit' end
30
- on_exit_state do |event| called << 'on_exit_state' end
31
- on_exit_event do |event| called << 'on_exit_event' end
17
+
18
+ # generic event callbacks
19
+ on_before do |event| called << 'on_before' end
20
+ on_after do |event| called << 'on_after' end
32
21
 
33
22
  # state callbacks
34
23
  on_enter :none do |event| called << 'on_enter_none' end
@@ -41,33 +30,24 @@ describe FiniteMachine, 'callbacks' do
41
30
  on_exit :green do |event| called << 'on_exit_green' end
42
31
 
43
32
  # event callbacks
44
- on_enter :init do |event| called << 'on_enter_init' end
45
- on_transition :init do |event| called << 'on_transition_init' end
46
- on_exit :init do |event| called << 'on_exit_init' end
33
+ on_before :init do |event| called << 'on_before_init' end
34
+ on_after :init do |event| called << 'on_after_init' end
47
35
  }
48
36
  end
49
37
 
50
38
  expect(fsm.current).to eql(:none)
51
39
  fsm.init
52
40
  expect(called).to eql([
41
+ 'on_before_init',
42
+ 'on_before',
53
43
  'on_exit_none',
54
44
  'on_exit',
55
- 'on_exit_state',
56
- 'on_enter_init',
57
- 'on_enter',
58
- 'on_enter_event',
59
45
  'on_transition_green',
60
46
  'on_transition',
61
- 'on_transition_state',
62
- 'on_transition_init',
63
- 'on_transition',
64
- 'on_transition_event',
65
47
  'on_enter_green',
66
48
  'on_enter',
67
- 'on_enter_state',
68
- 'on_exit_init',
69
- 'on_exit',
70
- 'on_exit_event'
49
+ 'on_after_init',
50
+ 'on_after'
71
51
  ])
72
52
  end
73
53
 
@@ -85,17 +65,12 @@ describe FiniteMachine, 'callbacks' do
85
65
 
86
66
  callbacks {
87
67
  # generic callbacks
88
- on_enter do |event| called << 'on_enter' end
89
- on_enter_state do |event| called << 'on_enter_state' end
90
- on_enter_event do |event| called << 'on_enter_event' end
91
-
92
- on_transition do |event| called << 'on_transition' end
93
- on_transition_state do |event| called << 'on_transition_state' end
94
- on_transition_event do |event| called << 'on_transition_event' end
95
-
68
+ on_enter do |event| called << 'on_enter' end
69
+ on_transition do |event| called << 'on_transition' end
96
70
  on_exit do |event| called << 'on_exit' end
97
- on_exit_state do |event| called << 'on_exit_state' end
98
- on_exit_event do |event| called << 'on_exit_event' end
71
+
72
+ on_before do |event| called << 'on_before' end
73
+ on_after do |event| called << 'on_after' end
99
74
 
100
75
  # state callbacks
101
76
  on_enter :green do |event| called << 'on_enter_green' end
@@ -111,113 +86,105 @@ describe FiniteMachine, 'callbacks' do
111
86
  on_exit :red do |event| called << "on_exit_red" end
112
87
 
113
88
  # event callbacks
114
- on_enter :slow do |event| called << 'on_enter_slow' end
115
- on_enter :stop do |event| called << "on_enter_stop" end
116
- on_enter :ready do |event| called << "on_enter_ready" end
117
- on_enter :go do |event| called << "on_enter_go" end
118
-
119
- on_transition :slow do |event| called << 'on_transition_slow' end
120
- on_transition :stop do |event| called << "on_transition_stop" end
121
- on_transition :ready do |event| called << "on_transition_ready" end
122
- on_transition :go do |event| called << "on_transition_go" end
123
-
124
- on_exit :slow do |event| called << 'on_exit_slow' end
125
- on_exit :stop do |event| called << "on_exit_stop" end
126
- on_exit :ready do |event| called << "on_exit_ready" end
127
- on_exit :go do |event| called << "on_exit_go" end
89
+ on_before :slow do |event| called << 'on_before_slow' end
90
+ on_before :stop do |event| called << "on_before_stop" end
91
+ on_before :ready do |event| called << "on_before_ready" end
92
+ on_before :go do |event| called << "on_before_go" end
93
+
94
+ on_after :slow do |event| called << 'on_after_slow' end
95
+ on_after :stop do |event| called << "on_after_stop" end
96
+ on_after :ready do |event| called << "on_after_ready" end
97
+ on_after :go do |event| called << "on_after_go" end
128
98
  }
129
99
  end
130
100
 
131
101
  called = []
132
102
  fsm.slow
133
103
  expect(called).to eql([
104
+ 'on_before_slow',
105
+ 'on_before',
134
106
  'on_exit_green',
135
107
  'on_exit',
136
- 'on_exit_state',
137
- 'on_enter_slow',
138
- 'on_enter',
139
- 'on_enter_event',
140
108
  'on_transition_yellow',
141
109
  'on_transition',
142
- 'on_transition_state',
143
- 'on_transition_slow',
144
- 'on_transition',
145
- 'on_transition_event',
146
110
  'on_enter_yellow',
147
111
  'on_enter',
148
- 'on_enter_state',
149
- 'on_exit_slow',
150
- 'on_exit',
151
- 'on_exit_event'
112
+ 'on_after_slow',
113
+ 'on_after'
152
114
  ])
153
115
 
154
116
  called = []
155
117
  fsm.stop
156
118
  expect(called).to eql([
119
+ 'on_before_stop',
120
+ 'on_before',
157
121
  'on_exit_yellow',
158
122
  'on_exit',
159
- 'on_exit_state',
160
- 'on_enter_stop',
161
- 'on_enter',
162
- 'on_enter_event',
163
123
  'on_transition_red',
164
124
  'on_transition',
165
- 'on_transition_state',
166
- 'on_transition_stop',
167
- 'on_transition',
168
- 'on_transition_event',
169
125
  'on_enter_red',
170
126
  'on_enter',
171
- 'on_enter_state',
172
- 'on_exit_stop',
173
- 'on_exit',
174
- 'on_exit_event'
127
+ 'on_after_stop',
128
+ 'on_after'
175
129
  ])
176
130
 
177
131
  called = []
178
132
  fsm.ready
179
133
  expect(called).to eql([
134
+ 'on_before_ready',
135
+ 'on_before',
180
136
  'on_exit_red',
181
137
  'on_exit',
182
- 'on_exit_state',
183
- 'on_enter_ready',
184
- 'on_enter',
185
- 'on_enter_event',
186
138
  'on_transition_yellow',
187
139
  'on_transition',
188
- 'on_transition_state',
189
- 'on_transition_ready',
190
- 'on_transition',
191
- 'on_transition_event',
192
140
  'on_enter_yellow',
193
141
  'on_enter',
194
- 'on_enter_state',
195
- 'on_exit_ready',
196
- 'on_exit',
197
- 'on_exit_event'
142
+ 'on_after_ready',
143
+ 'on_after'
198
144
  ])
199
145
 
200
146
  called = []
201
147
  fsm.go
202
148
  expect(called).to eql([
149
+ 'on_before_go',
150
+ 'on_before',
203
151
  'on_exit_yellow',
204
152
  'on_exit',
205
- 'on_exit_state',
206
- 'on_enter_go',
207
- 'on_enter',
208
- 'on_enter_event',
209
153
  'on_transition_green',
210
154
  'on_transition',
211
- 'on_transition_state',
212
- 'on_transition_go',
213
- 'on_transition',
214
- 'on_transition_event',
215
155
  'on_enter_green',
216
156
  'on_enter',
217
- 'on_enter_state',
218
- 'on_exit_go',
219
- 'on_exit',
220
- 'on_exit_event'
157
+ 'on_after_go',
158
+ 'on_after'
159
+ ])
160
+ end
161
+
162
+ it "maintains transition execution sequence from UML statechart" do
163
+ called = []
164
+ fsm = FiniteMachine.define do
165
+ initial :previous
166
+
167
+ events {
168
+ event :go, :previous => :next, if: -> { called << 'guard'; true}
169
+ }
170
+
171
+ callbacks {
172
+ on_exit { |event| called << "exit_#{event.from}" }
173
+ on_before { |event| called << "before_#{event.name}" }
174
+ on_transition { |event| called << "transition_#{event.from}_#{event.to}"}
175
+ on_enter { |event| called << "enter_#{event.to}"}
176
+ on_after { |event| called << "after_#{event.name}" }
177
+ }
178
+ end
179
+ expect(fsm.current).to eq(:previous)
180
+ fsm.go
181
+ expect(called).to eq([
182
+ 'before_go',
183
+ 'guard',
184
+ 'exit_previous',
185
+ 'transition_previous_next',
186
+ 'enter_next',
187
+ 'after_go'
221
188
  ])
222
189
  end
223
190
 
@@ -234,26 +201,28 @@ describe FiniteMachine, 'callbacks' do
234
201
  }
235
202
 
236
203
  callbacks {
237
- # generic callbacks
204
+ # generic state callbacks
238
205
  on_enter do |event| called << 'on_enter' end
239
206
  on_transition do |event| called << 'on_transition' end
240
207
  on_exit do |event| called << 'on_exit' end
241
208
 
209
+ # generic event callbacks
210
+ on_before do |event| called << 'on_before' end
211
+ on_after do |event| called << 'on_after' end
212
+
242
213
  # state callbacks
243
- on_exit :green do |event| called << 'on_exit_green_1' end
244
- on_exit :green do |event| called << 'on_exit_green_2' end
245
- on_enter :yellow do |event| called << 'on_enter_yellow_1' end
246
- on_enter :yellow do |event| called << 'on_enter_yellow_2' end
214
+ on_exit :green do |event| called << 'on_exit_green_1' end
215
+ on_exit :green do |event| called << 'on_exit_green_2' end
216
+ on_enter :yellow do |event| called << 'on_enter_yellow_1' end
217
+ on_enter :yellow do |event| called << 'on_enter_yellow_2' end
247
218
  on_transition :yellow do |event| called << 'on_transition_yellow_1' end
248
219
  on_transition :yellow do |event| called << 'on_transition_yellow_2' end
249
220
 
250
221
  # event callbacks
251
- on_enter :slow do |event| called << 'on_enter_slow_1' end
252
- on_enter :slow do |event| called << 'on_enter_slow_2' end
253
- on_transition :slow do |event| called << 'on_transition_slow_1' end
254
- on_transition :slow do |event| called << 'on_transition_slow_2' end
255
- on_exit :slow do |event| called << 'on_exit_slow_1' end
256
- on_exit :slow do |event| called << 'on_exit_slow_2' end
222
+ on_before :slow do |event| called << 'on_before_slow_1' end
223
+ on_before :slow do |event| called << 'on_before_slow_2' end
224
+ on_after :slow do |event| called << 'on_after_slow_1' end
225
+ on_after :slow do |event| called << 'on_after_slow_2' end
257
226
  }
258
227
  end
259
228
 
@@ -261,24 +230,21 @@ describe FiniteMachine, 'callbacks' do
261
230
  fsm.slow
262
231
  expect(fsm.current).to eql(:yellow)
263
232
  expect(called).to eql([
233
+ 'on_before_slow_1',
234
+ 'on_before_slow_2',
235
+ 'on_before',
264
236
  'on_exit_green_1',
265
237
  'on_exit_green_2',
266
238
  'on_exit',
267
- 'on_enter_slow_1',
268
- 'on_enter_slow_2',
269
- 'on_enter',
270
239
  'on_transition_yellow_1',
271
240
  'on_transition_yellow_2',
272
241
  'on_transition',
273
- 'on_transition_slow_1',
274
- 'on_transition_slow_2',
275
- 'on_transition',
276
242
  'on_enter_yellow_1',
277
243
  'on_enter_yellow_2',
278
244
  'on_enter',
279
- 'on_exit_slow_1',
280
- 'on_exit_slow_2',
281
- 'on_exit'
245
+ 'on_after_slow_1',
246
+ 'on_after_slow_2',
247
+ 'on_after'
282
248
  ])
283
249
  end
284
250
 
@@ -301,9 +267,8 @@ describe FiniteMachine, 'callbacks' do
301
267
  on_transition_yellow do |event| called << 'on_transition_yellow' end
302
268
 
303
269
  # event callbacks
304
- on_enter_slow do |event| called << 'on_enter_slow' end
305
- on_transition_slow do |event| called << 'on_transition_slow' end
306
- on_exit_slow do |event| called << 'on_exit_slow' end
270
+ on_before_slow do |event| called << 'on_before_slow' end
271
+ on_after_slow do |event| called << 'on_after_slow' end
307
272
  }
308
273
  end
309
274
 
@@ -311,18 +276,16 @@ describe FiniteMachine, 'callbacks' do
311
276
  fsm.slow
312
277
  expect(fsm.current).to eql(:yellow)
313
278
  expect(called).to eql([
279
+ 'on_before_slow',
314
280
  'on_exit_green',
315
- 'on_enter_slow',
316
281
  'on_transition_yellow',
317
- 'on_transition_slow',
318
282
  'on_enter_yellow',
319
- 'on_exit_slow'
283
+ 'on_after_slow'
320
284
  ])
321
285
  end
322
286
 
323
287
  it "passes event object to callback" do
324
288
  evt = nil
325
-
326
289
  fsm = FiniteMachine.define do
327
290
  initial :green
328
291
 
@@ -346,7 +309,6 @@ describe FiniteMachine, 'callbacks' do
346
309
 
347
310
  it "identifies the from state for callback event parameter" do
348
311
  evt = nil
349
-
350
312
  fsm = FiniteMachine.define do
351
313
  initial :green
352
314
 
@@ -395,11 +357,15 @@ describe FiniteMachine, 'callbacks' do
395
357
  }
396
358
 
397
359
  callbacks {
398
- # generic callbacks
360
+ # generic state callbacks
399
361
  on_enter(&callback)
400
362
  on_transition(&callback)
401
363
  on_exit(&callback)
402
364
 
365
+ # generic event callbacks
366
+ on_before(&callback)
367
+ on_after(&callback)
368
+
403
369
  # state callbacks
404
370
  on_enter :green, &callback
405
371
  on_enter :yellow, &callback
@@ -414,20 +380,15 @@ describe FiniteMachine, 'callbacks' do
414
380
  on_exit :red , &callback
415
381
 
416
382
  # event callbacks
417
- on_enter :slow , &callback
418
- on_enter :stop , &callback
419
- on_enter :ready, &callback
420
- on_enter :go , &callback
421
-
422
- on_transition :slow , &callback
423
- on_transition :stop , &callback
424
- on_transition :ready, &callback
425
- on_transition :go , &callback
426
-
427
- on_exit :slow , &callback
428
- on_exit :stop , &callback
429
- on_exit :ready, &callback
430
- on_exit :go , &callback
383
+ on_before :slow , &callback
384
+ on_before :stop , &callback
385
+ on_before :ready, &callback
386
+ on_before :go , &callback
387
+
388
+ on_after :slow , &callback
389
+ on_after :stop , &callback
390
+ on_after :ready, &callback
391
+ on_after :go , &callback
431
392
  }
432
393
  end
433
394
 
@@ -457,7 +418,27 @@ describe FiniteMachine, 'callbacks' do
457
418
  on_enter(:magic) { |event| called << 'on_enter'}
458
419
  }
459
420
  end
460
- }.to raise_error(FiniteMachine::InvalidCallbackNameError, /magic is not a valid callback name/)
421
+ }.to raise_error(FiniteMachine::InvalidCallbackNameError, /\"magic\" is not a valid callback name/)
422
+ end
423
+
424
+ it "doesn't allow to mix state callback with event name" do
425
+ expect {
426
+ FiniteMachine.define do
427
+ events { event :slow, :green => :yellow }
428
+
429
+ callbacks { on_enter_slow do |event| end }
430
+ end
431
+ }.to raise_error(FiniteMachine::InvalidCallbackNameError, "\"on_enter\" callback is a state listener and cannot be used with \"slow\" event name. Please use on_before or on_after instead.")
432
+ end
433
+
434
+ it "doesn't allow to mix event callback with state name" do
435
+ expect {
436
+ FiniteMachine.define do
437
+ events { event :slow, :green => :yellow }
438
+
439
+ callbacks { on_before_green do |event| end }
440
+ end
441
+ }.to raise_error(FiniteMachine::InvalidCallbackNameError, '"on_before" callback is an event listener and cannot be used with "green" state name. Please use on_enter, on_transition or on_exit instead.')
461
442
  end
462
443
 
463
444
  it "propagates exceptions raised inside callback" do
@@ -484,8 +465,8 @@ describe FiniteMachine, 'callbacks' do
484
465
  }
485
466
 
486
467
  callbacks {
487
- on_enter_stop do |event|
488
- called << 'on_enter_stop'
468
+ on_before_stop do |event|
469
+ called << 'on_before_stop'
489
470
  end
490
471
  }
491
472
  end
@@ -495,8 +476,8 @@ describe FiniteMachine, 'callbacks' do
495
476
  fsm.stop
496
477
  expect(fsm.current).to eql(:red)
497
478
  expect(called).to eql([
498
- 'on_enter_stop',
499
- 'on_enter_stop'
479
+ 'on_before_stop',
480
+ 'on_before_stop'
500
481
  ])
501
482
  end
502
483
 
@@ -552,6 +533,7 @@ describe FiniteMachine, 'callbacks' do
552
533
  }
553
534
 
554
535
  callbacks {
536
+ # state callbacks
555
537
  once_on_enter_green do |event| called << 'once_on_enter_green' end
556
538
  once_on_enter_yellow do |event| called << 'once_on_enter_yellow' end
557
539
 
@@ -560,6 +542,13 @@ describe FiniteMachine, 'callbacks' do
560
542
 
561
543
  once_on_exit_green do |event| called << 'once_on_exit_green' end
562
544
  once_on_exit_yellow do |event| called << 'once_on_exit_yellow' end
545
+
546
+ # event callbacks
547
+ once_on_before_slow do |event| called << 'once_on_before_slow' end
548
+ once_on_before_go do |event| called << 'once_on_before_go' end
549
+
550
+ once_on_after_slow do |event| called << 'once_on_after_slow' end
551
+ once_on_after_go do |event| called << 'once_on_after_go' end
563
552
  }
564
553
  end
565
554
  expect(fsm.current).to eql(:green)
@@ -570,12 +559,16 @@ describe FiniteMachine, 'callbacks' do
570
559
  fsm.slow
571
560
  expect(fsm.current).to eql(:yellow)
572
561
  expect(called).to eql([
562
+ 'once_on_before_slow',
573
563
  'once_on_exit_green',
574
564
  'once_on_transition_yellow',
575
565
  'once_on_enter_yellow',
566
+ 'once_on_after_slow',
567
+ 'once_on_before_go',
576
568
  'once_on_exit_yellow',
577
569
  'once_on_transition_green',
578
- 'once_on_enter_green'
570
+ 'once_on_enter_green',
571
+ 'once_on_after_go'
579
572
  ])
580
573
  end
581
574
 
@@ -633,35 +626,53 @@ describe FiniteMachine, 'callbacks' do
633
626
  }
634
627
 
635
628
  callbacks {
636
- on_enter_state do |event|
637
- callbacks << "enter_state_#{event.name}_#{event.from}_#{event.to}"
629
+ on_enter do |event|
630
+ callbacks << "enter_#{event.name}_#{event.from}_#{event.to}"
631
+ end
632
+ on_exit do |event|
633
+ callbacks << "exit_#{event.name}_#{event.from}_#{event.to}"
634
+ end
635
+ on_before do |event|
636
+ callbacks << "before_#{event.name}_#{event.from}_#{event.to}"
638
637
  end
639
- on_enter_event do |event|
640
- callbacks << "enter_event_#{event.name}_#{event.from}_#{event.to}"
638
+ on_after do |event|
639
+ callbacks << "after_#{event.name}_#{event.from}_#{event.to}"
641
640
  end
642
641
  }
643
642
  end
644
643
  expect(fsm.current).to eq(:initial)
645
644
  fsm.bump
646
645
  expect(callbacks).to eq([
647
- 'enter_event_bump_initial_low',
648
- 'enter_state_bump_initial_low'
646
+ 'before_bump_initial_low',
647
+ 'exit_bump_initial_low',
648
+ 'enter_bump_initial_low',
649
+ 'after_bump_initial_low'
649
650
  ])
650
651
  fsm.bump
651
652
  expect(callbacks).to eq([
652
- 'enter_event_bump_initial_low',
653
- 'enter_state_bump_initial_low',
654
- 'enter_event_bump_low_medium',
655
- 'enter_state_bump_low_medium'
653
+ 'before_bump_initial_low',
654
+ 'exit_bump_initial_low',
655
+ 'enter_bump_initial_low',
656
+ 'after_bump_initial_low',
657
+ 'before_bump_low_medium',
658
+ 'exit_bump_low_medium',
659
+ 'enter_bump_low_medium',
660
+ 'after_bump_low_medium'
656
661
  ])
657
662
  fsm.bump
658
663
  expect(callbacks).to eq([
659
- 'enter_event_bump_initial_low',
660
- 'enter_state_bump_initial_low',
661
- 'enter_event_bump_low_medium',
662
- 'enter_state_bump_low_medium',
663
- 'enter_event_bump_medium_high',
664
- 'enter_state_bump_medium_high'
664
+ 'before_bump_initial_low',
665
+ 'exit_bump_initial_low',
666
+ 'enter_bump_initial_low',
667
+ 'after_bump_initial_low',
668
+ 'before_bump_low_medium',
669
+ 'exit_bump_low_medium',
670
+ 'enter_bump_low_medium',
671
+ 'after_bump_low_medium',
672
+ 'before_bump_medium_high',
673
+ 'exit_bump_medium_high',
674
+ 'enter_bump_medium_high',
675
+ 'after_bump_medium_high'
665
676
  ])
666
677
  end
667
678
 
@@ -677,35 +688,35 @@ describe FiniteMachine, 'callbacks' do
677
688
  }
678
689
 
679
690
  callbacks {
680
- on_enter_state do |event|
681
- callbacks << "enter_state_#{event.name}_#{event.from}_#{event.to}"
691
+ on_enter do |event|
692
+ callbacks << "enter_#{event.name}_#{event.from}_#{event.to}"
682
693
  end
683
- on_enter_event do |event|
684
- callbacks << "enter_event_#{event.name}_#{event.from}_#{event.to}"
694
+ on_before do |event|
695
+ callbacks << "before_#{event.name}_#{event.from}_#{event.to}"
685
696
  end
686
697
  }
687
698
  end
688
699
  expect(fsm.current).to eq(:initial)
689
700
  fsm.bump
690
701
  expect(callbacks).to eq([
691
- 'enter_event_bump_initial_low',
692
- 'enter_state_bump_initial_low'
702
+ 'before_bump_initial_low',
703
+ 'enter_bump_initial_low'
693
704
  ])
694
705
  fsm.bump
695
706
  expect(callbacks).to eq([
696
- 'enter_event_bump_initial_low',
697
- 'enter_state_bump_initial_low',
698
- 'enter_event_bump_low_medium',
699
- 'enter_state_bump_low_medium'
707
+ 'before_bump_initial_low',
708
+ 'enter_bump_initial_low',
709
+ 'before_bump_low_medium',
710
+ 'enter_bump_low_medium'
700
711
  ])
701
712
  fsm.bump
702
713
  expect(callbacks).to eq([
703
- 'enter_event_bump_initial_low',
704
- 'enter_state_bump_initial_low',
705
- 'enter_event_bump_low_medium',
706
- 'enter_state_bump_low_medium',
707
- 'enter_event_bump_medium_high',
708
- 'enter_state_bump_medium_high'
714
+ 'before_bump_initial_low',
715
+ 'enter_bump_initial_low',
716
+ 'before_bump_low_medium',
717
+ 'enter_bump_low_medium',
718
+ 'before_bump_medium_high',
719
+ 'enter_bump_medium_high'
709
720
  ])
710
721
  end
711
722
  end