state_machine 0.4.0 → 0.4.1
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.
- data/CHANGELOG.rdoc +9 -0
- data/LICENSE +1 -1
- data/README.rdoc +4 -4
- data/Rakefile +1 -1
- data/lib/state_machine/event.rb +5 -3
- data/lib/state_machine/extensions.rb +2 -1
- data/lib/state_machine/guard.rb +24 -17
- data/lib/state_machine/integrations/active_record.rb +23 -1
- data/lib/state_machine/machine.rb +68 -27
- data/lib/state_machine.rb +1 -3
- data/test/active_record.log +17542 -0
- data/test/data_mapper.log +4814 -0
- data/test/sequel.log +2697 -0
- data/test/unit/event_test.rb +33 -0
- data/test/unit/guard_test.rb +64 -1
- data/test/unit/integrations/active_record_test.rb +58 -2
- data/test/unit/machine_test.rb +82 -11
- metadata +2 -2
data/test/unit/event_test.rb
CHANGED
@@ -301,6 +301,39 @@ class EventWithTransitionWithoutToStateTest < Test::Unit::TestCase
|
|
301
301
|
end
|
302
302
|
end
|
303
303
|
|
304
|
+
class EventWithTransitionWithNilToStateTest < Test::Unit::TestCase
|
305
|
+
def setup
|
306
|
+
@klass = Class.new
|
307
|
+
@machine = StateMachine::Machine.new(@klass)
|
308
|
+
@event = StateMachine::Event.new(@machine, 'turn_off')
|
309
|
+
@event.transition(:from => 'off', :to => nil)
|
310
|
+
|
311
|
+
@object = @klass.new
|
312
|
+
@object.state = 'off'
|
313
|
+
end
|
314
|
+
|
315
|
+
def test_should_be_able_to_fire
|
316
|
+
assert @event.can_fire?(@object)
|
317
|
+
end
|
318
|
+
|
319
|
+
def test_should_have_a_next_transition
|
320
|
+
transition = @event.next_transition(@object)
|
321
|
+
assert_not_nil transition
|
322
|
+
assert_equal 'off', transition.from
|
323
|
+
assert_equal nil, transition.to
|
324
|
+
assert_equal 'turn_off', transition.event
|
325
|
+
end
|
326
|
+
|
327
|
+
def test_should_fire
|
328
|
+
assert @event.fire(@object)
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_should_not_change_the_current_state
|
332
|
+
@event.fire(@object)
|
333
|
+
assert_equal nil, @object.state
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
304
337
|
class EventWithTransitionWithDynamicToStateTest < Test::Unit::TestCase
|
305
338
|
def setup
|
306
339
|
@klass = Class.new
|
data/test/unit/guard_test.rb
CHANGED
@@ -10,7 +10,7 @@ class GuardTest < Test::Unit::TestCase
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_should_have_requirements
|
13
|
-
expected = {:to =>
|
13
|
+
expected = {:to => %w(on), :from => %w(off)}
|
14
14
|
assert_equal expected, @guard.requirements
|
15
15
|
end
|
16
16
|
end
|
@@ -40,6 +40,10 @@ class GuardWithToRequirementTest < Test::Unit::TestCase
|
|
40
40
|
@guard = StateMachine::Guard.new(:to => 'on')
|
41
41
|
end
|
42
42
|
|
43
|
+
def test_should_match_if_not_specified
|
44
|
+
assert @guard.matches?(@object, :from => 'off')
|
45
|
+
end
|
46
|
+
|
43
47
|
def test_should_match_if_included
|
44
48
|
assert @guard.matches?(@object, :to => 'on')
|
45
49
|
end
|
@@ -48,6 +52,10 @@ class GuardWithToRequirementTest < Test::Unit::TestCase
|
|
48
52
|
assert !@guard.matches?(@object, :to => 'off')
|
49
53
|
end
|
50
54
|
|
55
|
+
def test_should_not_match_if_nil
|
56
|
+
assert !@guard.matches?(@object, :to => nil)
|
57
|
+
end
|
58
|
+
|
51
59
|
def test_should_ignore_from
|
52
60
|
assert @guard.matches?(@object, :to => 'on', :from => 'off')
|
53
61
|
end
|
@@ -86,6 +94,10 @@ class GuardWithFromRequirementTest < Test::Unit::TestCase
|
|
86
94
|
@guard = StateMachine::Guard.new(:from => 'on')
|
87
95
|
end
|
88
96
|
|
97
|
+
def test_should_match_if_not_specified
|
98
|
+
assert @guard.matches?(@object, :to => 'off')
|
99
|
+
end
|
100
|
+
|
89
101
|
def test_should_match_if_included
|
90
102
|
assert @guard.matches?(@object, :from => 'on')
|
91
103
|
end
|
@@ -94,6 +106,10 @@ class GuardWithFromRequirementTest < Test::Unit::TestCase
|
|
94
106
|
assert !@guard.matches?(@object, :from => 'off')
|
95
107
|
end
|
96
108
|
|
109
|
+
def test_should_not_match_if_nil
|
110
|
+
assert !@guard.matches?(@object, :from => nil)
|
111
|
+
end
|
112
|
+
|
97
113
|
def test_should_ignore_to
|
98
114
|
assert @guard.matches?(@object, :from => 'on', :to => 'off')
|
99
115
|
end
|
@@ -132,6 +148,10 @@ class GuardWithOnRequirementTest < Test::Unit::TestCase
|
|
132
148
|
@guard = StateMachine::Guard.new(:on => 'turn_on')
|
133
149
|
end
|
134
150
|
|
151
|
+
def test_should_match_if_not_specified
|
152
|
+
assert @guard.matches?(@object, :from => 'off')
|
153
|
+
end
|
154
|
+
|
135
155
|
def test_should_match_if_included
|
136
156
|
assert @guard.matches?(@object, :on => 'turn_on')
|
137
157
|
end
|
@@ -140,6 +160,10 @@ class GuardWithOnRequirementTest < Test::Unit::TestCase
|
|
140
160
|
assert !@guard.matches?(@object, :on => 'turn_off')
|
141
161
|
end
|
142
162
|
|
163
|
+
def test_should_not_match_if_nil
|
164
|
+
assert !@guard.matches?(@object, :on => nil)
|
165
|
+
end
|
166
|
+
|
143
167
|
def test_should_ignore_to
|
144
168
|
assert @guard.matches?(@object, :on => 'turn_on', :to => 'off')
|
145
169
|
end
|
@@ -182,6 +206,10 @@ class GuardWithExceptToRequirementTest < Test::Unit::TestCase
|
|
182
206
|
assert !@guard.matches?(@object, :to => 'off')
|
183
207
|
end
|
184
208
|
|
209
|
+
def test_should_match_if_nil
|
210
|
+
assert @guard.matches?(@object, :to => nil)
|
211
|
+
end
|
212
|
+
|
185
213
|
def test_should_ignore_from
|
186
214
|
assert @guard.matches?(@object, :except_to => 'off', :from => 'off')
|
187
215
|
end
|
@@ -228,6 +256,10 @@ class GuardWithExceptFromRequirementTest < Test::Unit::TestCase
|
|
228
256
|
assert !@guard.matches?(@object, :from => 'off')
|
229
257
|
end
|
230
258
|
|
259
|
+
def test_should_match_if_nil
|
260
|
+
assert @guard.matches?(@object, :from => nil)
|
261
|
+
end
|
262
|
+
|
231
263
|
def test_should_ignore_to
|
232
264
|
assert @guard.matches?(@object, :from => 'on', :to => 'off')
|
233
265
|
end
|
@@ -274,6 +306,10 @@ class GuardWithExceptOnRequirementTest < Test::Unit::TestCase
|
|
274
306
|
assert !@guard.matches?(@object, :on => 'turn_off')
|
275
307
|
end
|
276
308
|
|
309
|
+
def test_should_match_if_nil
|
310
|
+
assert @guard.matches?(@object, :on => nil)
|
311
|
+
end
|
312
|
+
|
277
313
|
def test_should_ignore_to
|
278
314
|
assert @guard.matches?(@object, :on => 'turn_on', :to => 'off')
|
279
315
|
end
|
@@ -371,6 +407,33 @@ class GuardWithDifferentRequirementsTest < Test::Unit::TestCase
|
|
371
407
|
end
|
372
408
|
end
|
373
409
|
|
410
|
+
class GuardWithNilRequirementsTest < Test::Unit::TestCase
|
411
|
+
def setup
|
412
|
+
@object = Object.new
|
413
|
+
@guard = StateMachine::Guard.new(:from => nil, :to => nil)
|
414
|
+
end
|
415
|
+
|
416
|
+
def test_should_match_empty_query
|
417
|
+
assert @guard.matches?(@object)
|
418
|
+
end
|
419
|
+
|
420
|
+
def test_should_match_if_all_requirements_match
|
421
|
+
assert @guard.matches?(@object, :from => nil, :to => nil)
|
422
|
+
end
|
423
|
+
|
424
|
+
def test_should_not_match_if_from_not_included
|
425
|
+
assert !@guard.matches?(@object, :from => 'off')
|
426
|
+
end
|
427
|
+
|
428
|
+
def test_should_not_match_if_to_not_included
|
429
|
+
assert !@guard.matches?(@object, :to => 'on')
|
430
|
+
end
|
431
|
+
|
432
|
+
def test_should_include_all_known_states
|
433
|
+
assert_equal [nil], @guard.known_states
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
374
437
|
class GuardWithIfConditionalTest < Test::Unit::TestCase
|
375
438
|
def setup
|
376
439
|
@object = Object.new
|
@@ -190,10 +190,43 @@ begin
|
|
190
190
|
end
|
191
191
|
end
|
192
192
|
|
193
|
+
class MachineWithColumnStateAttributeTest < ActiveRecord::TestCase
|
194
|
+
def setup
|
195
|
+
@model = new_model
|
196
|
+
@machine = StateMachine::Machine.new(@model, :initial => 'off')
|
197
|
+
@machine.other_states('on')
|
198
|
+
@record = @model.new
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_should_have_an_attribute_predicate
|
202
|
+
assert @record.respond_to?(:state?)
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_should_test_for_existence_on_predicate_without_parameters
|
206
|
+
assert @record.state?
|
207
|
+
|
208
|
+
@record.state = nil
|
209
|
+
assert !@record.state?
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_should_return_false_for_predicate_if_does_not_match_current_value
|
213
|
+
assert !@record.state?('on')
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_should_return_true_for_predicate_if_matches_current_value
|
217
|
+
assert @record.state?('off')
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_should_raise_exception_for_predicate_if_invalid_state_specified
|
221
|
+
assert_raise(ArgumentError) { @record.state?('invalid') }
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
193
225
|
class MachineWithNonColumnStateAttributeTest < ActiveRecord::TestCase
|
194
226
|
def setup
|
195
227
|
@model = new_model
|
196
228
|
@machine = StateMachine::Machine.new(@model, :status, :initial => 'off')
|
229
|
+
@machine.other_states('on')
|
197
230
|
@record = @model.new
|
198
231
|
end
|
199
232
|
|
@@ -205,6 +238,29 @@ begin
|
|
205
238
|
assert @record.respond_to?(:status=)
|
206
239
|
end
|
207
240
|
|
241
|
+
def test_should_define_an_attribute_predicate
|
242
|
+
assert @record.respond_to?(:status?)
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_should_raise_exception_on_predicate_without_parameters
|
246
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
247
|
+
assert_raise(ArgumentError) { @record.status? }
|
248
|
+
ensure
|
249
|
+
$VERBOSE = old_verbose
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_should_return_false_for_predicate_if_does_not_match_current_value
|
253
|
+
assert !@record.status?('on')
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_should_return_true_for_predicate_if_matches_current_value
|
257
|
+
assert @record.status?('off')
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_should_raise_exception_for_predicate_if_invalid_state_specified
|
261
|
+
assert_raise(ArgumentError) { @record.status?('invalid') }
|
262
|
+
end
|
263
|
+
|
208
264
|
def test_should_set_initial_state_on_created_object
|
209
265
|
assert_equal 'off', @record.status
|
210
266
|
end
|
@@ -213,7 +269,7 @@ begin
|
|
213
269
|
class MachineWithCallbacksTest < ActiveRecord::TestCase
|
214
270
|
def setup
|
215
271
|
@model = new_model
|
216
|
-
@machine = StateMachine::Machine.new(@model)
|
272
|
+
@machine = StateMachine::Machine.new(@model, :initial => 'off')
|
217
273
|
@record = @model.new(:state => 'off')
|
218
274
|
@transition = StateMachine::Transition.new(@record, @machine, 'turn_on', 'off', 'on')
|
219
275
|
end
|
@@ -285,7 +341,7 @@ begin
|
|
285
341
|
def test_should_include_transition_states_in_known_states
|
286
342
|
@machine.before_transition :to => 'error', :do => lambda {}
|
287
343
|
|
288
|
-
assert_equal %w(error), @machine.states.sort
|
344
|
+
assert_equal %w(error off), @machine.states.sort
|
289
345
|
end
|
290
346
|
end
|
291
347
|
|
data/test/unit/machine_test.rb
CHANGED
@@ -35,8 +35,8 @@ class MachineByDefaultTest < Test::Unit::TestCase
|
|
35
35
|
assert_nil @machine.action
|
36
36
|
end
|
37
37
|
|
38
|
-
def
|
39
|
-
|
38
|
+
def test_should_have_a_nil_state
|
39
|
+
assert_equal [nil], @machine.states
|
40
40
|
end
|
41
41
|
|
42
42
|
def test_should_not_be_extended_by_the_active_record_integration
|
@@ -158,7 +158,8 @@ class MachineWithDynamicInitialStateTest < Test::Unit::TestCase
|
|
158
158
|
@klass = Class.new do
|
159
159
|
attr_accessor :initial_state
|
160
160
|
end
|
161
|
-
@
|
161
|
+
@initial_state = lambda {|object| object.initial_state || 'default'}
|
162
|
+
@machine = StateMachine::Machine.new(@klass, :initial => @initial_state)
|
162
163
|
@object = @klass.new
|
163
164
|
end
|
164
165
|
|
@@ -174,8 +175,8 @@ class MachineWithDynamicInitialStateTest < Test::Unit::TestCase
|
|
174
175
|
assert_equal 'default', @object.state
|
175
176
|
end
|
176
177
|
|
177
|
-
def
|
178
|
-
assert_equal [], @machine.states
|
178
|
+
def test_should_be_included_in_known_states
|
179
|
+
assert_equal [@initial_state], @machine.states
|
179
180
|
end
|
180
181
|
end
|
181
182
|
|
@@ -228,6 +229,15 @@ class MachineTest < Test::Unit::TestCase
|
|
228
229
|
def test_should_raise_exception_if_invalid_option_specified
|
229
230
|
assert_raise(ArgumentError) {StateMachine::Machine.new(Class.new, :invalid => true)}
|
230
231
|
end
|
232
|
+
|
233
|
+
def test_should_evaluate_a_block_during_initialization
|
234
|
+
called = true
|
235
|
+
StateMachine::Machine.new(Class.new) do
|
236
|
+
called = respond_to?(:event)
|
237
|
+
end
|
238
|
+
|
239
|
+
assert called
|
240
|
+
end
|
231
241
|
end
|
232
242
|
|
233
243
|
class MachineWithoutIntegrationTest < Test::Unit::TestCase
|
@@ -822,7 +832,7 @@ end
|
|
822
832
|
class MachineWithEventsWithTransitionsTest < Test::Unit::TestCase
|
823
833
|
def setup
|
824
834
|
@klass = Class.new
|
825
|
-
@machine = StateMachine::Machine.new(@klass)
|
835
|
+
@machine = StateMachine::Machine.new(@klass, :initial => 'off')
|
826
836
|
@machine.event(:turn_on) do
|
827
837
|
transition :to => 'on', :from => 'off'
|
828
838
|
transition :to => 'error', :from => 'unknown'
|
@@ -893,19 +903,34 @@ class MachineWithNumericStatesTest < Test::Unit::TestCase
|
|
893
903
|
end
|
894
904
|
end
|
895
905
|
|
906
|
+
class MachineWithNilStatesTest < Test::Unit::TestCase
|
907
|
+
def setup
|
908
|
+
@klass = Class.new
|
909
|
+
@machine = StateMachine::Machine.new(@klass)
|
910
|
+
@machine.event(:turn_on) do
|
911
|
+
transition :to => 'on', :from => nil
|
912
|
+
end
|
913
|
+
end
|
914
|
+
|
915
|
+
def test_should_not_redefine_nil_predicate
|
916
|
+
object = @klass.new
|
917
|
+
assert !object.nil?
|
918
|
+
assert !object.respond_to?('?')
|
919
|
+
end
|
920
|
+
end
|
921
|
+
|
896
922
|
class MachineWithTransitionCallbacksTest < Test::Unit::TestCase
|
897
923
|
def setup
|
898
924
|
@klass = Class.new do
|
899
925
|
attr_accessor :callbacks
|
900
926
|
end
|
901
927
|
|
902
|
-
@machine = StateMachine::Machine.new(@klass)
|
928
|
+
@machine = StateMachine::Machine.new(@klass, :initial => 'off')
|
903
929
|
@event = @machine.event :turn_on do
|
904
930
|
transition :to => 'on', :from => 'off'
|
905
931
|
end
|
906
932
|
|
907
933
|
@object = @klass.new
|
908
|
-
@object.state = 'off'
|
909
934
|
@object.callbacks = []
|
910
935
|
end
|
911
936
|
|
@@ -1052,6 +1077,15 @@ class MachineFinderWithoutExistingMachineTest < Test::Unit::TestCase
|
|
1052
1077
|
@machine = StateMachine::Machine.find_or_create(@klass)
|
1053
1078
|
end
|
1054
1079
|
|
1080
|
+
def test_should_accept_a_block
|
1081
|
+
called = false
|
1082
|
+
StateMachine::Machine.find_or_create(Class.new) do
|
1083
|
+
called = respond_to?(:event)
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
assert called
|
1087
|
+
end
|
1088
|
+
|
1055
1089
|
def test_should_create_a_new_machine
|
1056
1090
|
assert_not_nil @machine
|
1057
1091
|
end
|
@@ -1068,6 +1102,15 @@ class MachineFinderWithExistingOnSameClassTest < Test::Unit::TestCase
|
|
1068
1102
|
@machine = StateMachine::Machine.find_or_create(@klass)
|
1069
1103
|
end
|
1070
1104
|
|
1105
|
+
def test_should_accept_a_block
|
1106
|
+
called = false
|
1107
|
+
StateMachine::Machine.find_or_create(@klass) do
|
1108
|
+
called = respond_to?(:event)
|
1109
|
+
end
|
1110
|
+
|
1111
|
+
assert called
|
1112
|
+
end
|
1113
|
+
|
1071
1114
|
def test_should_not_create_a_new_machine
|
1072
1115
|
assert_same @machine, @existing_machine
|
1073
1116
|
end
|
@@ -1092,6 +1135,15 @@ class MachineFinderWithExistingMachineOnSuperclassTest < Test::Unit::TestCase
|
|
1092
1135
|
@machine = StateMachine::Machine.find_or_create(@klass, 'status')
|
1093
1136
|
end
|
1094
1137
|
|
1138
|
+
def test_should_accept_a_block
|
1139
|
+
called = false
|
1140
|
+
StateMachine::Machine.find_or_create(Class.new(@base_class)) do
|
1141
|
+
called = respond_to?(:event)
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
assert called
|
1145
|
+
end
|
1146
|
+
|
1095
1147
|
def test_should_create_a_new_machine
|
1096
1148
|
assert_not_nil @machine
|
1097
1149
|
assert_not_same @machine, @base_machine
|
@@ -1211,14 +1263,33 @@ begin
|
|
1211
1263
|
end
|
1212
1264
|
end
|
1213
1265
|
|
1214
|
-
class
|
1266
|
+
class MachineDrawingWithNilStatesTest < Test::Unit::TestCase
|
1267
|
+
def setup
|
1268
|
+
@klass = Class.new do
|
1269
|
+
def self.name; 'Vehicle'; end
|
1270
|
+
end
|
1271
|
+
@machine = StateMachine::Machine.new(@klass, :activated_at, :initial => 'inactive')
|
1272
|
+
@machine.event :activate do
|
1273
|
+
transition :from => nil, :to => 'active'
|
1274
|
+
end
|
1275
|
+
@machine.draw
|
1276
|
+
end
|
1277
|
+
|
1278
|
+
def test_should_draw_machine
|
1279
|
+
assert File.exist?('./Vehicle_activated_at.png')
|
1280
|
+
ensure
|
1281
|
+
FileUtils.rm('./Vehicle_activated_at.png')
|
1282
|
+
end
|
1283
|
+
end
|
1284
|
+
|
1285
|
+
class MachineDrawingWithDynamicStatesTest < Test::Unit::TestCase
|
1215
1286
|
def setup
|
1216
1287
|
@klass = Class.new do
|
1217
1288
|
def self.name; 'Vehicle'; end
|
1218
1289
|
end
|
1219
|
-
@machine = StateMachine::Machine.new(@klass, :activated_at)
|
1290
|
+
@machine = StateMachine::Machine.new(@klass, :activated_at, :initial => 'inactive')
|
1220
1291
|
@machine.event :activate do
|
1221
|
-
transition :from =>
|
1292
|
+
transition :from => 'inactive', :to => lambda {Time.now}
|
1222
1293
|
end
|
1223
1294
|
@machine.draw
|
1224
1295
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: state_machine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Pfeifer
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-12-
|
12
|
+
date: 2008-12-16 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|