finite_machine 0.11.3 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +34 -0
  3. data/README.md +564 -569
  4. data/Rakefile +5 -1
  5. data/benchmarks/memory_profile.rb +11 -0
  6. data/benchmarks/memory_usage.rb +16 -9
  7. data/finite_machine.gemspec +10 -3
  8. data/lib/finite_machine.rb +34 -46
  9. data/lib/finite_machine/async_call.rb +5 -21
  10. data/lib/finite_machine/callable.rb +4 -4
  11. data/lib/finite_machine/catchable.rb +4 -2
  12. data/lib/finite_machine/choice_merger.rb +19 -19
  13. data/lib/finite_machine/const.rb +16 -0
  14. data/lib/finite_machine/definition.rb +2 -2
  15. data/lib/finite_machine/dsl.rb +66 -149
  16. data/lib/finite_machine/env.rb +4 -2
  17. data/lib/finite_machine/event_definition.rb +7 -15
  18. data/lib/finite_machine/{events_chain.rb → events_map.rb} +39 -51
  19. data/lib/finite_machine/hook_event.rb +60 -61
  20. data/lib/finite_machine/hooks.rb +44 -36
  21. data/lib/finite_machine/listener.rb +2 -2
  22. data/lib/finite_machine/logger.rb +5 -4
  23. data/lib/finite_machine/message_queue.rb +39 -30
  24. data/lib/finite_machine/observer.rb +55 -37
  25. data/lib/finite_machine/safety.rb +12 -10
  26. data/lib/finite_machine/state_definition.rb +3 -5
  27. data/lib/finite_machine/state_machine.rb +83 -64
  28. data/lib/finite_machine/state_parser.rb +51 -79
  29. data/lib/finite_machine/subscribers.rb +1 -1
  30. data/lib/finite_machine/threadable.rb +3 -1
  31. data/lib/finite_machine/transition.rb +30 -31
  32. data/lib/finite_machine/transition_builder.rb +23 -32
  33. data/lib/finite_machine/transition_event.rb +12 -11
  34. data/lib/finite_machine/two_phase_lock.rb +3 -1
  35. data/lib/finite_machine/undefined_transition.rb +5 -6
  36. data/lib/finite_machine/version.rb +2 -2
  37. data/spec/integration/system_spec.rb +36 -38
  38. data/spec/performance/benchmark_spec.rb +13 -21
  39. data/spec/unit/alias_target_spec.rb +22 -41
  40. data/spec/unit/async_callbacks_spec.rb +8 -13
  41. data/spec/unit/auto_methods_spec.rb +44 -0
  42. data/spec/unit/callable/call_spec.rb +1 -3
  43. data/spec/unit/callbacks_spec.rb +372 -463
  44. data/spec/unit/can_spec.rb +13 -23
  45. data/spec/unit/cancel_callbacks_spec.rb +46 -0
  46. data/spec/unit/choice_spec.rb +105 -141
  47. data/spec/unit/define_spec.rb +31 -31
  48. data/spec/unit/definition_spec.rb +24 -41
  49. data/spec/unit/event_names_spec.rb +6 -10
  50. data/spec/unit/events_map/add_spec.rb +23 -0
  51. data/spec/unit/events_map/choice_transition_spec.rb +25 -0
  52. data/spec/unit/events_map/clear_spec.rb +13 -0
  53. data/spec/unit/events_map/events_spec.rb +16 -0
  54. data/spec/unit/events_map/inspect_spec.rb +22 -0
  55. data/spec/unit/{events_chain → events_map}/match_transition_spec.rb +12 -14
  56. data/spec/unit/{events_chain → events_map}/move_to_spec.rb +14 -17
  57. data/spec/unit/events_map/states_for_spec.rb +17 -0
  58. data/spec/unit/events_spec.rb +91 -160
  59. data/spec/unit/handlers_spec.rb +34 -66
  60. data/spec/unit/hook_event/any_state_or_event_spec.rb +13 -0
  61. data/spec/unit/hook_event/build_spec.rb +1 -3
  62. data/spec/unit/hook_event/eql_spec.rb +1 -3
  63. data/spec/unit/hook_event/initialize_spec.rb +2 -4
  64. data/spec/unit/hook_event/notify_spec.rb +2 -4
  65. data/spec/unit/hooks/clear_spec.rb +1 -1
  66. data/spec/unit/hooks/{call_spec.rb → find_spec.rb} +4 -9
  67. data/spec/unit/hooks/inspect_spec.rb +16 -8
  68. data/spec/unit/hooks/register_spec.rb +4 -9
  69. data/spec/unit/if_unless_spec.rb +76 -115
  70. data/spec/unit/initial_spec.rb +50 -82
  71. data/spec/unit/inspect_spec.rb +14 -9
  72. data/spec/unit/is_spec.rb +12 -18
  73. data/spec/unit/log_transitions_spec.rb +4 -10
  74. data/spec/unit/logger_spec.rb +1 -3
  75. data/spec/unit/{event_queue_spec.rb → message_queue_spec.rb} +15 -8
  76. data/spec/unit/new_spec.rb +50 -0
  77. data/spec/unit/respond_to_spec.rb +2 -6
  78. data/spec/unit/state_parser/parse_spec.rb +9 -12
  79. data/spec/unit/states_spec.rb +12 -18
  80. data/spec/unit/subscribers_spec.rb +1 -3
  81. data/spec/unit/target_spec.rb +60 -93
  82. data/spec/unit/terminated_spec.rb +15 -25
  83. data/spec/unit/transition/check_conditions_spec.rb +16 -15
  84. data/spec/unit/transition/inspect_spec.rb +6 -6
  85. data/spec/unit/transition/matches_spec.rb +5 -7
  86. data/spec/unit/transition/states_spec.rb +5 -7
  87. data/spec/unit/transition/to_state_spec.rb +5 -13
  88. data/spec/unit/trigger_spec.rb +5 -9
  89. data/spec/unit/undefined_transition/eql_spec.rb +1 -3
  90. metadata +86 -49
  91. data/.gitignore +0 -18
  92. data/.rspec +0 -5
  93. data/.travis.yml +0 -27
  94. data/Gemfile +0 -16
  95. data/assets/finite_machine_logo.png +0 -0
  96. data/lib/finite_machine/async_proxy.rb +0 -55
  97. data/spec/unit/async_events_spec.rb +0 -107
  98. data/spec/unit/events_chain/add_spec.rb +0 -25
  99. data/spec/unit/events_chain/cancel_transitions_spec.rb +0 -22
  100. data/spec/unit/events_chain/choice_transition_spec.rb +0 -28
  101. data/spec/unit/events_chain/clear_spec.rb +0 -15
  102. data/spec/unit/events_chain/events_spec.rb +0 -18
  103. data/spec/unit/events_chain/inspect_spec.rb +0 -24
  104. data/spec/unit/events_chain/states_for_spec.rb +0 -17
  105. data/spec/unit/hook_event/infer_default_name_spec.rb +0 -13
  106. data/spec/unit/state_parser/inspect_spec.rb +0 -25
