finite_machine 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/Gemfile +1 -1
  4. data/README.md +150 -35
  5. data/lib/finite_machine.rb +1 -0
  6. data/lib/finite_machine/catchable.rb +1 -1
  7. data/lib/finite_machine/definition.rb +61 -0
  8. data/lib/finite_machine/dsl.rb +45 -10
  9. data/lib/finite_machine/event.rb +17 -1
  10. data/lib/finite_machine/hook_event.rb +66 -7
  11. data/lib/finite_machine/observer.rb +3 -3
  12. data/lib/finite_machine/state_machine.rb +36 -28
  13. data/lib/finite_machine/version.rb +1 -1
  14. data/spec/spec_helper.rb +2 -2
  15. data/spec/unit/async_events_spec.rb +1 -1
  16. data/spec/unit/callbacks_spec.rb +23 -23
  17. data/spec/unit/can_spec.rb +22 -22
  18. data/spec/unit/event/eql_spec.rb +37 -0
  19. data/spec/unit/event/initialize_spec.rb +38 -0
  20. data/spec/unit/event/inspect_spec.rb +1 -1
  21. data/spec/unit/event_queue_spec.rb +2 -2
  22. data/spec/unit/events_chain/check_choice_conditions_spec.rb +2 -2
  23. data/spec/unit/events_chain/clear_spec.rb +1 -1
  24. data/spec/unit/events_chain/insert_spec.rb +1 -1
  25. data/spec/unit/events_spec.rb +17 -20
  26. data/spec/unit/hook_event/eql_spec.rb +37 -0
  27. data/spec/unit/hook_event/initialize_spec.rb +22 -0
  28. data/spec/unit/if_unless_spec.rb +6 -6
  29. data/spec/unit/initialize_spec.rb +6 -6
  30. data/spec/unit/is_spec.rb +12 -12
  31. data/spec/unit/logger_spec.rb +1 -1
  32. data/spec/unit/respond_to_spec.rb +2 -2
  33. data/spec/unit/standalone_spec.rb +72 -0
  34. data/spec/unit/subscribers_spec.rb +2 -2
  35. data/spec/unit/target_spec.rb +59 -10
  36. data/spec/unit/{finished_spec.rb → terminated_spec.rb} +38 -8
  37. metadata +15 -4
data/spec/unit/is_spec.rb CHANGED
@@ -18,17 +18,17 @@ describe FiniteMachine, 'is?' do
18
18
 
19
19
  expect(fsm.current).to eql(:green)
20
20
 
21
- expect(fsm.is?(:green)).to be_true
22
- expect(fsm.is?(:yellow)).to be_false
23
- expect(fsm.is?([:green, :red])).to be_true
24
- expect(fsm.is?([:yellow, :red])).to be_false
21
+ expect(fsm.is?(:green)).to be true
22
+ expect(fsm.is?(:yellow)).to be false
23
+ expect(fsm.is?([:green, :red])).to be true
24
+ expect(fsm.is?([:yellow, :red])).to be false
25
25
 
26
26
  fsm.slow
27
27
 
28
- expect(fsm.is?(:green)).to be_false
29
- expect(fsm.is?(:yellow)).to be_true
30
- expect(fsm.is?([:green, :red])).to be_false
31
- expect(fsm.is?([:yellow, :red])).to be_true
28
+ expect(fsm.is?(:green)).to be false
29
+ expect(fsm.is?(:yellow)).to be true
30
+ expect(fsm.is?([:green, :red])).to be false
31
+ expect(fsm.is?([:yellow, :red])).to be true
32
32
  end
33
33
 
34
34
  it "defines helper methods to check current state" do
@@ -44,12 +44,12 @@ describe FiniteMachine, 'is?' do
44
44
  end
45
45
  expect(fsm.current).to eql(:green)
46
46
 
47
- expect(fsm.green?).to be_true
48
- expect(fsm.yellow?).to be_false
47
+ expect(fsm.green?).to be true
48
+ expect(fsm.yellow?).to be false
49
49
 
