finite_machine 0.11.3 → 0.12.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.
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