@@ -1,6 +1,4 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
1
+ # frozen_string_literal: true
4
2
 
5
3
  RSpec.describe FiniteMachine::Definition, '#alias_target' do
6
4
 
@@ -22,67 +20,51 @@ RSpec.describe FiniteMachine::Definition, '#alias_target' do
22
20
 
23
21
  it "aliases target" do
24
22
  car = Car.new
25
- fsm = FiniteMachine.new
26
- fsm.target(car)
23
+ fsm = FiniteMachine.new(car, alias_target: :delorean)
27
24
 
28
25
  expect(fsm.target).to eq(car)
29
26
  expect { fsm.car }.to raise_error(NoMethodError)
30
-
31
- fsm.alias_target(:delorean)
32
27
  expect(fsm.delorean).to eq(car)
33
28
  end
34
29
 
35
30
  it "scopes the target alias to a state machine instance" do
36
31
  delorean = Car.new
37
32
  batmobile = Car.new
38
- fsm_a = FiniteMachine.new
39
- fsm_a.target(delorean)
40
- fsm_b = FiniteMachine.new
41
- fsm_b.target(batmobile)
42
-
43
- fsm_a.alias_target(:delorean)
44
- fsm_b.alias_target(:batmobile)
33
+ fsm_a = FiniteMachine.new(delorean, alias_target: :delorean)
34
+ fsm_b = FiniteMachine.new(batmobile, alias_target: :batmobile)
45
35
 
46
36
  expect(fsm_a.delorean).to eq(delorean)
47
- expect { fsm_a.batmobile }.to raise_error(NoMethodError)
37
+ expect { fsm_a.batmobile }.to raise_error(NameError)
48
38
 
49
39
  expect(fsm_b.batmobile).to eq(batmobile)
50
- expect { fsm_b.delorean }.to raise_error(NoMethodError)
40
+ expect { fsm_b.delorean }.to raise_error(NameError)
51
41
  end
52
42
 
53
43
  context 'when inside definition' do
54
44
  before do
55
- class Engine < FiniteMachine::Definition
45
+ stub_const("Engine", Class.new(FiniteMachine::Definition) do
56
46
  initial :neutral
57
47
 
58
- alias_target :car
48
+ event :forward, [:reverse, :neutral] => :one
49
+ event :shift, :one => :two
50
+ event :shift, :two => :one
51
+ event :back, [:neutral, :one] => :reverse
59
52
 
60
- events {
61
- event :forward, [:reverse, :neutral] => :one
62
- event :shift, :one => :two
63
- event :shift, :two => :one
64
- event :back, [:neutral, :one] => :reverse
65
- }
53
+ on_enter :reverse do |event|
54
+ car.turn_reverse_lights_on
55
+ end
66
56
 
67
- callbacks {
68
- on_enter :reverse do |event|
69
- car.turn_reverse_lights_on
70
- end
57
+ on_exit :reverse do |event|
58
+ car.turn_reverse_lights_off
59
+ end
71
60
 
72
- on_exit :reverse do |event|
73
- car.turn_reverse_lights_off
74
- end
75
- }
76
-
77
- handlers {
78
- handle FiniteMachine::InvalidStateError do |exception| end
79
- }
80
- end
61
+ handle FiniteMachine::InvalidStateError do |exception| end
62
+ end)
81
63
  end
82
64
 
83
65
  it "creates unique instances" do
84
- engine_a = Engine.new
85
- engine_b = Engine.new
66
+ engine_a = Engine.new(alias_target: :car)
67
+ engine_b = Engine.new(alias_target: :car)
86
68
  expect(engine_a).not_to be(engine_b)
87
69
 
88
70
  engine_a.forward
@@ -92,8 +74,7 @@ RSpec.describe FiniteMachine::Definition, '#alias_target' do
92
74
 
93
75
  it "allows to create standalone machine" do
94
76
  car = Car.new
95
- engine = Engine.new
96
- engine.target car
77
+ engine = Engine.new(car, alias_target: :car)
97
78
  expect(engine.current).to eq(:neutral)
98
79
 
99
80
  engine.forward
@@ -1,23 +1,18 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe FiniteMachine, 'async callbacks' do
4
-
5
4
  it "permits async callback" do
6
5
  called = []
7
- fsm = FiniteMachine.define do
6
+ fsm = FiniteMachine.new do
8
7
  initial :green, silent: false
9
8
 
10
- events {
11
- event :slow, :green => :yellow
12
- event :go, :yellow => :green
13
- }
9
+ event :slow, :green => :yellow
10
+ event :go, :yellow => :green
14
11
 
15
- callbacks {
16
- on_enter :green, :async do |event| called << 'on_enter_green' end
17
- on_before :slow, :async do |event| called << 'on_before_slow' end
18
- on_exit :yellow, :async do |event| called << 'on_exit_yellow' end
19
- on_after :go, :async do |event| called << 'on_after_go' end
20
- }
12
+ on_enter :green, :async do |event| called << 'on_enter_green' end
13
+ on_before :slow, :async do |event| called << 'on_before_slow' end
14
+ on_exit :yellow, :async do |event| called << 'on_exit_yellow' end
15
+ on_after :go, :async do |event| called << 'on_after_go' end
21
16
  end
22
17
  fsm.slow
23
18
  fsm.go
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe FiniteMachine, ':auto_methods' do
4
+ it "allows turning off automatic methods generation" do
5
+ fsm = FiniteMachine.new(auto_methods: false) do
6
+ initial :green
7
+
8
+ event :slow, :green => :yellow
9
+ event :stop, :yellow => :red
10
+ event :ready, :red => :yellow
11
+ event :go, :yellow => :green
12
+
13
+ # allows for fluid callback names
14
+ once_on_enter_yellow do |event| 'once_on_enter_yellow' end
15
+ end
16
+
17
+ expect(fsm.respond_to?(:slow)).to eq(false)
18
+ expect { fsm.slow }.to raise_error(NoMethodError)
19
+ expect(fsm.current).to eq(:green)
20
+
21
+ fsm.trigger(:slow)
22
+ expect(fsm.current).to eq(:yellow)
23
+ end
24
+
25
+ it "allows to use any method name without auto method generation" do
26
+ fsm = FiniteMachine.new(auto_methods: false) do
27
+ initial :green
28
+
29
+ event :fail, :green => :red
30
+ end
31
+
32
+ fsm.trigger(:fail)
33
+ expect(fsm.current).to eq(:red)
34
+ end
35
+
36
+ it "detects dangerous event names" do
37
+ expect {
38
+ FiniteMachine.new do
39
+ event :trigger, :a => :b
40
+ end
41
+ }.to raise_error(FiniteMachine::AlreadyDefinedError)
42
+ end
43
+ end
44
+
@@ -1,6 +1,4 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
1
+ # frozen_string_literal: true
4
2
 
