state_machine 0.8.1 → 0.9.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.
- data/CHANGELOG.rdoc +17 -0
- data/LICENSE +1 -1
- data/README.rdoc +162 -23
- data/Rakefile +3 -18
- data/lib/state_machine.rb +3 -4
- data/lib/state_machine/callback.rb +65 -13
- data/lib/state_machine/eval_helpers.rb +20 -4
- data/lib/state_machine/initializers.rb +4 -0
- data/lib/state_machine/initializers/merb.rb +1 -0
- data/lib/state_machine/initializers/rails.rb +7 -0
- data/lib/state_machine/integrations.rb +21 -6
- data/lib/state_machine/integrations/active_model.rb +414 -0
- data/lib/state_machine/integrations/active_model/locale.rb +11 -0
- data/lib/state_machine/integrations/{active_record → active_model}/observer.rb +7 -7
- data/lib/state_machine/integrations/active_record.rb +65 -129
- data/lib/state_machine/integrations/active_record/locale.rb +4 -11
- data/lib/state_machine/integrations/data_mapper.rb +24 -6
- data/lib/state_machine/integrations/data_mapper/observer.rb +36 -0
- data/lib/state_machine/integrations/mongo_mapper.rb +295 -0
- data/lib/state_machine/integrations/sequel.rb +33 -7
- data/lib/state_machine/machine.rb +121 -23
- data/lib/state_machine/machine_collection.rb +12 -103
- data/lib/state_machine/transition.rb +125 -164
- data/lib/state_machine/transition_collection.rb +244 -0
- data/lib/tasks/state_machine.rb +12 -15
- data/test/functional/state_machine_test.rb +11 -1
- data/test/unit/callback_test.rb +305 -32
- data/test/unit/eval_helpers_test.rb +103 -1
- data/test/unit/event_test.rb +2 -1
- data/test/unit/guard_test.rb +2 -1
- data/test/unit/integrations/active_model_test.rb +909 -0
- data/test/unit/integrations/active_record_test.rb +1542 -1292
- data/test/unit/integrations/data_mapper_test.rb +1369 -1041
- data/test/unit/integrations/mongo_mapper_test.rb +1349 -0
- data/test/unit/integrations/sequel_test.rb +1214 -985
- data/test/unit/integrations_test.rb +8 -0
- data/test/unit/machine_collection_test.rb +140 -513
- data/test/unit/machine_test.rb +212 -10
- data/test/unit/state_test.rb +2 -1
- data/test/unit/transition_collection_test.rb +2098 -0
- data/test/unit/transition_test.rb +704 -552
- metadata +16 -3
data/lib/tasks/state_machine.rb
CHANGED
@@ -1,9 +1,18 @@
|
|
1
1
|
namespace :state_machine do
|
2
2
|
desc 'Draws a set of state machines using GraphViz. Target files to load with FILE=x,y,z; Machine class with CLASS=x,y,z; Font name with FONT=x; Image format with FORMAT=x; Orientation with ORIENTATION=x'
|
3
3
|
task :draw do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
if defined?(Rails)
|
5
|
+
Rake::Task['environment'].invoke
|
6
|
+
elsif defined?(Merb)
|
7
|
+
Rake::Task['merb_env'].invoke
|
8
|
+
|
9
|
+
# Fix ruby-graphviz being incompatible with Merb's process title
|
10
|
+
$0 = 'rake'
|
11
|
+
else
|
12
|
+
# Load the library
|
13
|
+
$:.unshift(File.dirname(__FILE__) + '/..')
|
14
|
+
require 'state_machine'
|
15
|
+
end
|
7
16
|
|
8
17
|
# Build drawing options
|
9
18
|
options = {}
|
@@ -15,16 +24,4 @@ namespace :state_machine do
|
|
15
24
|
|
16
25
|
StateMachine::Machine.draw(ENV['CLASS'], options)
|
17
26
|
end
|
18
|
-
|
19
|
-
namespace :draw do
|
20
|
-
desc 'Draws a set of state machines using GraphViz for a Ruby on Rails application. Target class with CLASS=x,y,z; Font name with FONT=x; Image format with FORMAT=x; Orientation with ORIENTATION=x'
|
21
|
-
task :rails => [:environment, 'state_machine:draw']
|
22
|
-
|
23
|
-
desc 'Draws a set of state machines using GraphViz for a Merb application. Target class with CLASS=x,y,z; Font name with FONT=x; Image format with FORMAT=x; Orientation with ORIENTATION=x'
|
24
|
-
task :merb => [:merb_env] do
|
25
|
-
# Fix ruby-graphviz being incompatible with Merb's process title
|
26
|
-
$0 = 'rake'
|
27
|
-
Rake::Task['state_machine:draw'].invoke
|
28
|
-
end
|
29
|
-
end
|
30
27
|
end
|
@@ -40,7 +40,7 @@ class ModelBase
|
|
40
40
|
end
|
41
41
|
|
42
42
|
class Vehicle < ModelBase
|
43
|
-
attr_accessor :auto_shop, :seatbelt_on, :insurance_premium, :force_idle, :callbacks, :saved
|
43
|
+
attr_accessor :auto_shop, :seatbelt_on, :insurance_premium, :force_idle, :callbacks, :saved, :time_elapsed
|
44
44
|
|
45
45
|
def initialize(attributes = {})
|
46
46
|
attributes = {
|
@@ -68,6 +68,12 @@ class Vehicle < ModelBase
|
|
68
68
|
after_transition any => :parked, :do => lambda {|vehicle| vehicle.callbacks << 'before_enter_parked'}
|
69
69
|
before_transition any => :idling, :do => lambda {|vehicle| vehicle.callbacks << 'before_enter_idling'}
|
70
70
|
|
71
|
+
around_transition do |vehicle, transition, block|
|
72
|
+
time = Time.now
|
73
|
+
block.call
|
74
|
+
vehicle.time_elapsed = Time.now - time
|
75
|
+
end
|
76
|
+
|
71
77
|
event :park do
|
72
78
|
transition [:idling, :first_gear] => :parked
|
73
79
|
end
|
@@ -447,6 +453,10 @@ class VehicleIdlingTest < Test::Unit::TestCase
|
|
447
453
|
assert @vehicle.seatbelt_on
|
448
454
|
end
|
449
455
|
|
456
|
+
def test_should_track_time_elapsed
|
457
|
+
assert_not_nil @vehicle.time_elapsed
|
458
|
+
end
|
459
|
+
|
450
460
|
def test_should_allow_park
|
451
461
|
assert @vehicle.park
|
452
462
|
end
|
data/test/unit/callback_test.rb
CHANGED
@@ -1,25 +1,42 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
2
|
|
3
3
|
class CallbackTest < Test::Unit::TestCase
|
4
|
+
def test_should_raise_exception_if_invalid_type_specified
|
5
|
+
exception = assert_raise(ArgumentError) { StateMachine::Callback.new(:invalid) {} }
|
6
|
+
assert_equal 'Type must be :before, :after, or :around', exception.message
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_should_not_raise_exception_if_using_before_type
|
10
|
+
assert_nothing_raised { StateMachine::Callback.new(:before) {} }
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_not_raise_exception_if_using_after_type
|
14
|
+
assert_nothing_raised { StateMachine::Callback.new(:after) {} }
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_should_not_raise_exception_if_using_around_type
|
18
|
+
assert_nothing_raised { StateMachine::Callback.new(:around) {} }
|
19
|
+
end
|
20
|
+
|
4
21
|
def test_should_raise_exception_if_no_methods_specified
|
5
|
-
exception = assert_raise(ArgumentError) { StateMachine::Callback.new }
|
22
|
+
exception = assert_raise(ArgumentError) { StateMachine::Callback.new(:before) }
|
6
23
|
assert_equal 'Method(s) for callback must be specified', exception.message
|
7
24
|
end
|
8
25
|
|
9
26
|
def test_should_not_raise_exception_if_method_specified_in_do_option
|
10
|
-
assert_nothing_raised { StateMachine::Callback.new(:do => :run) }
|
27
|
+
assert_nothing_raised { StateMachine::Callback.new(:before, :do => :run) }
|
11
28
|
end
|
12
29
|
|
13
30
|
def test_should_not_raise_exception_if_method_specified_as_argument
|
14
|
-
assert_nothing_raised { StateMachine::Callback.new(:run) }
|
31
|
+
assert_nothing_raised { StateMachine::Callback.new(:before, :run) }
|
15
32
|
end
|
16
33
|
|
17
34
|
def test_should_not_raise_exception_if_method_specified_as_block
|
18
|
-
assert_nothing_raised { StateMachine::Callback.new(:run) {} }
|
35
|
+
assert_nothing_raised { StateMachine::Callback.new(:before, :run) {} }
|
19
36
|
end
|
20
37
|
|
21
38
|
def test_should_not_raise_exception_if_implicit_option_specified
|
22
|
-
assert_nothing_raised { StateMachine::Callback.new(:do => :run, :invalid => :valid) }
|
39
|
+
assert_nothing_raised { StateMachine::Callback.new(:before, :do => :run, :invalid => :valid) }
|
23
40
|
end
|
24
41
|
|
25
42
|
def test_should_not_bind_to_objects
|
@@ -33,7 +50,11 @@ end
|
|
33
50
|
|
34
51
|
class CallbackByDefaultTest < Test::Unit::TestCase
|
35
52
|
def setup
|
36
|
-
@callback = StateMachine::Callback.new(:
|
53
|
+
@callback = StateMachine::Callback.new(:before) {}
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_should_have_type
|
57
|
+
assert_equal :before, @callback.type
|
37
58
|
end
|
38
59
|
|
39
60
|
def test_should_not_have_a_terminator
|
@@ -53,7 +74,7 @@ end
|
|
53
74
|
|
54
75
|
class CallbackWithMethodArgumentTest < Test::Unit::TestCase
|
55
76
|
def setup
|
56
|
-
@callback = StateMachine::Callback.new(lambda {|*args| @args = args})
|
77
|
+
@callback = StateMachine::Callback.new(:before, lambda {|*args| @args = args})
|
57
78
|
|
58
79
|
@object = Object.new
|
59
80
|
@result = @callback.call(@object)
|
@@ -70,7 +91,7 @@ end
|
|
70
91
|
|
71
92
|
class CallbackWithMultipleMethodArgumentsTest < Test::Unit::TestCase
|
72
93
|
def setup
|
73
|
-
@callback = StateMachine::Callback.new(:run_1, :run_2)
|
94
|
+
@callback = StateMachine::Callback.new(:before, :run_1, :run_2)
|
74
95
|
|
75
96
|
class << @object = Object.new
|
76
97
|
attr_accessor :callbacks
|
@@ -98,7 +119,7 @@ end
|
|
98
119
|
|
99
120
|
class CallbackWithDoMethodTest < Test::Unit::TestCase
|
100
121
|
def setup
|
101
|
-
@callback = StateMachine::Callback.new(:do => lambda {|*args| @args = args})
|
122
|
+
@callback = StateMachine::Callback.new(:before, :do => lambda {|*args| @args = args})
|
102
123
|
|
103
124
|
@object = Object.new
|
104
125
|
@result = @callback.call(@object)
|
@@ -115,7 +136,7 @@ end
|
|
115
136
|
|
116
137
|
class CallbackWithMultipleDoMethodsTest < Test::Unit::TestCase
|
117
138
|
def setup
|
118
|
-
@callback = StateMachine::Callback.new(:do => [:run_1, :run_2])
|
139
|
+
@callback = StateMachine::Callback.new(:before, :do => [:run_1, :run_2])
|
119
140
|
|
120
141
|
class << @object = Object.new
|
121
142
|
attr_accessor :callbacks
|
@@ -143,7 +164,7 @@ end
|
|
143
164
|
|
144
165
|
class CallbackWithBlockTest < Test::Unit::TestCase
|
145
166
|
def setup
|
146
|
-
@callback = StateMachine::Callback.new do |*args|
|
167
|
+
@callback = StateMachine::Callback.new(:before) do |*args|
|
147
168
|
@args = args
|
148
169
|
end
|
149
170
|
|
@@ -162,7 +183,7 @@ end
|
|
162
183
|
|
163
184
|
class CallbackWithMixedMethodsTest < Test::Unit::TestCase
|
164
185
|
def setup
|
165
|
-
@callback = StateMachine::Callback.new(:run_argument, :do => :run_do) do |object|
|
186
|
+
@callback = StateMachine::Callback.new(:before, :run_argument, :do => :run_do) do |object|
|
166
187
|
object.callbacks << :block
|
167
188
|
end
|
168
189
|
|
@@ -193,7 +214,7 @@ end
|
|
193
214
|
class CallbackWithExplicitRequirementsTest < Test::Unit::TestCase
|
194
215
|
def setup
|
195
216
|
@object = Object.new
|
196
|
-
@callback = StateMachine::Callback.new(:from => :parked, :to => :idling, :on => :ignite, :do => lambda {})
|
217
|
+
@callback = StateMachine::Callback.new(:before, :from => :parked, :to => :idling, :on => :ignite, :do => lambda {})
|
197
218
|
end
|
198
219
|
|
199
220
|
def test_should_call_with_empty_context
|
@@ -224,7 +245,7 @@ end
|
|
224
245
|
class CallbackWithImplicitRequirementsTest < Test::Unit::TestCase
|
225
246
|
def setup
|
226
247
|
@object = Object.new
|
227
|
-
@callback = StateMachine::Callback.new(:parked => :idling, :on => :ignite, :do => lambda {})
|
248
|
+
@callback = StateMachine::Callback.new(:before, :parked => :idling, :on => :ignite, :do => lambda {})
|
228
249
|
end
|
229
250
|
|
230
251
|
def test_should_call_with_empty_context
|
@@ -258,12 +279,12 @@ class CallbackWithIfConditionTest < Test::Unit::TestCase
|
|
258
279
|
end
|
259
280
|
|
260
281
|
def test_should_call_if_true
|
261
|
-
callback = StateMachine::Callback.new(:if => lambda {true}, :do => lambda {})
|
282
|
+
callback = StateMachine::Callback.new(:before, :if => lambda {true}, :do => lambda {})
|
262
283
|
assert callback.call(@object)
|
263
284
|
end
|
264
285
|
|
265
286
|
def test_should_not_call_if_false
|
266
|
-
callback = StateMachine::Callback.new(:if => lambda {false}, :do => lambda {})
|
287
|
+
callback = StateMachine::Callback.new(:before, :if => lambda {false}, :do => lambda {})
|
267
288
|
assert !callback.call(@object)
|
268
289
|
end
|
269
290
|
end
|
@@ -274,12 +295,12 @@ class CallbackWithUnlessConditionTest < Test::Unit::TestCase
|
|
274
295
|
end
|
275
296
|
|
276
297
|
def test_should_call_if_false
|
277
|
-
callback = StateMachine::Callback.new(:unless => lambda {false}, :do => lambda {})
|
298
|
+
callback = StateMachine::Callback.new(:before, :unless => lambda {false}, :do => lambda {})
|
278
299
|
assert callback.call(@object)
|
279
300
|
end
|
280
301
|
|
281
302
|
def test_should_not_call_if_true
|
282
|
-
callback = StateMachine::Callback.new(:unless => lambda {true}, :do => lambda {})
|
303
|
+
callback = StateMachine::Callback.new(:before, :unless => lambda {true}, :do => lambda {})
|
283
304
|
assert !callback.call(@object)
|
284
305
|
end
|
285
306
|
end
|
@@ -290,7 +311,7 @@ class CallbackWithoutTerminatorTest < Test::Unit::TestCase
|
|
290
311
|
end
|
291
312
|
|
292
313
|
def test_should_not_halt_if_result_is_false
|
293
|
-
callback = StateMachine::Callback.new(:do => lambda {false}, :terminator => nil)
|
314
|
+
callback = StateMachine::Callback.new(:before, :do => lambda {false}, :terminator => nil)
|
294
315
|
assert_nothing_thrown { callback.call(@object) }
|
295
316
|
end
|
296
317
|
end
|
@@ -301,24 +322,24 @@ class CallbackWithTerminatorTest < Test::Unit::TestCase
|
|
301
322
|
end
|
302
323
|
|
303
324
|
def test_should_not_halt_if_terminator_does_not_match
|
304
|
-
callback = StateMachine::Callback.new(:do => lambda {false}, :terminator => lambda {|result| result == true})
|
325
|
+
callback = StateMachine::Callback.new(:before, :do => lambda {false}, :terminator => lambda {|result| result == true})
|
305
326
|
assert_nothing_thrown { callback.call(@object) }
|
306
327
|
end
|
307
328
|
|
308
329
|
def test_should_halt_if_terminator_matches
|
309
|
-
callback = StateMachine::Callback.new(:do => lambda {false}, :terminator => lambda {|result| result == false})
|
330
|
+
callback = StateMachine::Callback.new(:before, :do => lambda {false}, :terminator => lambda {|result| result == false})
|
310
331
|
assert_throws(:halt) { callback.call(@object) }
|
311
332
|
end
|
312
333
|
|
313
334
|
def test_should_halt_if_terminator_matches_any_method
|
314
|
-
callback = StateMachine::Callback.new(:do => [lambda {true}, lambda {false}], :terminator => lambda {|result| result == false})
|
335
|
+
callback = StateMachine::Callback.new(:before, :do => [lambda {true}, lambda {false}], :terminator => lambda {|result| result == false})
|
315
336
|
assert_throws(:halt) { callback.call(@object) }
|
316
337
|
end
|
317
338
|
end
|
318
339
|
|
319
340
|
class CallbackWithoutArgumentsTest < Test::Unit::TestCase
|
320
341
|
def setup
|
321
|
-
@callback = StateMachine::Callback.new(:do => lambda {|object| @arg = object})
|
342
|
+
@callback = StateMachine::Callback.new(:before, :do => lambda {|object| @arg = object})
|
322
343
|
|
323
344
|
@object = Object.new
|
324
345
|
@callback.call(@object, {}, 1, 2, 3)
|
@@ -331,7 +352,7 @@ end
|
|
331
352
|
|
332
353
|
class CallbackWithArgumentsTest < Test::Unit::TestCase
|
333
354
|
def setup
|
334
|
-
@callback = StateMachine::Callback.new(:do => lambda {|*args| @args = args})
|
355
|
+
@callback = StateMachine::Callback.new(:before, :do => lambda {|*args| @args = args})
|
335
356
|
|
336
357
|
@object = Object.new
|
337
358
|
@callback.call(@object, {}, 1, 2, 3)
|
@@ -344,7 +365,7 @@ end
|
|
344
365
|
|
345
366
|
class CallbackWithUnboundMethodTest < Test::Unit::TestCase
|
346
367
|
def setup
|
347
|
-
@callback = StateMachine::Callback.new(:do => lambda {|*args| @context = args.unshift(self)})
|
368
|
+
@callback = StateMachine::Callback.new(:before, :do => lambda {|*args| @context = args.unshift(self)})
|
348
369
|
|
349
370
|
@object = Object.new
|
350
371
|
@callback.call(@object, {}, 1, 2, 3)
|
@@ -362,7 +383,7 @@ class CallbackWithBoundMethodTest < Test::Unit::TestCase
|
|
362
383
|
|
363
384
|
def test_should_call_method_within_the_context_of_the_object_for_block_methods
|
364
385
|
context = nil
|
365
|
-
callback = StateMachine::Callback.new(:do => lambda {|*args| context = [self] + args}, :bind_to_object => true)
|
386
|
+
callback = StateMachine::Callback.new(:before, :do => lambda {|*args| context = [self] + args}, :bind_to_object => true)
|
366
387
|
callback.call(@object, {}, 1, 2, 3)
|
367
388
|
|
368
389
|
assert_equal [@object, 1, 2, 3], context
|
@@ -377,14 +398,14 @@ class CallbackWithBoundMethodTest < Test::Unit::TestCase
|
|
377
398
|
end
|
378
399
|
end
|
379
400
|
|
380
|
-
callback = StateMachine::Callback.new(:do => :after_ignite, :bind_to_object => true)
|
401
|
+
callback = StateMachine::Callback.new(:before, :do => :after_ignite, :bind_to_object => true)
|
381
402
|
callback.call(@object)
|
382
403
|
|
383
404
|
assert_equal [], @object.context
|
384
405
|
end
|
385
406
|
|
386
407
|
def test_should_ignore_option_for_string_methods
|
387
|
-
callback = StateMachine::Callback.new(:do => '[1, 2, 3]', :bind_to_object => true)
|
408
|
+
callback = StateMachine::Callback.new(:before, :do => '[1, 2, 3]', :bind_to_object => true)
|
388
409
|
assert callback.call(@object)
|
389
410
|
end
|
390
411
|
end
|
@@ -396,7 +417,7 @@ class CallbackWithMultipleBoundMethodsTest < Test::Unit::TestCase
|
|
396
417
|
first_context = nil
|
397
418
|
second_context = nil
|
398
419
|
|
399
|
-
@callback = StateMachine::Callback.new(:do => [lambda {first_context = self}, lambda {second_context = self}], :bind_to_object => true)
|
420
|
+
@callback = StateMachine::Callback.new(:before, :do => [lambda {first_context = self}, lambda {second_context = self}], :bind_to_object => true)
|
400
421
|
@callback.call(@object)
|
401
422
|
|
402
423
|
@first_context = first_context
|
@@ -415,7 +436,7 @@ class CallbackWithApplicationBoundObjectTest < Test::Unit::TestCase
|
|
415
436
|
StateMachine::Callback.bind_to_object = true
|
416
437
|
|
417
438
|
context = nil
|
418
|
-
@callback = StateMachine::Callback.new(:do => lambda {|*args| context = self})
|
439
|
+
@callback = StateMachine::Callback.new(:before, :do => lambda {|*args| context = self})
|
419
440
|
|
420
441
|
@object = Object.new
|
421
442
|
@callback.call(@object)
|
@@ -431,6 +452,33 @@ class CallbackWithApplicationBoundObjectTest < Test::Unit::TestCase
|
|
431
452
|
end
|
432
453
|
end
|
433
454
|
|
455
|
+
class CallbackWithBoundMethodAndArgumentsTest < Test::Unit::TestCase
|
456
|
+
def setup
|
457
|
+
@object = Object.new
|
458
|
+
end
|
459
|
+
|
460
|
+
def test_should_include_single_argument_if_specified
|
461
|
+
context = nil
|
462
|
+
callback = StateMachine::Callback.new(:before, :do => lambda {|arg1| context = [arg1]}, :bind_to_object => true)
|
463
|
+
callback.call(@object, {}, 1)
|
464
|
+
assert_equal [1], context
|
465
|
+
end
|
466
|
+
|
467
|
+
def test_should_include_multiple_arguments_if_specified
|
468
|
+
context = nil
|
469
|
+
callback = StateMachine::Callback.new(:before, :do => lambda {|arg1, arg2, arg3| context = [arg1, arg2, arg3]}, :bind_to_object => true)
|
470
|
+
callback.call(@object, {}, 1, 2, 3)
|
471
|
+
assert_equal [1, 2, 3], context
|
472
|
+
end
|
473
|
+
|
474
|
+
def test_should_include_arguments_if_splat_used
|
475
|
+
context = nil
|
476
|
+
callback = StateMachine::Callback.new(:before, :do => lambda {|*args| context = args}, :bind_to_object => true)
|
477
|
+
callback.call(@object, {}, 1, 2, 3)
|
478
|
+
assert_equal [1, 2, 3], context
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
434
482
|
class CallbackWithApplicationTerminatorTest < Test::Unit::TestCase
|
435
483
|
def setup
|
436
484
|
@original_terminator = StateMachine::Callback.bind_to_object
|
@@ -440,12 +488,12 @@ class CallbackWithApplicationTerminatorTest < Test::Unit::TestCase
|
|
440
488
|
end
|
441
489
|
|
442
490
|
def test_should_not_halt_if_terminator_does_not_match
|
443
|
-
callback = StateMachine::Callback.new(:do => lambda {true})
|
491
|
+
callback = StateMachine::Callback.new(:before, :do => lambda {true})
|
444
492
|
assert_nothing_thrown { callback.call(@object) }
|
445
493
|
end
|
446
494
|
|
447
495
|
def test_should_halt_if_terminator_matches
|
448
|
-
callback = StateMachine::Callback.new(:do => lambda {false})
|
496
|
+
callback = StateMachine::Callback.new(:before, :do => lambda {false})
|
449
497
|
assert_throws(:halt) { callback.call(@object) }
|
450
498
|
end
|
451
499
|
|
@@ -453,3 +501,228 @@ class CallbackWithApplicationTerminatorTest < Test::Unit::TestCase
|
|
453
501
|
StateMachine::Callback.bind_to_object = @original_bind_to_object
|
454
502
|
end
|
455
503
|
end
|
504
|
+
|
505
|
+
class CallbackWithAroundTypeAndBlockTest < Test::Unit::TestCase
|
506
|
+
def setup
|
507
|
+
@object = Object.new
|
508
|
+
@callbacks = []
|
509
|
+
end
|
510
|
+
|
511
|
+
def test_should_evaluate_before_without_after
|
512
|
+
callback = StateMachine::Callback.new(:around, lambda {|*args| block = args.pop; @args = args; block.call})
|
513
|
+
assert callback.call(@object)
|
514
|
+
assert_equal [@object], @args
|
515
|
+
end
|
516
|
+
|
517
|
+
def test_should_evaluate_after_without_before
|
518
|
+
callback = StateMachine::Callback.new(:around, lambda {|*args| block = args.pop; block.call; @args = args})
|
519
|
+
assert callback.call(@object)
|
520
|
+
assert_equal [@object], @args
|
521
|
+
end
|
522
|
+
|
523
|
+
def test_should_halt_if_not_yielded
|
524
|
+
callback = StateMachine::Callback.new(:around, lambda {|block|})
|
525
|
+
assert_throws(:halt) { callback.call(@object) }
|
526
|
+
end
|
527
|
+
|
528
|
+
def test_should_call_block_after_before
|
529
|
+
callback = StateMachine::Callback.new(:around, lambda {|block| @callbacks << :before; block.call})
|
530
|
+
assert callback.call(@object) { @callbacks << :block }
|
531
|
+
assert_equal [:before, :block], @callbacks
|
532
|
+
end
|
533
|
+
|
534
|
+
def test_should_call_block_before_after
|
535
|
+
@callbacks = []
|
536
|
+
callback = StateMachine::Callback.new(:around, lambda {|block| block.call; @callbacks << :after})
|
537
|
+
assert callback.call(@object) { @callbacks << :block }
|
538
|
+
assert_equal [:block, :after], @callbacks
|
539
|
+
end
|
540
|
+
|
541
|
+
def test_should_halt_if_block_halts
|
542
|
+
callback = StateMachine::Callback.new(:around, lambda {|block| block.call; @callbacks << :after})
|
543
|
+
assert_throws(:halt) { callback.call(@object) { throw :halt } }
|
544
|
+
assert_equal [], @callbacks
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
class CallbackWithAroundTypeAndMultipleMethodsTest < Test::Unit::TestCase
|
549
|
+
def setup
|
550
|
+
@callback = StateMachine::Callback.new(:around, :run_1, :run_2)
|
551
|
+
|
552
|
+
class << @object = Object.new
|
553
|
+
attr_accessor :before_callbacks
|
554
|
+
attr_accessor :after_callbacks
|
555
|
+
|
556
|
+
def run_1
|
557
|
+
(@before_callbacks ||= []) << :run_1
|
558
|
+
yield
|
559
|
+
(@after_callbacks ||= []) << :run_1
|
560
|
+
end
|
561
|
+
|
562
|
+
def run_2
|
563
|
+
(@before_callbacks ||= []) << :run_2
|
564
|
+
yield
|
565
|
+
(@after_callbacks ||= []) << :run_2
|
566
|
+
end
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
def test_should_succeed
|
571
|
+
assert @callback.call(@object)
|
572
|
+
end
|
573
|
+
|
574
|
+
def test_should_evaluate_before_callbacks_in_order
|
575
|
+
@callback.call(@object)
|
576
|
+
assert_equal [:run_1, :run_2], @object.before_callbacks
|
577
|
+
end
|
578
|
+
|
579
|
+
def test_should_evaluate_after_callbacks_in_reverse_order
|
580
|
+
@callback.call(@object)
|
581
|
+
assert_equal [:run_2, :run_1], @object.after_callbacks
|
582
|
+
end
|
583
|
+
|
584
|
+
def test_should_call_block_after_before_callbacks
|
585
|
+
@callback.call(@object) { (@object.before_callbacks ||= []) << :block }
|
586
|
+
assert_equal [:run_1, :run_2, :block], @object.before_callbacks
|
587
|
+
end
|
588
|
+
|
589
|
+
def test_should_call_block_before_after_callbacks
|
590
|
+
@callback.call(@object) { (@object.after_callbacks ||= []) << :block }
|
591
|
+
assert_equal [:block, :run_2, :run_1], @object.after_callbacks
|
592
|
+
end
|
593
|
+
|
594
|
+
def test_should_halt_if_first_doesnt_yield
|
595
|
+
class << @object
|
596
|
+
def run_1
|
597
|
+
(@before_callbacks ||= []) << :run_1
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
catch(:halt) do
|
602
|
+
@callback.call(@object) { (@object.before_callbacks ||= []) << :block }
|
603
|
+
end
|
604
|
+
|
605
|
+
assert_equal [:run_1], @object.before_callbacks
|
606
|
+
assert_nil @object.after_callbacks
|
607
|
+
end
|
608
|
+
|
609
|
+
def test_should_halt_if_last_doesnt_yield
|
610
|
+
class << @object
|
611
|
+
def run_2
|
612
|
+
(@before_callbacks ||= []) << :run_2
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
616
|
+
catch(:halt) { @callback.call(@object) }
|
617
|
+
assert_equal [:run_1, :run_2], @object.before_callbacks
|
618
|
+
assert_nil @object.after_callbacks
|
619
|
+
end
|
620
|
+
|
621
|
+
def test_should_not_evaluate_further_methods_if_after_halts
|
622
|
+
class << @object
|
623
|
+
def run_2
|
624
|
+
(@before_callbacks ||= []) << :run_2
|
625
|
+
yield
|
626
|
+
(@after_callbacks ||= []) << :run_2
|
627
|
+
throw :halt
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
631
|
+
catch(:halt) { @callback.call(@object) }
|
632
|
+
assert_equal [:run_1, :run_2], @object.before_callbacks
|
633
|
+
assert_equal [:run_2], @object.after_callbacks
|
634
|
+
end
|
635
|
+
end
|
636
|
+
|
637
|
+
class CallbackWithAroundTypeAndArgumentsTest < Test::Unit::TestCase
|
638
|
+
def setup
|
639
|
+
@object = Object.new
|
640
|
+
end
|
641
|
+
|
642
|
+
def test_should_include_object_if_specified
|
643
|
+
callback = StateMachine::Callback.new(:around, lambda {|object, block| @args = [object]; block.call})
|
644
|
+
callback.call(@object)
|
645
|
+
assert_equal [@object], @args
|
646
|
+
end
|
647
|
+
|
648
|
+
def test_should_include_arguments_if_specified
|
649
|
+
callback = StateMachine::Callback.new(:around, lambda {|object, arg1, arg2, arg3, block| @args = [object, arg1, arg2, arg3]; block.call})
|
650
|
+
callback.call(@object, {}, 1, 2, 3)
|
651
|
+
assert_equal [@object, 1, 2, 3], @args
|
652
|
+
end
|
653
|
+
|
654
|
+
def test_should_include_arguments_if_splat_used
|
655
|
+
callback = StateMachine::Callback.new(:around, lambda {|*args| block = args.pop; @args = args; block.call})
|
656
|
+
callback.call(@object, {}, 1, 2, 3)
|
657
|
+
assert_equal [@object, 1, 2, 3], @args
|
658
|
+
end
|
659
|
+
end
|
660
|
+
|
661
|
+
class CallbackWithAroundTypeAndTerminatorTest < Test::Unit::TestCase
|
662
|
+
def setup
|
663
|
+
@object = Object.new
|
664
|
+
end
|
665
|
+
|
666
|
+
def test_should_not_halt_if_terminator_does_not_match
|
667
|
+
callback = StateMachine::Callback.new(:around, :do => lambda {|block| block.call(false); false}, :terminator => lambda {|result| result == true})
|
668
|
+
assert_nothing_thrown { callback.call(@object) }
|
669
|
+
end
|
670
|
+
|
671
|
+
def test_should_not_halt_if_terminator_matches
|
672
|
+
callback = StateMachine::Callback.new(:around, :do => lambda {|block| block.call(false); false}, :terminator => lambda {|result| result == false})
|
673
|
+
assert_nothing_thrown { callback.call(@object) }
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
677
|
+
class CallbackWithAroundTypeAndBoundMethodTest < Test::Unit::TestCase
|
678
|
+
def setup
|
679
|
+
@object = Object.new
|
680
|
+
end
|
681
|
+
|
682
|
+
def test_should_call_method_within_the_context_of_the_object
|
683
|
+
context = nil
|
684
|
+
callback = StateMachine::Callback.new(:around, :do => lambda {|block| context = self; block.call}, :bind_to_object => true)
|
685
|
+
callback.call(@object, {}, 1, 2, 3)
|
686
|
+
|
687
|
+
assert_equal @object, context
|
688
|
+
end
|
689
|
+
|
690
|
+
def test_should_include_arguments_if_specified
|
691
|
+
context = nil
|
692
|
+
callback = StateMachine::Callback.new(:around, :do => lambda {|*args| block = args.pop; context = args; block.call}, :bind_to_object => true)
|
693
|
+
callback.call(@object, {}, 1, 2, 3)
|
694
|
+
|
695
|
+
assert_equal [1, 2, 3], context
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
class CallbackSuccessMatcherTest < Test::Unit::TestCase
|
700
|
+
def setup
|
701
|
+
@object = Object.new
|
702
|
+
end
|
703
|
+
|
704
|
+
def test_should_match_if_not_specified
|
705
|
+
callback = StateMachine::Callback.new(:before) {}
|
706
|
+
assert callback.matches_success?(true)
|
707
|
+
end
|
708
|
+
|
709
|
+
def test_should_match_if_true_and_not_including_failures
|
710
|
+
callback = StateMachine::Callback.new(:before, :include_failures => false) {}
|
711
|
+
assert callback.matches_success?(true)
|
712
|
+
end
|
713
|
+
|
714
|
+
def test_should_match_if_true_and_including_failures
|
715
|
+
callback = StateMachine::Callback.new(:before, :include_failures => true) {}
|
716
|
+
assert callback.matches_success?(true)
|
717
|
+
end
|
718
|
+
|
719
|
+
def test_should_not_match_if_false_and_not_including_failures
|
720
|
+
callback = StateMachine::Callback.new(:before, :include_failures => false) {}
|
721
|
+
assert !callback.matches_success?(false)
|
722
|
+
end
|
723
|
+
|
724
|
+
def test_Should_match_if_false_and_including_failures
|
725
|
+
callback = StateMachine::Callback.new(:before, :include_failures => true) {}
|
726
|
+
assert callback.matches_success?(false)
|
727
|
+
end
|
728
|
+
end
|