50
50
  fsm.slow
51
51
 
52
- expect(fsm.green?).to be_false
53
- expect(fsm.yellow?).to be_true
52
+ expect(fsm.green?).to be false
53
+ expect(fsm.yellow?).to be true
54
54
  end
55
55
  end
@@ -9,7 +9,7 @@ describe FiniteMachine::Logger do
9
9
 
10
10
  subject(:logger) { described_class }
11
11
 
12
- before { FiniteMachine.stub(:logger) { log } }
12
+ before { allow(FiniteMachine).to receive(:logger) { log } }
13
13
 
14
14
  it "debugs message call" do
15
15
  expect(log).to receive(:debug).with(message)
@@ -31,7 +31,7 @@ describe FiniteMachine, '#respond_to' do
31
31
  expect(fsm).to respond_to(:on_enter_slow)
32
32
  end
33
33
 
34
- it "knows about target class methods" do
35
- expect(fsm).to respond_to(:engine_on?)
34
+ it "doesn't know about target class methods" do
35
+ expect(fsm).not_to respond_to(:engine_on?)
36
36
  end
37
37
  end
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe FiniteMachine::Definition, 'definition' do
6
+
7
+ before do
8
+ class Engine < FiniteMachine::Definition
9
+ initial :neutral
10
+
11
+ events {
12
+ event :forward, [:reverse, :neutral] => :one
13
+ event :shift, :one => :two
14
+ event :shift, :two => :one
15
+ event :back, [:neutral, :one] => :reverse
16
+ }
17
+
18
+ callbacks {
19
+ on_enter :reverse do |event|
20
+ target.turn_reverse_lights_on
21
+ end
22
+
23
+ on_exit :reverse do |event|
24
+ target.turn_reverse_lights_off
25
+ end
26
+ }
27
+
28
+ handlers {
29
+ handle FiniteMachine::InvalidStateError do |exception| end
30
+ }
31
+ end
32
+ end
33
+
34
+ it "creates unique instances" do
35
+ engine_a = Engine.new
36
+ engine_b = Engine.new
37
+ expect(engine_a).not_to be(engine_b)
38
+
39
+ engine_a.forward
40
+ expect(engine_a.current).to eq(:one)
41
+ expect(engine_b.current).to eq(:neutral)
42
+ end
43
+
44
+ it "allows to create standalone machine" do
45
+ Car = Class.new do
46
+ def turn_reverse_lights_off
47
+ @reverse_lights = false
48
+ end
49
+
50
+ def turn_reverse_lights_on
51
+ @reverse_lights = true
52
+ end
53
+
54
+ def reverse_lights?
55
+ @reverse_lights ||= false
56
+ end
57
+ end
58
+
59
+ car = Car.new
60
+ engine = Engine.new
61
+ engine.target car
62
+ expect(engine.current).to eq(:neutral)
63
+
64
+ engine.forward
65
+ expect(engine.current).to eq(:one)
66
+ expect(car.reverse_lights?).to be false
67
+
68
+ engine.back
69
+ expect(engine.current).to eq(:reverse)
70
+ expect(car.reverse_lights?).to be true
71
+ end
72
+ end
@@ -12,7 +12,7 @@ describe FiniteMachine::Subscribers do
12
12
  before { subscribers.subscribe(listener) }
13
13
 
14
14
  it "checks if any subscribers exist" do
15
- expect(subscribers.empty?).to be_false
15
+ expect(subscribers.empty?).to be(false)
16
16
  end
17
17
 
18
18
  it "returns index for the subscriber" do
@@ -26,6 +26,6 @@ describe FiniteMachine::Subscribers do
26
26
 
27
27
  it "resets the subscribers" do
28
28
  subscribers.reset
29
- expect(subscribers.empty?).to be_true
29
+ expect(subscribers.empty?).to be(true)
30
30
  end
31
31
  end