5
3
  RSpec.describe FiniteMachine::Callable, '#call' do
6
4
 
@@ -1,192 +1,180 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
1
+ # frozen_string_literal
4
2
 
5
3
  RSpec.describe FiniteMachine, 'callbacks' do
6
-
7
4
  it "triggers default init event" do
8
5
  called = []
9
- fsm = FiniteMachine.define do
6
+ fsm = FiniteMachine.new do
10
7
  initial :green, defer: true, silent: false
11
8
 
12
- callbacks {
13
- # generic state callbacks
14
- on_enter do |event| called << 'on_enter' end
15
- on_transition do |event| called << 'on_transition' end
16
- on_exit do |event| called << 'on_exit' end
9
+ # generic state callbacks
10
+ on_enter do |event| called << 'on_enter' end
11
+ on_transition do |event| called << 'on_transition' end
12
+ on_exit do |event| called << 'on_exit' end
17
13
 
18
- # generic event callbacks
19
- on_before do |event| called << 'on_before' end
20
- on_after do |event| called << 'on_after' end
14
+ # generic event callbacks
15
+ on_before any_event do |event| called << 'on_before' end
16
+ on_after do |event| called << 'on_after' end
21
17
 
22
- # state callbacks
23
- on_enter :none do |event| called << 'on_enter_none' end
24
- on_enter :green do |event| called << 'on_enter_green' end
18
+ # state callbacks
19
+ on_enter :none do |event| called << 'on_enter_none' end
20
+ on_enter :green do |event| called << 'on_enter_green' end
25
21
 
26
- on_transition :none do |event| called << 'on_transition_none' end
27
- on_transition :green do |event| called << 'on_transition_green' end
22
+ on_transition :none do |event| called << 'on_transition_none' end
23
+ on_transition :green do |event| called << 'on_transition_green' end
28
24
 
29
- on_exit :none do |event| called << 'on_exit_none' end
30
- on_exit :green do |event| called << 'on_exit_green' end
25
+ on_exit :none do |event| called << 'on_exit_none' end
26
+ on_exit :green do |event| called << 'on_exit_green' end
31
27
 
32
- # event callbacks
33
- on_before :init do |event| called << 'on_before_init' end
34
- on_after :init do |event| called << 'on_after_init' end
35
- }
28
+ # event callbacks
29
+ on_before :init do |event| called << 'on_before_init' end
30
+ on_after :init do |event| called << 'on_after_init' end
36
31
  end
37
32
 
38
33
  expect(fsm.current).to eql(:none)
39
34
  fsm.init
40
35
  expect(called).to eql([
41
- 'on_before_init',
42
36
  'on_before',
43
- 'on_exit_none',
37
+ 'on_before_init',
44
38
  'on_exit',
45
- 'on_transition_green',
39
+ 'on_exit_none',
46
40
  'on_transition',
47
- 'on_enter_green',
41
+ 'on_transition_green',
48
42
  'on_enter',
49
- 'on_after_init',
50
- 'on_after'
43
+ 'on_enter_green',
44
+ 'on_after',
45
+ 'on_after_init'
51
46
  ])
52
47
  end
53
48
 
54
49
  it "executes callbacks in order" do
55
50
  called = []
56
- fsm = FiniteMachine.define do
51
+ fsm = FiniteMachine.new do
57
52
  initial :green, silent: false
58
53
 
59
- events {
60
- event :slow, :green => :yellow
61
- event :stop, :yellow => :red
62
- event :ready, :red => :yellow
63
- event :go, :yellow => :green
64
- }
65
-
66
- callbacks {
67
- # generic callbacks
68
- on_enter do |event| called << 'on_enter' end
69
- on_transition do |event| called << 'on_transition' end
70
- on_exit do |event| called << 'on_exit' end
71
-
72
- on_before do |event| called << 'on_before' end
73
- on_after do |event| called << 'on_after' end
74
-
75
- # state callbacks
76
- on_enter :green do |event| called << 'on_enter_green' end
77
- on_enter :yellow do |event| called << "on_enter_yellow" end
78
- on_enter :red do |event| called << "on_enter_red" end
79
-
80
- on_transition :green do |event| called << 'on_transition_green' end
81
- on_transition :yellow do |event| called << "on_transition_yellow" end
82
- on_transition :red do |event| called << "on_transition_red" end
83
-
84
- on_exit :green do |event| called << 'on_exit_green' end
85
- on_exit :yellow do |event| called << "on_exit_yellow" end
86
- on_exit :red do |event| called << "on_exit_red" end
87
-
88
- # event callbacks
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
98
- }
54
+ event :slow, :green => :yellow
55
+ event :stop, :yellow => :red
56
+ event :ready, :red => :yellow
57
+ event :go, :yellow => :green
58
+
59
+ # generic callbacks
60
+ on_enter do |event| called << 'on_enter' end
61
+ on_transition do |event| called << 'on_transition' end
62
+ on_exit do |event| called << 'on_exit' end
63
+
64
+ on_before do |event| called << 'on_before' end
65
+ on_after do |event| called << 'on_after' end
66
+
67
+ # state callbacks
68
+ on_enter :green do |event| called << 'on_enter_green' end
69
+ on_enter :yellow do |event| called << "on_enter_yellow" end
70
+ on_enter :red do |event| called << "on_enter_red" end
71
+
72
+ on_transition :green do |event| called << 'on_transition_green' end
73
+ on_transition :yellow do |event| called << "on_transition_yellow" end
74
+ on_transition :red do |event| called << "on_transition_red" end
75
+
76
+ on_exit :green do |event| called << 'on_exit_green' end
77
+ on_exit :yellow do |event| called << "on_exit_yellow" end
78
+ on_exit :red do |event| called << "on_exit_red" end
79
+
80
+ # event callbacks
81
+ on_before :slow do |event| called << 'on_before_slow' end
82
+ on_before :stop do |event| called << "on_before_stop" end
83
+ on_before :ready do |event| called << "on_before_ready" end
84
+ on_before :go do |event| called << "on_before_go" end
85
+
86
+ on_after :slow do |event| called << 'on_after_slow' end
87
+ on_after :stop do |event| called << "on_after_stop" end
88
+ on_after :ready do |event| called << "on_after_ready" end
89
+ on_after :go do |event| called << "on_after_go" end
99
90
  end
100
91
 
101
92
  expect(fsm.current).to eq(:green)
102
93
  expect(called).to eq([
103
94
  'on_before',
104
95
  'on_exit',
105
- 'on_transition_green',
106
96
  'on_transition',
107
- 'on_enter_green',
97
+ 'on_transition_green',
108
98
  'on_enter',
99
+ 'on_enter_green',
109
100
  'on_after'
110
101
  ])
111
102
 
112
103
  called = []
113
104
  fsm.slow
114
105
  expect(called).to eql([
115
- 'on_before_slow',
116
106
  'on_before',
117
- 'on_exit_green',
107
+ 'on_before_slow',
118
108
  'on_exit',
119
- 'on_transition_yellow',
109
+ 'on_exit_green',
120
110
  'on_transition',
121
- 'on_enter_yellow',
111
+ 'on_transition_yellow',
122
112
  'on_enter',
123
- 'on_after_slow',
124
- 'on_after'
113
+ 'on_enter_yellow',
114
+ 'on_after',
115
+ 'on_after_slow'
125
116
  ])
126
117
 
127
118
  called = []
128
119
  fsm.stop
129
120
  expect(called).to eql([
130
- 'on_before_stop',
131
121
  'on_before',
132
- 'on_exit_yellow',
122
+ 'on_before_stop',
133
123
  'on_exit',
134
- 'on_transition_red',
124
+ 'on_exit_yellow',
135
125
  'on_transition',
136
- 'on_enter_red',
126
+ 'on_transition_red',
137
127
  'on_enter',
138
- 'on_after_stop',
139
- 'on_after'
128
+ 'on_enter_red',
129
+ 'on_after',
130
+ 'on_after_stop'
140
131
  ])
141
132
 
142
133
  called = []
143
134
  fsm.ready
144
135
  expect(called).to eql([
145
- 'on_before_ready',
146
136
  'on_before',
147
- 'on_exit_red',
137
+ 'on_before_ready',
148
138
  'on_exit',
149
- 'on_transition_yellow',
139
+ 'on_exit_red',
150
140
  'on_transition',
151
- 'on_enter_yellow',
141
+ 'on_transition_yellow',
152
142
  'on_enter',
153
- 'on_after_ready',
154
- 'on_after'
143
+ 'on_enter_yellow',
144
+ 'on_after',
145
+ 'on_after_ready'
155
146
  ])
156
147
 
157
148
  called = []
158
149
  fsm.go
159
150
  expect(called).to eql([
160
- 'on_before_go',
161
151
  'on_before',
162
- 'on_exit_yellow',
152
+ 'on_before_go',
163
153
  'on_exit',
164
- 'on_transition_green',
154
+ 'on_exit_yellow',
165
155
  'on_transition',
166
- 'on_enter_green',
156
+ 'on_transition_green',
167
157
  'on_enter',
168
- 'on_after_go',
169
- 'on_after'
158
+ 'on_enter_green',
159
+ 'on_after',
160
+ 'on_after_go'
170
161
  ])
171
162
  end
172
163
 
173
164
  it "maintains transition execution sequence from UML statechart" do
174
165
  called = []
175
- fsm = FiniteMachine.define do
166
+ fsm = FiniteMachine.new do
176
167
  initial :previous, silent: false
177
168
 
178
- events {
179
- event :go, :previous => :next, if: -> { called << 'guard'; true}
180
- }
181
-
182
- callbacks {
183
- on_exit { |event| called << "exit_#{event.from}" }
184
- on_before { |event| called << "before_#{event.name}" }
185
- on_transition { |event| called << "transition_#{event.from}_#{event.to}"}
186
- on_enter { |event| called << "enter_#{event.to}"}
187
- on_after { |event| called << "after_#{event.name}" }
188
- }
169
+ event :go, :previous => :next, if: -> { called << 'guard'; true}
170
+
171
+ on_exit { |event| called << "exit_#{event.from}" }
172
+ on_before { |event| called << "before_#{event.name}" }
173
+ on_transition { |event| called << "transition_#{event.from}_#{event.to}"}
174
+ on_enter { |event| called << "enter_#{event.to}"}
175
+ on_after { |event| called << "after_#{event.name}" }
189
176
  end
177
+
190
178
  expect(fsm.current).to eq(:previous)
191
179
  fsm.go
192
180
  expect(called).to eq([
@@ -206,40 +194,36 @@ RSpec.describe FiniteMachine, 'callbacks' do
206
194
 
207
195
  it "allows multiple callbacks for the same state" do
208
196
  called = []
209
- fsm = FiniteMachine.define do
197
+ fsm = FiniteMachine.new do
210
198
  initial :green, silent: false
211
199
 
212
- events {
213
- event :slow, :green => :yellow
214
- event :stop, :yellow => :red
215
- event :ready, :red => :yellow
216
- event :go, :yellow => :green
217
- }
218
-
219
- callbacks {
220
- # generic state callbacks
221
- on_enter do |event| called << 'on_enter' end
222
- on_transition do |event| called << 'on_transition' end
223
- on_exit do |event| called << 'on_exit' end
224
-
225
- # generic event callbacks
226
- on_before do |event| called << 'on_before' end
227
- on_after do |event| called << 'on_after' end
228
-
229
- # state callbacks
230
- on_exit :green do |event| called << 'on_exit_green_1' end
231
- on_exit :green do |event| called << 'on_exit_green_2' end
232
- on_enter :yellow do |event| called << 'on_enter_yellow_1' end
233
- on_enter :yellow do |event| called << 'on_enter_yellow_2' end
234
- on_transition :yellow do |event| called << 'on_transition_yellow_1' end
235
- on_transition :yellow do |event| called << 'on_transition_yellow_2' end
236
-
237
- # event callbacks
238
- on_before :slow do |event| called << 'on_before_slow_1' end
239
- on_before :slow do |event| called << 'on_before_slow_2' end
240
- on_after :slow do |event| called << 'on_after_slow_1' end
241
- on_after :slow do |event| called << 'on_after_slow_2' end
242
- }
200
+ event :slow, :green => :yellow
201
+ event :stop, :yellow => :red
202
+ event :ready, :red => :yellow
203
+ event :go, :yellow => :green
204
+
205
+ # generic state callbacks
206
+ on_enter do |event| called << 'on_enter' end
207
+ on_transition do |event| called << 'on_transition' end
208
+ on_exit do |event| called << 'on_exit' end
209
+
210
+ # generic event callbacks
211
+ on_before do |event| called << 'on_before' end
212
+ on_after do |event| called << 'on_after' end
213
+
214
+ # state callbacks
215
+ on_exit :green do |event| called << 'on_exit_green_1' end
216
+ on_exit :green do |event| called << 'on_exit_green_2' end
217
+ on_enter :yellow do |event| called << 'on_enter_yellow_1' end
218
+ on_enter :yellow do |event| called << 'on_enter_yellow_2' end
219
+ on_transition :yellow do |event| called << 'on_transition_yellow_1' end
220
+ on_transition :yellow do |event| called << 'on_transition_yellow_2' end
221
+
222
+ # event callbacks
223
+ on_before :slow do |event| called << 'on_before_slow_1' end
224
+ on_before :slow do |event| called << 'on_before_slow_2' end
225
+ on_after :slow do |event| called << 'on_after_slow_1' end
226
+ on_after :slow do |event| called << 'on_after_slow_2' end
243
227
  end
244
228
 
245
229
  expect(fsm.current).to eql(:green)
@@ -254,46 +238,42 @@ RSpec.describe FiniteMachine, 'callbacks' do
254
238
  fsm.slow
255
239
  expect(fsm.current).to eql(:yellow)
256
240
  expect(called).to eql([
241
+ 'on_before',
257
242
  'on_before_slow_1',
258
243
  'on_before_slow_2',
259
- 'on_before',
244
+ 'on_exit',
260
245
  'on_exit_green_1',
261
246
  'on_exit_green_2',
262
- 'on_exit',
247
+ 'on_transition',
263
248
  'on_transition_yellow_1',
264
249
  'on_transition_yellow_2',
265
- 'on_transition',
250
+ 'on_enter',
266
251
  'on_enter_yellow_1',
267
252
  'on_enter_yellow_2',
268
- 'on_enter',
253
+ 'on_after',
269
254
  'on_after_slow_1',
270
- 'on_after_slow_2',
271
- 'on_after'
255
+ 'on_after_slow_2'
272
256
  ])
273
257
  end
274
258
 
275
259
  it "allows for fluid callback definition" do
276
260
  called = []
277
- fsm = FiniteMachine.define do
261
+ fsm = FiniteMachine.new do
278
262
  initial :green
279
263
 
280
- events {
281
- event :slow, :green => :yellow
282
- event :stop, :yellow => :red
283
- event :ready, :red => :yellow
284
- event :go, :yellow => :green
285
- }
286
-
287
- callbacks {
288
- # state callbacks
289
- on_exit_green do |event| called << 'on_exit_green' end
290
- on_enter_yellow do |event| called << 'on_enter_yellow' end
291
- on_transition_yellow do |event| called << 'on_transition_yellow' end
292
-
293
- # event callbacks
294
- on_before_slow do |event| called << 'on_before_slow' end
295
- on_after_slow do |event| called << 'on_after_slow' end
296
- }
264
+ event :slow, :green => :yellow
265
+ event :stop, :yellow => :red
266
+ event :ready, :red => :yellow
267
+ event :go, :yellow => :green
268
+
269
+ # state callbacks
270
+ on_exit_green do |event| called << 'on_exit_green' end
271
+ on_enter_yellow do |event| called << 'on_enter_yellow' end
272
+ on_transition_yellow do |event| called << 'on_transition_yellow' end
273
+
274
+ # event callbacks
275
+ on_before_slow do |event| called << 'on_before_slow' end
276
+ on_after_slow do |event| called << 'on_after_slow' end
297
277
  end
298
278
 
299
279
  called = []
@@ -310,16 +290,12 @@ RSpec.describe FiniteMachine, 'callbacks' do
310
290
 
311
291
  it "passes event object to callback" do
312
292
  evt = nil
313
- fsm = FiniteMachine.define do
293
+ fsm = FiniteMachine.new do
314
294
  initial :green
315
295
 
316
- events {
317
- event :slow, :green => :yellow
318
- }
296
+ event :slow, :green => :yellow
319
297
 
320
- callbacks {
321
- on_enter(:yellow) { |e| evt = e }
322
- }
298
+ on_enter(:yellow) { |e| evt = e }
323
299
  end
324
300
 
325
301
  expect(fsm.current).to eql(:green)
@@ -333,17 +309,13 @@ RSpec.describe FiniteMachine, 'callbacks' do
333
309
 
334
310
  it "identifies the from state for callback event parameter" do
335
311
  evt = nil
336
- fsm = FiniteMachine.define do
312
+ fsm = FiniteMachine.new do
337
313
  initial :green
338
314
 
339
- events {
340
- event :slow, [:red, :blue, :green] => :yellow
341
- event :fast, :red => :purple
342
- }
315
+ event :slow, [:red, :blue, :green] => :yellow
316
+ event :fast, :red => :purple
343
317
 
344
- callbacks {
345
- on_enter(:yellow) { |e| evt = e }
346
- }
318
+ on_enter(:yellow) { |e| evt = e }
347
319
  end
348
320
 
349
321
  expect(fsm.current).to eql(:green)
@@ -366,54 +338,47 @@ RSpec.describe FiniteMachine, 'callbacks' do
366
338
  target.expect(b).to target.eql(expected[:b])
367
339
  target.expect(c).to target.eql(expected[:c])
368
340
  }
369
- context = self
370
341
 
371
- fsm = FiniteMachine.define do
342
+ fsm = FiniteMachine.new(self) do
372
343
  initial :green
373
344
 
374
- target context
375
-
376
- events {
377
- event :slow, :green => :yellow
378
- event :stop, :yellow => :red
379
- event :ready, :red => :yellow
380
- event :go, :yellow => :green
381
- }
382
-
383
- callbacks {
384
- # generic state callbacks
385
- on_enter(&callback)
386
- on_transition(&callback)
387
- on_exit(&callback)
388
-
389
- # generic event callbacks
390
- on_before(&callback)
391
- on_after(&callback)
392
-
393
- # state callbacks
394
- on_enter :green, &callback
395
- on_enter :yellow, &callback
396
- on_enter :red, &callback
397
-
398
- on_transition :green , &callback
399
- on_transition :yellow, &callback
400
- on_transition :red , &callback
401
-
402
- on_exit :green , &callback
403
- on_exit :yellow, &callback
404
- on_exit :red , &callback
405
-
406
- # event callbacks
407
- on_before :slow , &callback
408
- on_before :stop , &callback
409
- on_before :ready, &callback
410
- on_before :go , &callback
411
-
412
- on_after :slow , &callback
413
- on_after :stop , &callback
414
- on_after :ready, &callback
415
- on_after :go , &callback
416
- }
345
+ event :slow, :green => :yellow
346
+ event :stop, :yellow => :red
347
+ event :ready, :red => :yellow
348
+ event :go, :yellow => :green
349
+
350
+ # generic state callbacks
351
+ on_enter(&callback)
352
+ on_transition(&callback)
353
+ on_exit(&callback)
354
+
355
+ # generic event callbacks
356
+ on_before(&callback)
357
+ on_after(&callback)
358
+
359
+ # state callbacks
360
+ on_enter :green, &callback
361
+ on_enter :yellow, &callback
362
+ on_enter :red, &callback
363
+
364
+ on_transition :green , &callback
365
+ on_transition :yellow, &callback
366
+ on_transition :red , &callback
367
+
368
+ on_exit :green , &callback
369
+ on_exit :yellow, &callback
370
+ on_exit :red , &callback
371
+
372
+ # event callbacks
373
+ on_before :slow , &callback
374
+ on_before :stop , &callback
375
+ on_before :ready, &callback
376
+ on_before :go , &callback
377
+
378
+ on_after :slow , &callback
379
+ on_after :stop , &callback
380
+ on_after :ready, &callback
381
+ on_after :go , &callback
417
382
  end
418
383
 
419
384
  expected = {name: :slow, from: :green, to: :yellow, a: 1, b: 2, c: 3}
@@ -441,63 +406,55 @@ RSpec.describe FiniteMachine, 'callbacks' do
441
406
  target.expect(c).to target.eql(expected[:c])
442
407
  }
443
408
 
444
- context = self
445
-
446
- fsm = FiniteMachine.define do
409
+ fsm = FiniteMachine.new(self) do
447
410
  initial :red
448
411
 
449
- target context
450
-
451
- events {
452
- event :power_on, :off => :red
453
- event :power_off, :any => :off
454
- event :go, :red => :green
455
- event :slow, :green => :yellow
456
- event :stop, :yellow => :red
457
- }
458
-
459
- callbacks {
460
- # generic state callbacks
461
- on_enter(&callback)
462
- on_transition(&callback)
463
- on_exit(&callback)
464
-
465
- # generic event callbacks
466
- on_before(&callback)
467
- on_after(&callback)
468
-
469
- # state callbacks
470
- on_enter :green, &callback
471
- on_enter :yellow, &callback
472
- on_enter :red, &callback
473
- on_enter :off, &callback
474
- on_enter :off, &callback
475
-
476
- on_transition :green, &callback
477
- on_transition :yellow, &callback
478
- on_transition :red, &callback
479
- on_transition :off, &callback
480
- on_transition :off, &callback
481
-
482
- on_exit :green, &callback
483
- on_exit :yellow, &callback
484
- on_exit :red, &callback
485
- on_exit :off, &callback
486
- on_exit :off, &callback
487
-
488
- # event callbacks
489
- on_before :power_on, &callback
490
- on_before :power_off, &callback
491
- on_before :go, &callback
492
- on_before :slow, &callback
493
- on_before :stop, &callback
494
-
495
- on_after :power_on, &callback
496
- on_after :power_off, &callback
497
- on_after :go, &callback
498
- on_after :slow, &callback
499
- on_after :stop, &callback
500
- }
412
+ event :power_on, :off => :red
413
+ event :power_off, any_state => :off
414
+ event :go, :red => :green
415
+ event :slow, :green => :yellow
416
+ event :stop, :yellow => :red
417
+
418
+ # generic state callbacks
419
+ on_enter(&callback)
420
+ on_transition(&callback)
421
+ on_exit(&callback)
422
+
423
+ # generic event callbacks
424
+ on_before(&callback)
425
+ on_after(&callback)
426
+
427
+ # state callbacks
428
+ on_enter :green, &callback
429
+ on_enter :yellow, &callback
430
+ on_enter :red, &callback
431
+ on_enter :off, &callback
432
+ on_enter :off, &callback
433
+
434
+ on_transition :green, &callback
435
+ on_transition :yellow, &callback
436
+ on_transition :red, &callback
437
+ on_transition :off, &callback
438
+ on_transition :off, &callback
439
+
440
+ on_exit :green, &callback
441
+ on_exit :yellow, &callback
442
+ on_exit :red, &callback
443
+ on_exit :off, &callback
444
+ on_exit :off, &callback
445
+
446
+ # event callbacks
447
+ on_before :power_on, &callback
448
+ on_before :power_off, &callback
449
+ on_before :go, &callback
450
+ on_before :slow, &callback
451
+ on_before :stop, &callback
452
+
453
+ on_after :power_on, &callback
454
+ on_after :power_off, &callback
455
+ on_after :go, &callback
456
+ on_after :slow, &callback
457
+ on_after :stop, &callback
501
458
  end
502
459
 
503
460
  expect(fsm.current).to eq(:red)
@@ -517,47 +474,43 @@ RSpec.describe FiniteMachine, 'callbacks' do
517
474
 
518
475
  it "raises an error with invalid callback name" do
519
476
  expect {
520
- FiniteMachine.define do
477
+ FiniteMachine.new do
521
478
  initial :green
522
479
 
523
- events {
524
- event :slow, :green => :yellow
525
- }
480
+ event :slow, :green => :yellow
526
481
 
527
- callbacks {
528
- on_enter(:magic) { |event| called << 'on_enter'}
529
- }
482
+ on_enter(:magic) { |event| called << 'on_enter'}
530
483
  end
531
484
  }.to raise_error(FiniteMachine::InvalidCallbackNameError, /\"magic\" is not a valid callback name/)
532
485
  end
533
486
 
534
487
  it "doesn't allow to mix state callback with event name" do
535
488
  expect {
536
- FiniteMachine.define do
537
- events { event :slow, :green => :yellow }
489
+ FiniteMachine.new do
490
+ event :slow, :green => :yellow
538
491
 
539
- callbacks { on_enter_slow do |event| end }
492
+ on_enter_slow do |event| end
540
493
  end
541
494
  }.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.")
542
495
  end
543
496
 
544
497
  it "doesn't allow to mix event callback with state name" do
545
498
  expect {
546
- FiniteMachine.define do
547
- events { event :slow, :green => :yellow }
499
+ FiniteMachine.new do
500
+ event :slow, :green => :yellow
548
501
 
549
- callbacks { on_before_green do |event| end }
502
+ on_before_green do |event| end
550
503
  end
551
504
  }.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.')
552
505
  end
553
506
 
554
507
  it "propagates exceptions raised inside callback" do
555
- fsm = FiniteMachine.define do
508
+ fsm = FiniteMachine.new do
556
509
  initial :green
557
510
 
558
- events { event :slow, :green => :yellow }
511
+ event :slow, :green => :yellow
559
512
 
560
- callbacks { on_enter(:yellow) { raise RuntimeError } }
513
+ on_enter(:yellow) { raise RuntimeError }
561
514
  end
562
515
 
563
516
  expect(fsm.current).to eql(:green)
@@ -566,19 +519,15 @@ RSpec.describe FiniteMachine, 'callbacks' do
566
519
 
567
520
  it "executes callbacks with multiple 'from' transitions" do
568
521
  called = []
569
- fsm = FiniteMachine.define do
522
+ fsm = FiniteMachine.new do
570
523
  initial :green
571
524
 
572
- events {
573
- event :stop, :green => :yellow
574
- event :stop, :yellow => :red
575
- }
525
+ event :stop, :green => :yellow
526
+ event :stop, :yellow => :red
576
527
 
577
- callbacks {
578
- on_before_stop do |event|
579
- called << 'on_before_stop'
580
- end
581
- }
528
+ on_before_stop do |event|
529
+ called << 'on_before_stop'
530
+ end
582
531
  end
583
532
  expect(fsm.current).to eql(:green)
584
533
  fsm.stop
@@ -593,15 +542,13 @@ RSpec.describe FiniteMachine, 'callbacks' do
593
542
 
594
543
  it "allows to define callbacks on machine instance" do
595
544
  called = []
596
- fsm = FiniteMachine.define do
545
+ fsm = FiniteMachine.new do
597
546
  initial :green
598
547
 
599
- events {
600
- event :slow, :green => :yellow
601
- event :stop, :yellow => :red
602
- event :ready, :red => :yellow
603
- event :go, :yellow => :green
604
- }
548
+ event :slow, :green => :yellow
549
+ event :stop, :yellow => :red
550
+ event :ready, :red => :yellow
551
+ event :go, :yellow => :green
605
552
  end
606
553
 
607
554
  fsm.on_enter_yellow do |event|
@@ -616,52 +563,46 @@ RSpec.describe FiniteMachine, 'callbacks' do
616
563
  end
617
564
 
618
565
  it "raises error for unknown callback" do
619
- expect { FiniteMachine.define do
620
- initial :green
566
+ expect {
567
+ FiniteMachine.new do
568
+ initial :green
621
569
 
622
- events {
623
570
  event :slow, :green => :yellow
624
571
  event :stop, :yellow => :red
625
572
  event :ready, :red => :yellow
626
573
  event :go, :yellow => :green
627
- }
628
574
 
629
- callbacks {
630
575
  on_enter_unknown do |event| end
631
- }
632
- end }.to raise_error(NoMethodError)
576
+ end
577
+ }.to raise_error(NameError, /`on_enter_unknown'/)
633
578
  end
634
579
 
635
580
  it "triggers callbacks only once" do
636
581
  called = []
637
- fsm = FiniteMachine.define do
582
+ fsm = FiniteMachine.new do
638
583
  initial :green, silent: false
639
584
 
640
- events {
641
- event :slow, :green => :yellow
642
- event :go, :yellow => :green
643
- }
644
-
645
- callbacks {
646
- # state callbacks
647
- once_on_enter_green do |event| called << 'once_on_enter_green' end
648
- once_on_enter_yellow do |event| called << 'once_on_enter_yellow' end
649
-
650
- once_on_transition_green do |event| called << 'once_on_transition_green' end
651
- once_on_transition_yellow do |event| called << 'once_on_transition_yellow' end
652
- once_on_exit_none do |event| called << 'once_on_exit_none' end
653
- once_on_exit_green do |event| called << 'once_on_exit_green' end
654
- once_on_exit_yellow do |event| called << 'once_on_exit_yellow' end
655
-
656
- # event callbacks
657
- once_on_before_init do |event| called << 'once_on_before_init' end
658
- once_on_before_slow do |event| called << 'once_on_before_slow' end
659
- once_on_before_go do |event| called << 'once_on_before_go' end
660
-
661
- once_on_after_init do |event| called << 'once_on_after_init' end
662
- once_on_after_slow do |event| called << 'once_on_after_slow' end
663
- once_on_after_go do |event| called << 'once_on_after_go' end
664
- }
585
+ event :slow, :green => :yellow
586
+ event :go, :yellow => :green
587
+
588
+ # state callbacks
589
+ once_on_enter_green do |event| called << 'once_on_enter_green' end
590
+ once_on_enter_yellow do |event| called << 'once_on_enter_yellow' end
591
+
592
+ once_on_transition_green do |event| called << 'once_on_transition_green' end
593
+ once_on_transition_yellow do |event| called << 'once_on_transition_yellow' end
594
+ once_on_exit_none do |event| called << 'once_on_exit_none' end
595
+ once_on_exit_green do |event| called << 'once_on_exit_green' end
596
+ once_on_exit_yellow do |event| called << 'once_on_exit_yellow' end
597
+
598
+ # event callbacks
599
+ once_on_before_init do |event| called << 'once_on_before_init' end
600
+ once_on_before_slow do |event| called << 'once_on_before_slow' end
601
+ once_on_before_go do |event| called << 'once_on_before_go' end
602
+
603
+ once_on_after_init do |event| called << 'once_on_after_init' end
604
+ once_on_after_slow do |event| called << 'once_on_after_slow' end
605
+ once_on_after_go do |event| called << 'once_on_after_go' end
665
606
  end
666
607
  expect(fsm.current).to eql(:green)
667
608
  fsm.slow
@@ -687,83 +628,31 @@ RSpec.describe FiniteMachine, 'callbacks' do
687
628
  ])
688
629
  end
689
630
 
690
- it "cancels transition on event callback" do
691
- fsm = FiniteMachine.define do
692
- initial :green
693
-
694
- events {
695
- event :slow, :green => :yellow
696
- event :go, :yellow => :green
697
- }
698
-
699
- callbacks {
700
- on_exit :green do |event|
701
- FiniteMachine::CANCELLED
702
- end
703
- }
704
- end
705
-
706
- expect(fsm.current).to eql(:green)
707
- fsm.slow
708
- expect(fsm.current).to eql(:green)
709
- end
710
-
711
- it "stops executing callbacks when cancelled" do
712
- called = []
713
-
714
- fsm = FiniteMachine.define do
715
- initial :initial
716
-
717
- events { event :bump, initial: :low }
718
-
719
- callbacks {
720
- on_before do |event|
721
- called << "enter_#{event.name}_#{event.from}_#{event.to}"
722
-
723
- FiniteMachine::CANCELLED
724
- end
725
-
726
- on_exit :initial do |event| called << "exit_initial" end
727
- on_exit do |event| called << "exit_any" end
728
- on_enter :low do |event| called << "enter_low" end
729
- on_after :bump do |event| called << "after_#{event.name}" end
730
- on_after do |event| called << "after_any" end
731
- }
732
- end
733
-
734
- fsm.bump
735
-
736
- expect(called).to eq(['enter_bump_initial_low'])
737
- end
738
-
739
631
  xit "groups callbacks"
740
632
 
741
633
  it "groups states from separate events with the same name" do
742
634
  callbacks = []
743
- fsm = FiniteMachine.define do
635
+ fsm = FiniteMachine.new do
744
636
  initial :initial, silent: false
745
637
 
746
- events {
747
- event :bump, :initial => :low
748
- event :bump, :low => :medium
749
- event :bump, :medium => :high
750
- }
751
-
752
- callbacks {
753
- on_enter do |event|
754
- callbacks << "enter_#{event.name}_#{event.from}_#{event.to}"
755
- end
756
- on_exit do |event|
757
- callbacks << "exit_#{event.name}_#{event.from}_#{event.to}"
758
- end
759
- on_before do |event|
760
- callbacks << "before_#{event.name}_#{event.from}_#{event.to}"
761
- end
762
- on_after do |event|
763
- callbacks << "after_#{event.name}_#{event.from}_#{event.to}"
764
- end
765
- }
638
+ event :bump, :initial => :low
639
+ event :bump, :low => :medium
640
+ event :bump, :medium => :high
641
+
642
+ on_enter do |event|
643
+ callbacks << "enter_#{event.name}_#{event.from}_#{event.to}"
644
+ end
645
+ on_exit do |event|
646
+ callbacks << "exit_#{event.name}_#{event.from}_#{event.to}"
647
+ end
648
+ on_before do |event|
649
+ callbacks << "before_#{event.name}_#{event.from}_#{event.to}"
650
+ end
651
+ on_after do |event|
652
+ callbacks << "after_#{event.name}_#{event.from}_#{event.to}"
653
+ end
766
654
  end
655
+
767
656
  expect(fsm.current).to eq(:initial)
768
657
  fsm.bump
769
658
  expect(callbacks).to eq([
@@ -814,24 +703,21 @@ RSpec.describe FiniteMachine, 'callbacks' do
814
703
 
815
704
  it "groups states under event name" do
816
705
  callbacks = []
817
- fsm = FiniteMachine.define do
706
+ fsm = FiniteMachine.new do
818
707
  initial :initial, silent: false
819
708
 
820
- events {
821
- event :bump, :initial => :low,
822
- :low => :medium,
823
- :medium => :high
824
- }
825
-
826
- callbacks {
827
- on_enter do |event|
828
- callbacks << "enter_#{event.name}_#{event.from}_#{event.to}"
829
- end
830
- on_before do |event|
831
- callbacks << "before_#{event.name}_#{event.from}_#{event.to}"
832
- end
833
- }
709
+ event :bump, :initial => :low,
710
+ :low => :medium,
711
+ :medium => :high
712
+
713
+ on_enter do |event|
714
+ callbacks << "enter_#{event.name}_#{event.from}_#{event.to}"
715
+ end
716
+ on_before do |event|
717
+ callbacks << "before_#{event.name}_#{event.from}_#{event.to}"
718
+ end
834
719
  end
720
+
835
721
  expect(fsm.current).to eq(:initial)
836
722
  fsm.bump
837
723
  expect(callbacks).to eq([
@@ -864,18 +750,14 @@ RSpec.describe FiniteMachine, 'callbacks' do
864
750
 
865
751
  it "permits state and event with the same name" do
866
752
  called = []
867
- fsm = FiniteMachine.define do
753
+ fsm = FiniteMachine.new do
868
754
  initial :on_hook, silent: false
869
755
 
870
- events {
871
- event :off_hook, :on_hook => :off_hook
872
- event :on_hook, :off_hook => :on_hook
873
- }
756
+ event :off_hook, :on_hook => :off_hook
757
+ event :on_hook, :off_hook => :on_hook
874
758
 
875
- callbacks {
876
- on_before(:on_hook) { |event| called << "on_before_#{event.name}"}
877
- on_enter(:on_hook) { |event| called << "on_enter_#{event.to}"}
878
- }
759
+ on_before(:on_hook) { |event| called << "on_before_#{event.name}"}
760
+ on_enter(:on_hook) { |event| called << "on_enter_#{event.to}"}
879
761
  end
880
762
  expect(fsm.current).to eq(:on_hook)
881
763
  expect(called).to eq([
@@ -893,18 +775,14 @@ RSpec.describe FiniteMachine, 'callbacks' do
893
775
 
894
776
  it "allows to selectively silence events" do
895
777
  called = []
896
- fsm = FiniteMachine.define do
778
+ fsm = FiniteMachine.new do
897
779
  initial :yellow
898
780
 
899
- events {
900
- event :go, :yellow => :green, silent: true
901
- event :stop, :green => :red
902
- }
781
+ event :go, :yellow => :green, silent: true
782
+ event :stop, :green => :red
903
783
 
904
- callbacks {
905
- on_enter :green do |event| called << 'on_enter_yellow' end
906
- on_enter :red do |event| called << 'on_enter_red' end
907
- }
784
+ on_enter :green do |event| called << 'on_enter_yellow' end
785
+ on_enter :red do |event| called << 'on_enter_red' end
908
786
  end
909
787
  expect(fsm.current).to eq(:yellow)
910
788
  fsm.go
@@ -914,22 +792,18 @@ RSpec.describe FiniteMachine, 'callbacks' do
914
792
 
915
793
  it "executes event-based callbacks even when state does not change" do
916
794
  called = []
917
- fsm = FiniteMachine.define do
795
+ fsm = FiniteMachine.new do
918
796
  initial :active
919
797
 
920
- events {
921
- event :advance, :active => :inactive, if: -> { false }
922
- event :advance, :inactive => :active, if: -> { false }
923
- }
924
-
925
- callbacks {
926
- on_before do |event|
927
- called << "before_#{event.name}_#{event.from}_#{event.to}"
928
- end
929
- on_after do |event|
930
- called << "after_#{event.name}_#{event.from}_#{event.to}"
931
- end
932
- }
798
+ event :advance, :active => :inactive, if: -> { false }
799
+ event :advance, :inactive => :active, if: -> { false }
800
+
801
+ on_before do |event|
802
+ called << "before_#{event.name}_#{event.from}_#{event.to}"
803
+ end
804
+ on_after do |event|
805
+ called << "after_#{event.name}_#{event.from}_#{event.to}"
806
+ end
933
807
  end
934
808
  expect(fsm.current).to eq(:active)
935
809
  fsm.advance
@@ -939,4 +813,39 @@ RSpec.describe FiniteMachine, 'callbacks' do
939
813
  'after_advance_active_inactive'
940
814
  ])
941
815
  end
816
+
817
+ it "doesn't transition if error raised in callback" do
818
+ fsm = FiniteMachine.new do
819
+ initial :green
820
+
821
+ event :slow, :green => :yellow
822
+
823
+ on_enter { raise RuntimeError }
824
+ end
825
+
826
+ expect {
827
+ fsm.slow
828
+ }.to raise_error(RuntimeError)
829
+ expect(fsm.current).to eq(:green)
830
+ end
831
+
832
+ xit "narrows down on_transition callback to state transition" do
833
+ called = []
834
+ fsm = FiniteMachine.new do
835
+ initial :red
836
+
837
+ event :ready, :red => :yellow
838
+ event :go, :yellow => :green
839
+ event :stop, :green => :red
840
+
841
+ on_transition :yellow => :green do
842
+ called << 'on_transition_yellow_green'
843
+ end
844
+ end
845
+
846
+ fsm.ready
847
+ fsm.go
848
+
849
+ expect(called).to eq(['on_transition_yellow_green'])
850
+ end
942
851
  end