@@ -16,6 +16,10 @@ describe FiniteMachine, '#target' do
16
16
  @reverse_lights = true
17
17
  end
18
18
 
19
+ def reverse_lights?
20
+ @reverse_lights ||= false
21
+ end
22
+
19
23
  def engine
20
24
  context = self
21
25
  @engine ||= FiniteMachine.define do
@@ -32,25 +36,25 @@ describe FiniteMachine, '#target' do
32
36
 
33
37
  callbacks {
34
38
  on_enter :reverse do |event|
35
- turn_reverse_lights_on
39
+ target.turn_reverse_lights_on
36
40
  end
37
41
 
38
42
  on_exit :reverse do |event|
39
- turn_reverse_lights_off
43
+ target.turn_reverse_lights_off
40
44
  end
41
45
  }
42
46
  end
43
47
  end
44
48
  end
45
49
  car = Car.new
46
- expect(car.reverse_lights).to be_false
50
+ expect(car.reverse_lights?).to be(false)
47
51
  expect(car.engine.current).to eql(:neutral)
48
52
  car.engine.back
49
53
  expect(car.engine.current).to eql(:reverse)
50
- expect(car.reverse_lights).to be_true
54
+ expect(car.reverse_lights?).to be(true)
51
55
  car.engine.forward
52
56
  expect(car.engine.current).to eql(:one)
53
- expect(car.reverse_lights).to be_false
57
+ expect(car.reverse_lights?).to be(false)
54
58
  end
55
59
 
56
60
  it "propagates method call" do
@@ -112,6 +116,10 @@ describe FiniteMachine, '#target' do
112
116
  @reverse_lights = true
113
117
  end
114
118
 
119
+ def reverse_lights?
120
+ @reverse_lights ||= false
121
+ end
122
+
115
123
  def engine
116
124
  self.called ||= []
117
125
  context ||= self
@@ -129,12 +137,12 @@ describe FiniteMachine, '#target' do
129
137
 
130
138
  callbacks {
131
139
  on_enter :reverse do |event|
132
- called << 'on_enter_reverse'
133
- turn_reverse_lights_on
140
+ target.called << 'on_enter_reverse'
141
+ target.turn_reverse_lights_on
134
142
  forward('Piotr!')
135
143
  end
136
144
  on_before :forward do |event, name|
137
- called << "on_enter_forward with #{name}"
145
+ target.called << "on_enter_forward with #{name}"
138
146
  end
139
147
  }
140
148
  end
@@ -142,7 +150,7 @@ describe FiniteMachine, '#target' do
142
150
  end
143
151
 
144
152
  car = Car.new
145
- expect(car.reverse_lights).to be_false
153
+ expect(car.reverse_lights?).to be(false)
146
154
  expect(car.engine.current).to eql(:neutral)
147
155
  car.engine.back
148
156
  expect(car.engine.current).to eql(:one)
@@ -158,7 +166,7 @@ describe FiniteMachine, '#target' do
158
166
  fsm = FiniteMachine.define do
159
167
  initial :green
160
168
 
161
- target context
169
+ target context
162
170
 
163
171
  events {
164
172
  event :slow, :green => :yellow
@@ -174,4 +182,45 @@ describe FiniteMachine, '#target' do
174
182
  fsm.slow
175
183
  expect(called).to eq(context)
176
184
  end
185
+
186
+ it "allows to differentiate between same named methods" do
187
+ called = []
188
+ Car = Class.new do
189
+ def initialize(called)
190
+ @called = called
191
+ end
192
+ def save
193
+ @called << 'car save called'
194
+ end
195
+ end
196
+
197
+ car = Car.new(called)
198
+ fsm = FiniteMachine.define do
199
+ initial :unsaved
200
+
201
+ target car
202
+
203
+ events {
204
+ event :validate, :unsaved => :valid
205
+ event :save, :valid => :saved
206
+ }
207
+
208
+ callbacks {
209
+ on_enter :valid do |event|
210
+ target.save
211
+ save
212
+ end
213
+ on_after :save do |event|
214
+ called << 'event save called'
215
+ end
216
+ }
217
+ end
218
+ expect(fsm.current).to eql(:unsaved)
219
+ fsm.validate
220
+ expect(fsm.current).to eql(:saved)
221
+ expect(called).to eq([
222
+ 'car save called',
223
+ 'event save called'
224
+ ])
225
+ end
177
226
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe FiniteMachine, 'finished?' do
5
+ describe FiniteMachine, 'terminated?' do
6
6
 
7
7
  it "allows to specify terminal state" do
8
8
  fsm = FiniteMachine.define do
@@ -16,15 +16,15 @@ describe FiniteMachine, 'finished?' do
16
16
  end
17
17
 
18
18
  expect(fsm.current).to eql(:green)
19
- expect(fsm.finished?).to be_false
19
+ expect(fsm.terminated?).to be(false)
20
20
 
21
21
  fsm.slow
22
22
  expect(fsm.current).to eql(:yellow)
23
- expect(fsm.finished?).to be_false
23
+ expect(fsm.terminated?).to be(false)
24
24
 
25
25
  fsm.stop
26
26
  expect(fsm.current).to eql(:red)
27
- expect(fsm.finished?).to be_true
27
+ expect(fsm.terminated?).to be(true)
28
28
  end
29
29
 
30
30
  it "allows to specify terminal state as parameter" do
@@ -38,7 +38,7 @@ describe FiniteMachine, 'finished?' do
38
38
  end
39
39
  fsm.slow
40
40
  fsm.stop
41
- expect(fsm.finished?).to be_true
41
+ expect(fsm.terminated?).to be(true)
42
42
  end
43
43
 
44
44
  it "checks without terminal state" do
@@ -52,14 +52,44 @@ describe FiniteMachine, 'finished?' do
52
52
  end
53
53
 
54
54
  expect(fsm.current).to eql(:green)
55
- expect(fsm.finished?).to be_false
55
+ expect(fsm.terminated?).to be(false)
56
56
 
57
57
  fsm.slow
58
58
  expect(fsm.current).to eql(:yellow)
59
- expect(fsm.finished?).to be_false
59
+ expect(fsm.terminated?).to be(false)
60
60
 
61
61
  fsm.stop
62
62
  expect(fsm.current).to eql(:red)
63
- expect(fsm.finished?).to be_false
63
+ expect(fsm.terminated?).to be(false)
64
+ end
65
+
66
+ it "allows for multiple terminal states" do
67
+ fsm = FiniteMachine.define do
68
+ initial :open
69
+
70
+ terminal :close, :canceled, :faulty
71
+
72
+ events {
73
+ event :resolve, :open => :close
74
+ event :decline, :open => :canceled
75
+ event :error, :open => :faulty
76
+ }
77
+ end
78
+ expect(fsm.current).to eql(:open)
79
+ expect(fsm.terminated?).to be(false)
80
+
81
+ fsm.resolve
82
+ expect(fsm.current).to eql(:close)
83
+ expect(fsm.terminated?).to be(true)
84
+
85
+ fsm.restore!(:open)
86
+ fsm.decline
87
+ expect(fsm.current).to eql(:canceled)
88
+ expect(fsm.terminated?).to be(true)
89
+
90
+ fsm.restore!(:open)
91
+ fsm.error
92
+ expect(fsm.current).to eql(:faulty)
93
+ expect(fsm.terminated?).to be(true)
64
94
  end
65
95
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finite_machine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Murach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-05 00:00:00.000000000 Z
11
+ date: 2014-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,7 @@ files:
52
52
  - lib/finite_machine/callable.rb
53
53
  - lib/finite_machine/catchable.rb
54
54
  - lib/finite_machine/choice_merger.rb
55
+ - lib/finite_machine/definition.rb
55
56
  - lib/finite_machine/dsl.rb
56
57
  - lib/finite_machine/event.rb
57
58
  - lib/finite_machine/event_builder.rb
@@ -79,6 +80,8 @@ files:
79
80
  - spec/unit/choice_spec.rb
80
81
  - spec/unit/define_spec.rb
81
82
  - spec/unit/event/add_spec.rb
83
+ - spec/unit/event/eql_spec.rb
84
+ - spec/unit/event/initialize_spec.rb
82
85
  - spec/unit/event/inspect_spec.rb
83
86
  - spec/unit/event/next_transition_spec.rb
84
87
  - spec/unit/event_queue_spec.rb
@@ -88,8 +91,9 @@ files:
88
91
  - spec/unit/events_chain/inspect_spec.rb
89
92
  - spec/unit/events_chain/select_transition_spec.rb
90
93
  - spec/unit/events_spec.rb
91
- - spec/unit/finished_spec.rb
92
94
  - spec/unit/handlers_spec.rb
95
+ - spec/unit/hook_event/eql_spec.rb
96
+ - spec/unit/hook_event/initialize_spec.rb
93
97
  - spec/unit/hooks/call_spec.rb
94
98
  - spec/unit/hooks/inspect_spec.rb
95
99
  - spec/unit/hooks/register_spec.rb
@@ -99,11 +103,13 @@ files:
99
103
  - spec/unit/is_spec.rb
100
104
  - spec/unit/logger_spec.rb
101
105
  - spec/unit/respond_to_spec.rb
106
+ - spec/unit/standalone_spec.rb
102
107
  - spec/unit/state_parser/inspect_spec.rb
103
108
  - spec/unit/state_parser/parse_states_spec.rb
104
109
  - spec/unit/states_spec.rb
105
110
  - spec/unit/subscribers_spec.rb
106
111
  - spec/unit/target_spec.rb
112
+ - spec/unit/terminated_spec.rb
107
113
  - spec/unit/transition/inspect_spec.rb
108
114
  - spec/unit/transition/parse_states_spec.rb
109
115
  - tasks/console.rake
@@ -142,6 +148,8 @@ test_files:
142
148
  - spec/unit/choice_spec.rb
143
149
  - spec/unit/define_spec.rb
144
150
  - spec/unit/event/add_spec.rb
151
+ - spec/unit/event/eql_spec.rb
152
+ - spec/unit/event/initialize_spec.rb
145
153
  - spec/unit/event/inspect_spec.rb
146
154
  - spec/unit/event/next_transition_spec.rb
147
155
  - spec/unit/event_queue_spec.rb
@@ -151,8 +159,9 @@ test_files:
151
159
  - spec/unit/events_chain/inspect_spec.rb
152
160
  - spec/unit/events_chain/select_transition_spec.rb
153
161
  - spec/unit/events_spec.rb
154
- - spec/unit/finished_spec.rb
155
162
  - spec/unit/handlers_spec.rb
163
+ - spec/unit/hook_event/eql_spec.rb
164
+ - spec/unit/hook_event/initialize_spec.rb
156
165
  - spec/unit/hooks/call_spec.rb
157
166
  - spec/unit/hooks/inspect_spec.rb
158
167
  - spec/unit/hooks/register_spec.rb
@@ -162,11 +171,13 @@ test_files:
162
171
  - spec/unit/is_spec.rb
163
172
  - spec/unit/logger_spec.rb
164
173
  - spec/unit/respond_to_spec.rb
174
+ - spec/unit/standalone_spec.rb
165
175
  - spec/unit/state_parser/inspect_spec.rb
166
176
  - spec/unit/state_parser/parse_states_spec.rb
167
177
  - spec/unit/states_spec.rb
168
178
  - spec/unit/subscribers_spec.rb
169
179
  - spec/unit/target_spec.rb
180
+ - spec/unit/terminated_spec.rb
170
181
  - spec/unit/transition/inspect_spec.rb
171
182
  - spec/unit/transition/parse_states_spec.rb
172
183
  has_rdoc: