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
@@ -61,6 +61,10 @@ class TransitionTest < Test::Unit::TestCase
|
|
61
61
|
assert_nil @transition.action
|
62
62
|
end
|
63
63
|
|
64
|
+
def test_should_not_be_transient
|
65
|
+
assert_equal false, @transition.transient?
|
66
|
+
end
|
67
|
+
|
64
68
|
def test_should_generate_attributes
|
65
69
|
expected = {:object => @object, :attribute => :state, :event => :ignite, :from => 'parked', :to => 'idling'}
|
66
70
|
assert_equal expected, @transition.attributes
|
@@ -350,16 +354,9 @@ class TransitionAfterBeingRolledBackTest < Test::Unit::TestCase
|
|
350
354
|
end
|
351
355
|
end
|
352
356
|
|
353
|
-
class
|
357
|
+
class TransitionWithoutCallbacksTest < Test::Unit::TestCase
|
354
358
|
def setup
|
355
|
-
@klass = Class.new
|
356
|
-
attr_reader :saved, :save_state
|
357
|
-
|
358
|
-
def save
|
359
|
-
@save_state = state
|
360
|
-
@saved = true
|
361
|
-
end
|
362
|
-
end
|
359
|
+
@klass = Class.new
|
363
360
|
|
364
361
|
@machine = StateMachine::Machine.new(@klass)
|
365
362
|
@machine.state :parked, :idling
|
@@ -370,24 +367,47 @@ class TransitionWithCallbacksTest < Test::Unit::TestCase
|
|
370
367
|
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
371
368
|
end
|
372
369
|
|
373
|
-
def
|
374
|
-
|
375
|
-
|
370
|
+
def test_should_succeed
|
371
|
+
assert_equal true, @transition.run_callbacks
|
372
|
+
end
|
373
|
+
|
374
|
+
def test_should_succeed_if_after_callbacks_skipped
|
375
|
+
assert_equal true, @transition.run_callbacks(:after => false)
|
376
|
+
end
|
377
|
+
|
378
|
+
def test_should_call_block_if_provided
|
379
|
+
@transition.run_callbacks { @ran_block = true; {} }
|
380
|
+
assert @ran_block
|
381
|
+
end
|
382
|
+
|
383
|
+
def test_should_track_block_result
|
384
|
+
@transition.run_callbacks {{:result => 1}}
|
385
|
+
assert_equal 1, @transition.result
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
class TransitionWithBeforeCallbacksTest < Test::Unit::TestCase
|
390
|
+
def setup
|
391
|
+
@klass = Class.new
|
376
392
|
|
377
|
-
|
378
|
-
|
393
|
+
@machine = StateMachine::Machine.new(@klass)
|
394
|
+
@machine.state :parked, :idling
|
395
|
+
@machine.event :ignite
|
396
|
+
|
397
|
+
@object = @klass.new
|
398
|
+
@object.state = 'parked'
|
399
|
+
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
379
400
|
end
|
380
401
|
|
381
|
-
def
|
382
|
-
@
|
383
|
-
@
|
384
|
-
@machine.before_transition(lambda {@callbacks << 2})
|
385
|
-
@transition.before
|
402
|
+
def test_should_run_before_callbacks
|
403
|
+
@machine.before_transition {@run = true}
|
404
|
+
result = @transition.run_callbacks
|
386
405
|
|
387
|
-
assert_equal
|
406
|
+
assert_equal true, result
|
407
|
+
assert_equal true, @run
|
388
408
|
end
|
389
409
|
|
390
|
-
def
|
410
|
+
def test_should_only_run_those_that_match_transition_context
|
391
411
|
@count = 0
|
392
412
|
callback = lambda {@count += 1}
|
393
413
|
|
@@ -395,76 +415,142 @@ class TransitionWithCallbacksTest < Test::Unit::TestCase
|
|
395
415
|
@machine.before_transition :from => :parked, :to => :parked, :on => :park, :do => callback
|
396
416
|
@machine.before_transition :from => :parked, :to => :idling, :on => :ignite, :do => callback
|
397
417
|
@machine.before_transition :from => :idling, :to => :idling, :on => :park, :do => callback
|
398
|
-
@transition.
|
418
|
+
@transition.run_callbacks
|
399
419
|
|
400
420
|
assert_equal 1, @count
|
401
421
|
end
|
402
422
|
|
403
|
-
def
|
404
|
-
@machine.before_transition
|
405
|
-
@transition.
|
423
|
+
def test_should_pass_transition_as_argument
|
424
|
+
@machine.before_transition {|*args| @args = args}
|
425
|
+
@transition.run_callbacks
|
406
426
|
|
407
427
|
assert_equal [@object, @transition], @args
|
408
428
|
end
|
409
429
|
|
410
|
-
def
|
411
|
-
@machine.before_transition
|
430
|
+
def test_should_catch_halts
|
431
|
+
@machine.before_transition {throw :halt}
|
412
432
|
|
413
433
|
result = nil
|
414
|
-
assert_nothing_thrown { result = @transition.
|
434
|
+
assert_nothing_thrown { result = @transition.run_callbacks }
|
415
435
|
assert_equal false, result
|
416
436
|
end
|
417
437
|
|
418
|
-
def
|
419
|
-
@machine.before_transition
|
420
|
-
@transition.
|
421
|
-
|
422
|
-
assert_equal 'parked', @state
|
438
|
+
def test_should_not_catch_exceptions
|
439
|
+
@machine.before_transition {raise ArgumentError}
|
440
|
+
assert_raise(ArgumentError) { @transition.run_callbacks }
|
423
441
|
end
|
424
442
|
|
425
|
-
def
|
443
|
+
def test_should_not_be_able_to_run_twice
|
426
444
|
@count = 0
|
427
|
-
@machine.before_transition
|
428
|
-
@transition.
|
429
|
-
@transition.
|
445
|
+
@machine.before_transition {@count += 1}
|
446
|
+
@transition.run_callbacks
|
447
|
+
@transition.run_callbacks
|
430
448
|
assert_equal 1, @count
|
431
449
|
end
|
432
450
|
|
433
|
-
def
|
451
|
+
def test_should_be_able_to_run_again_after_halt
|
452
|
+
@count = 0
|
453
|
+
@machine.before_transition {@count += 1; throw :halt}
|
454
|
+
@transition.run_callbacks
|
455
|
+
@transition.run_callbacks
|
456
|
+
assert_equal 2, @count
|
457
|
+
end
|
458
|
+
|
459
|
+
def test_should_be_able_to_run_again_after_resetting
|
434
460
|
@count = 0
|
435
|
-
@machine.before_transition
|
436
|
-
@transition.
|
461
|
+
@machine.before_transition {@count += 1}
|
462
|
+
@transition.run_callbacks
|
437
463
|
@transition.reset
|
438
|
-
@transition.
|
464
|
+
@transition.run_callbacks
|
439
465
|
assert_equal 2, @count
|
440
466
|
end
|
441
467
|
|
442
|
-
def
|
443
|
-
@machine.
|
444
|
-
|
445
|
-
|
446
|
-
assert_equal true, result
|
447
|
-
assert_equal true, @run
|
468
|
+
def test_should_succeed_if_block_result_is_false
|
469
|
+
@machine.before_transition {@run = true}
|
470
|
+
assert_equal true, @transition.run_callbacks {{:result => false}}
|
471
|
+
assert @run
|
448
472
|
end
|
449
473
|
|
450
|
-
def
|
451
|
-
@
|
452
|
-
|
474
|
+
def test_should_succeed_if_block_result_is_true
|
475
|
+
@machine.before_transition {@run = true}
|
476
|
+
assert_equal true, @transition.run_callbacks {{:result => true}}
|
477
|
+
assert @run
|
478
|
+
end
|
479
|
+
|
480
|
+
def test_should_succeed_if_block_success_is_false
|
481
|
+
@machine.before_transition {@run = true}
|
482
|
+
assert_equal true, @transition.run_callbacks {{:success => false}}
|
483
|
+
assert @run
|
484
|
+
end
|
485
|
+
|
486
|
+
def test_should_succeed_if_block_success_is_false
|
487
|
+
@machine.before_transition {@run = true}
|
488
|
+
assert_equal true, @transition.run_callbacks {{:success => true}}
|
489
|
+
assert @run
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
class TransitionWithMultipleBeforeCallbacksTest < Test::Unit::TestCase
|
494
|
+
def setup
|
495
|
+
@klass = Class.new
|
453
496
|
|
454
|
-
@
|
455
|
-
|
497
|
+
@machine = StateMachine::Machine.new(@klass)
|
498
|
+
@machine.state :parked, :idling
|
499
|
+
@machine.event :ignite
|
500
|
+
|
501
|
+
@object = @klass.new
|
502
|
+
@object.state = 'parked'
|
503
|
+
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
456
504
|
end
|
457
505
|
|
458
|
-
def
|
506
|
+
def test_should_run_in_the_order_they_were_defined
|
459
507
|
@callbacks = []
|
460
|
-
@machine.
|
461
|
-
@machine.
|
462
|
-
@transition.
|
508
|
+
@machine.before_transition {@callbacks << 1}
|
509
|
+
@machine.before_transition {@callbacks << 2}
|
510
|
+
@transition.run_callbacks
|
463
511
|
|
464
512
|
assert_equal [1, 2], @callbacks
|
465
513
|
end
|
466
514
|
|
467
|
-
def
|
515
|
+
def test_should_not_run_further_callbacks_if_halted
|
516
|
+
@callbacks = []
|
517
|
+
@machine.before_transition {@callbacks << 1; throw :halt}
|
518
|
+
@machine.before_transition {@callbacks << 2}
|
519
|
+
|
520
|
+
assert_equal false, @transition.run_callbacks
|
521
|
+
assert_equal [1], @callbacks
|
522
|
+
end
|
523
|
+
|
524
|
+
def test_should_fail_if_any_callback_halted
|
525
|
+
@machine.before_transition {true}
|
526
|
+
@machine.before_transition {throw :halt}
|
527
|
+
|
528
|
+
assert_equal false, @transition.run_callbacks
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
class TransitionWithAfterCallbacksTest < Test::Unit::TestCase
|
533
|
+
def setup
|
534
|
+
@klass = Class.new
|
535
|
+
|
536
|
+
@machine = StateMachine::Machine.new(@klass)
|
537
|
+
@machine.state :parked, :idling
|
538
|
+
@machine.event :ignite
|
539
|
+
|
540
|
+
@object = @klass.new
|
541
|
+
@object.state = 'parked'
|
542
|
+
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
543
|
+
end
|
544
|
+
|
545
|
+
def test_should_run_after_callbacks
|
546
|
+
@machine.after_transition {|object| @run = true}
|
547
|
+
result = @transition.run_callbacks
|
548
|
+
|
549
|
+
assert_equal true, result
|
550
|
+
assert_equal true, @run
|
551
|
+
end
|
552
|
+
|
553
|
+
def test_should_only_run_those_that_match_transition_context
|
468
554
|
@count = 0
|
469
555
|
callback = lambda {@count += 1}
|
470
556
|
|
@@ -472,119 +558,125 @@ class TransitionWithCallbacksTest < Test::Unit::TestCase
|
|
472
558
|
@machine.after_transition :from => :parked, :to => :parked, :on => :park, :do => callback
|
473
559
|
@machine.after_transition :from => :parked, :to => :idling, :on => :ignite, :do => callback
|
474
560
|
@machine.after_transition :from => :idling, :to => :idling, :on => :park, :do => callback
|
475
|
-
@transition.
|
561
|
+
@transition.run_callbacks
|
476
562
|
|
477
563
|
assert_equal 1, @count
|
478
564
|
end
|
479
565
|
|
480
|
-
def
|
481
|
-
@machine.after_transition
|
482
|
-
@transition.
|
566
|
+
def test_should_not_run_if_not_successful
|
567
|
+
@machine.after_transition {|object| @run = true}
|
568
|
+
@transition.run_callbacks {{:success => false}}
|
483
569
|
assert !@run
|
484
570
|
end
|
485
571
|
|
486
|
-
def
|
487
|
-
@machine.after_transition(
|
488
|
-
|
489
|
-
@
|
490
|
-
|
491
|
-
|
572
|
+
def test_should_run_if_not_successful_and_includes_failures
|
573
|
+
@machine.after_transition(:include_failures => true) {|object| @run = true}
|
574
|
+
@transition.run_callbacks {{:success => false}}
|
575
|
+
assert @run
|
576
|
+
end
|
577
|
+
|
578
|
+
def test_should_run_if_successful
|
579
|
+
@machine.after_transition {|object| @run = true}
|
580
|
+
@transition.run_callbacks {{:success => true}}
|
581
|
+
assert @run
|
582
|
+
end
|
583
|
+
|
584
|
+
def test_should_run_if_successful_and_includes_failures
|
585
|
+
@machine.after_transition(:include_failures => true) {|object| @run = true}
|
586
|
+
@transition.run_callbacks {{:success => true}}
|
587
|
+
assert @run
|
588
|
+
end
|
589
|
+
|
590
|
+
def test_should_pass_transition_as_argument
|
591
|
+
@machine.after_transition {|*args| @args = args}
|
492
592
|
|
493
|
-
@transition.
|
593
|
+
@transition.run_callbacks
|
494
594
|
assert_equal [@object, @transition], @args
|
495
|
-
assert_equal false, @transition.result
|
496
595
|
end
|
497
596
|
|
498
|
-
def
|
499
|
-
@machine.after_transition
|
597
|
+
def test_should_catch_halts
|
598
|
+
@machine.after_transition {throw :halt}
|
500
599
|
|
501
600
|
result = nil
|
502
|
-
assert_nothing_thrown { result = @transition.
|
601
|
+
assert_nothing_thrown { result = @transition.run_callbacks }
|
503
602
|
assert_equal true, result
|
504
603
|
end
|
505
604
|
|
506
|
-
def
|
507
|
-
@machine.after_transition
|
508
|
-
@transition.
|
509
|
-
|
510
|
-
|
605
|
+
def test_should_not_catch_exceptions
|
606
|
+
@machine.after_transition {raise ArgumentError}
|
607
|
+
assert_raise(ArgumentError) { @transition.run_callbacks }
|
608
|
+
end
|
609
|
+
|
610
|
+
def test_should_not_be_able_to_run_twice
|
611
|
+
@count = 0
|
612
|
+
@machine.after_transition {@count += 1}
|
613
|
+
@transition.run_callbacks
|
614
|
+
@transition.run_callbacks
|
615
|
+
assert_equal 1, @count
|
511
616
|
end
|
512
617
|
|
513
|
-
def
|
618
|
+
def test_should_not_be_able_to_run_twice_if_halted
|
514
619
|
@count = 0
|
515
|
-
@machine.after_transition
|
516
|
-
@transition.
|
517
|
-
@transition.
|
620
|
+
@machine.after_transition {@count += 1; throw :halt}
|
621
|
+
@transition.run_callbacks
|
622
|
+
@transition.run_callbacks
|
518
623
|
assert_equal 1, @count
|
519
624
|
end
|
520
625
|
|
521
|
-
def
|
626
|
+
def test_should_be_able_to_run_again_after_resetting
|
522
627
|
@count = 0
|
523
|
-
@machine.after_transition
|
524
|
-
@transition.
|
628
|
+
@machine.after_transition {@count += 1}
|
629
|
+
@transition.run_callbacks
|
525
630
|
@transition.reset
|
526
|
-
@transition.
|
631
|
+
@transition.run_callbacks
|
527
632
|
assert_equal 2, @count
|
528
633
|
end
|
529
634
|
end
|
530
635
|
|
531
|
-
class
|
636
|
+
class TransitionWithMultipleAfterCallbacksTest < Test::Unit::TestCase
|
532
637
|
def setup
|
533
|
-
@klass = Class.new
|
534
|
-
attr_reader :saved, :save_state
|
535
|
-
|
536
|
-
def save
|
537
|
-
@save_state = state
|
538
|
-
@saved = true
|
539
|
-
end
|
540
|
-
end
|
638
|
+
@klass = Class.new
|
541
639
|
|
542
|
-
@machine = StateMachine::Machine.new(@klass
|
640
|
+
@machine = StateMachine::Machine.new(@klass)
|
543
641
|
@machine.state :parked, :idling
|
544
642
|
@machine.event :ignite
|
545
643
|
|
546
644
|
@object = @klass.new
|
547
645
|
@object.state = 'parked'
|
548
646
|
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
549
|
-
@result = @transition.perform
|
550
|
-
end
|
551
|
-
|
552
|
-
def test_should_have_empty_args
|
553
|
-
assert_equal [], @transition.args
|
554
|
-
end
|
555
|
-
|
556
|
-
def test_should_have_a_result
|
557
|
-
assert_equal true, @transition.result
|
558
|
-
end
|
559
|
-
|
560
|
-
def test_should_be_successful
|
561
|
-
assert_equal true, @result
|
562
647
|
end
|
563
648
|
|
564
|
-
def
|
565
|
-
|
649
|
+
def test_should_run_in_the_order_they_were_defined
|
650
|
+
@callbacks = []
|
651
|
+
@machine.after_transition {@callbacks << 1}
|
652
|
+
@machine.after_transition {@callbacks << 2}
|
653
|
+
@transition.run_callbacks
|
654
|
+
|
655
|
+
assert_equal [1, 2], @callbacks
|
566
656
|
end
|
567
657
|
|
568
|
-
def
|
569
|
-
|
658
|
+
def test_should_not_run_further_callbacks_if_halted
|
659
|
+
@callbacks = []
|
660
|
+
@machine.after_transition {@callbacks << 1; throw :halt}
|
661
|
+
@machine.after_transition {@callbacks << 2}
|
662
|
+
|
663
|
+
assert_equal true, @transition.run_callbacks
|
664
|
+
assert_equal [1], @callbacks
|
570
665
|
end
|
571
666
|
|
572
|
-
def
|
573
|
-
|
667
|
+
def test_should_fail_if_any_callback_halted
|
668
|
+
@machine.after_transition {true}
|
669
|
+
@machine.after_transition {throw :halt}
|
670
|
+
|
671
|
+
assert_equal true, @transition.run_callbacks
|
574
672
|
end
|
575
673
|
end
|
576
674
|
|
577
|
-
class
|
675
|
+
class TransitionWithAroundCallbacksTest < Test::Unit::TestCase
|
578
676
|
def setup
|
579
|
-
@klass = Class.new
|
580
|
-
attr_reader :saved
|
581
|
-
|
582
|
-
def save
|
583
|
-
@saved = true
|
584
|
-
end
|
585
|
-
end
|
677
|
+
@klass = Class.new
|
586
678
|
|
587
|
-
@machine = StateMachine::Machine.new(@klass
|
679
|
+
@machine = StateMachine::Machine.new(@klass)
|
588
680
|
@machine.state :parked, :idling
|
589
681
|
@machine.event :ignite
|
590
682
|
|
@@ -593,308 +685,551 @@ class TransitionWithPerformArgumentsTest < Test::Unit::TestCase
|
|
593
685
|
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
594
686
|
end
|
595
687
|
|
596
|
-
def
|
597
|
-
@
|
688
|
+
def test_should_run_around_callbacks
|
689
|
+
@machine.around_transition {|object, transition, block| @run_before = true; block.call; @run_after = true}
|
690
|
+
result = @transition.run_callbacks
|
598
691
|
|
599
|
-
assert_equal
|
600
|
-
|
692
|
+
assert_equal true, result
|
693
|
+
assert_equal true, @run_before
|
694
|
+
assert_equal true, @run_after
|
601
695
|
end
|
602
696
|
|
603
|
-
def
|
604
|
-
@
|
697
|
+
def test_should_only_run_those_that_match_transition_context
|
698
|
+
@count = 0
|
699
|
+
callback = lambda {|object, transition, block| @count += 1; block.call}
|
605
700
|
|
606
|
-
|
607
|
-
|
701
|
+
@machine.around_transition :from => :parked, :to => :idling, :on => :park, :do => callback
|
702
|
+
@machine.around_transition :from => :parked, :to => :parked, :on => :park, :do => callback
|
703
|
+
@machine.around_transition :from => :parked, :to => :idling, :on => :ignite, :do => callback
|
704
|
+
@machine.around_transition :from => :idling, :to => :idling, :on => :park, :do => callback
|
705
|
+
@transition.run_callbacks
|
706
|
+
|
707
|
+
assert_equal 1, @count
|
608
708
|
end
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
@klass = Class.new do
|
614
|
-
attr_reader :saved
|
615
|
-
|
616
|
-
def save
|
617
|
-
@saved = true
|
618
|
-
end
|
619
|
-
end
|
709
|
+
|
710
|
+
def test_should_pass_transition_as_argument
|
711
|
+
@machine.around_transition {|*args| block = args.pop; @args = args; block.call}
|
712
|
+
@transition.run_callbacks
|
620
713
|
|
621
|
-
@
|
622
|
-
|
623
|
-
|
624
|
-
|
714
|
+
assert_equal [@object, @transition], @args
|
715
|
+
end
|
716
|
+
|
717
|
+
def test_should_run_block_between_callback
|
718
|
+
@callbacks = []
|
719
|
+
@machine.around_transition {|block| @callbacks << :before; block.call; @callbacks << :after}
|
720
|
+
@transition.run_callbacks { @callbacks << :within; {:success => true} }
|
625
721
|
|
626
|
-
|
627
|
-
@object.state = 'parked'
|
628
|
-
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
629
|
-
@result = @transition.perform(false)
|
722
|
+
assert_equal [:before, :within, :after], @callbacks
|
630
723
|
end
|
631
724
|
|
632
|
-
def
|
633
|
-
|
725
|
+
def test_should_have_access_to_result_after_yield
|
726
|
+
@machine.around_transition {|block| @before_result = @transition.result; block.call; @after_result = @transition.result}
|
727
|
+
@transition.run_callbacks {{:result => 1, :success => true}}
|
728
|
+
|
729
|
+
assert_nil @before_result
|
730
|
+
assert_equal 1, @after_result
|
634
731
|
end
|
635
732
|
|
636
|
-
def
|
637
|
-
|
733
|
+
def test_should_catch_before_yield_halts
|
734
|
+
@machine.around_transition {throw :halt}
|
735
|
+
|
736
|
+
result = nil
|
737
|
+
assert_nothing_thrown { result = @transition.run_callbacks }
|
738
|
+
assert_equal false, result
|
638
739
|
end
|
639
740
|
|
640
|
-
def
|
641
|
-
|
741
|
+
def test_should_catch_after_yield_halts
|
742
|
+
@machine.around_transition {|block| block.call; throw :halt}
|
743
|
+
|
744
|
+
result = nil
|
745
|
+
assert_nothing_thrown { result = @transition.run_callbacks }
|
746
|
+
assert_equal true, result
|
642
747
|
end
|
643
748
|
|
644
|
-
def
|
645
|
-
|
749
|
+
def test_should_not_catch_before_yield
|
750
|
+
@machine.around_transition {raise ArgumentError}
|
751
|
+
assert_raise(ArgumentError) { @transition.run_callbacks }
|
646
752
|
end
|
647
753
|
|
648
|
-
def
|
649
|
-
|
754
|
+
def test_should_not_catch_after_yield
|
755
|
+
@machine.around_transition {|block| block.call; raise ArgumentError}
|
756
|
+
assert_raise(ArgumentError) { @transition.run_callbacks }
|
650
757
|
end
|
651
758
|
|
652
|
-
def
|
653
|
-
|
759
|
+
def test_should_fail_if_not_yielded
|
760
|
+
@machine.around_transition {}
|
761
|
+
|
762
|
+
result = nil
|
763
|
+
assert_nothing_thrown { result = @transition.run_callbacks }
|
764
|
+
assert_equal false, result
|
765
|
+
end
|
766
|
+
|
767
|
+
def test_should_not_be_able_to_run_twice
|
768
|
+
@before_count = 0
|
769
|
+
@after_count = 0
|
770
|
+
@machine.around_transition {|block| @before_count += 1; block.call; @after_count += 1}
|
771
|
+
@transition.run_callbacks
|
772
|
+
@transition.run_callbacks
|
773
|
+
assert_equal 1, @before_count
|
774
|
+
assert_equal 1, @after_count
|
775
|
+
end
|
776
|
+
|
777
|
+
def test_should_be_able_to_run_again_after_resetting
|
778
|
+
@before_count = 0
|
779
|
+
@after_count = 0
|
780
|
+
@machine.around_transition {|block| @before_count += 1; block.call; @after_count += 1}
|
781
|
+
@transition.run_callbacks
|
782
|
+
@transition.reset
|
783
|
+
@transition.run_callbacks
|
784
|
+
assert_equal 2, @before_count
|
785
|
+
assert_equal 2, @after_count
|
786
|
+
end
|
787
|
+
|
788
|
+
def test_should_succeed_if_block_result_is_false
|
789
|
+
@machine.around_transition {|block| @before_run = true; block.call; @after_run = true}
|
790
|
+
assert_equal true, @transition.run_callbacks {{:success => true, :result => false}}
|
791
|
+
assert @before_run
|
792
|
+
assert @after_run
|
793
|
+
end
|
794
|
+
|
795
|
+
def test_should_succeed_if_block_result_is_true
|
796
|
+
@machine.around_transition {|block| @before_run = true; block.call; @after_run = true}
|
797
|
+
assert_equal true, @transition.run_callbacks {{:success => true, :result => true}}
|
798
|
+
assert @before_run
|
799
|
+
assert @after_run
|
800
|
+
end
|
801
|
+
|
802
|
+
def test_should_only_run_before_if_block_success_is_false
|
803
|
+
@machine.around_transition {|block| @before_run = true; block.call; @after_run = true}
|
804
|
+
assert_equal true, @transition.run_callbacks {{:success => false}}
|
805
|
+
assert @before_run
|
806
|
+
assert !@after_run
|
807
|
+
end
|
808
|
+
|
809
|
+
def test_should_succeed_if_including_failure_and_block_success_is_false
|
810
|
+
@machine.around_transition(:include_failures => true) {|block| @before_run = true; block.call; @after_run = true}
|
811
|
+
assert_equal true, @transition.run_callbacks {{:success => false}}
|
812
|
+
assert @before_run
|
813
|
+
assert @after_run
|
814
|
+
end
|
815
|
+
|
816
|
+
def test_should_succeed_if_block_success_is_false
|
817
|
+
@machine.around_transition {|block| @before_run = true; block.call; @after_run = true}
|
818
|
+
assert_equal true, @transition.run_callbacks {{:success => true}}
|
819
|
+
assert @before_run
|
820
|
+
assert @after_run
|
654
821
|
end
|
655
822
|
end
|
656
823
|
|
657
|
-
class
|
824
|
+
class TransitionWithMultipleAroundCallbacksTest < Test::Unit::TestCase
|
658
825
|
def setup
|
659
|
-
@klass = Class.new
|
660
|
-
class << self
|
661
|
-
attr_accessor :running_transaction
|
662
|
-
end
|
663
|
-
|
664
|
-
attr_accessor :result
|
665
|
-
|
666
|
-
def save
|
667
|
-
@result = self.class.running_transaction
|
668
|
-
true
|
669
|
-
end
|
670
|
-
end
|
826
|
+
@klass = Class.new
|
671
827
|
|
672
|
-
@machine = StateMachine::Machine.new(@klass
|
828
|
+
@machine = StateMachine::Machine.new(@klass)
|
673
829
|
@machine.state :parked, :idling
|
674
830
|
@machine.event :ignite
|
675
831
|
|
676
832
|
@object = @klass.new
|
677
833
|
@object.state = 'parked'
|
678
834
|
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
679
|
-
|
680
|
-
class << @machine
|
681
|
-
def within_transaction(object)
|
682
|
-
owner_class.running_transaction = object
|
683
|
-
yield
|
684
|
-
owner_class.running_transaction = false
|
685
|
-
end
|
686
|
-
end
|
687
835
|
end
|
688
836
|
|
689
|
-
def
|
690
|
-
@
|
691
|
-
|
692
|
-
|
837
|
+
def test_should_before_yield_in_the_order_they_were_defined
|
838
|
+
@callbacks = []
|
839
|
+
@machine.around_transition {|block| @callbacks << 1; block.call}
|
840
|
+
@machine.around_transition {|block| @callbacks << 2; block.call}
|
841
|
+
@transition.run_callbacks
|
693
842
|
|
694
|
-
assert_equal
|
843
|
+
assert_equal [1, 2], @callbacks
|
695
844
|
end
|
696
845
|
|
697
|
-
def
|
698
|
-
@
|
699
|
-
@
|
846
|
+
def test_should_before_yield_multiple_methods_in_the_order_they_were_defined
|
847
|
+
@callbacks = []
|
848
|
+
@machine.around_transition(lambda {|block| @callbacks << 1; block.call}, lambda {|block| @callbacks << 2; block.call})
|
849
|
+
@machine.around_transition(lambda {|block| @callbacks << 3; block.call}, lambda {|block| @callbacks << 4; block.call})
|
850
|
+
@transition.run_callbacks
|
700
851
|
|
701
|
-
assert_equal
|
852
|
+
assert_equal [1, 2, 3, 4], @callbacks
|
702
853
|
end
|
703
854
|
|
704
|
-
def
|
705
|
-
@
|
855
|
+
def test_should_after_yield_in_the_reverse_order_they_were_defined
|
856
|
+
@callbacks = []
|
857
|
+
@machine.around_transition {|block| block.call; @callbacks << 1}
|
858
|
+
@machine.around_transition {|block| block.call; @callbacks << 2}
|
859
|
+
@transition.run_callbacks
|
706
860
|
|
707
|
-
assert_equal
|
861
|
+
assert_equal [2, 1], @callbacks
|
708
862
|
end
|
709
863
|
|
710
|
-
def
|
711
|
-
@
|
712
|
-
@
|
864
|
+
def test_should_after_yield_multiple_methods_in_the_reverse_order_they_were_defined
|
865
|
+
@callbacks = []
|
866
|
+
@machine.around_transition(lambda {|block| block.call; @callbacks << 1}) {|block| block.call; @callbacks << 2}
|
867
|
+
@machine.around_transition(lambda {|block| block.call; @callbacks << 3}) {|block| block.call; @callbacks << 4}
|
868
|
+
@transition.run_callbacks
|
713
869
|
|
714
|
-
assert_equal
|
870
|
+
assert_equal [4, 3, 2, 1], @callbacks
|
871
|
+
end
|
872
|
+
|
873
|
+
def test_should_run_block_between_callback
|
874
|
+
@callbacks = []
|
875
|
+
@machine.around_transition {|block| @callbacks << :before_1; block.call; @callbacks << :after_1}
|
876
|
+
@machine.around_transition {|block| @callbacks << :before_2; block.call; @callbacks << :after_2}
|
877
|
+
@transition.run_callbacks { @callbacks << :within; {:success => true} }
|
878
|
+
|
879
|
+
assert_equal [:before_1, :before_2, :within, :after_2, :after_1], @callbacks
|
880
|
+
end
|
881
|
+
|
882
|
+
def test_should_have_access_to_result_after_yield
|
883
|
+
@machine.around_transition {|block| @before_result_1 = @transition.result; block.call; @after_result_1 = @transition.result}
|
884
|
+
@machine.around_transition {|block| @before_result_2 = @transition.result; block.call; @after_result_2 = @transition.result}
|
885
|
+
@transition.run_callbacks {{:result => 1, :success => true}}
|
886
|
+
|
887
|
+
assert_nil @before_result_1
|
888
|
+
assert_nil @before_result_2
|
889
|
+
assert_equal 1, @after_result_1
|
890
|
+
assert_equal 1, @after_result_2
|
891
|
+
end
|
892
|
+
|
893
|
+
def test_should_fail_if_any_before_yield_halted
|
894
|
+
@machine.around_transition {|block| block.call}
|
895
|
+
@machine.around_transition {throw :halt}
|
896
|
+
|
897
|
+
assert_equal false, @transition.run_callbacks
|
898
|
+
end
|
899
|
+
|
900
|
+
def test_should_not_continue_around_callbacks_if_before_yield_halted
|
901
|
+
@callbacks = []
|
902
|
+
@machine.around_transition {@callbacks << 1; throw :halt}
|
903
|
+
@machine.around_transition {|block| @callbacks << 2; block.call; @callbacks << 3}
|
904
|
+
|
905
|
+
assert_equal false, @transition.run_callbacks
|
906
|
+
assert_equal [1], @callbacks
|
907
|
+
end
|
908
|
+
|
909
|
+
def test_should_not_continue_around_callbacks_if_later_before_yield_halted
|
910
|
+
@callbacks = []
|
911
|
+
@machine.around_transition {|block| block.call; @callbacks << 1}
|
912
|
+
@machine.around_transition {throw :halt}
|
913
|
+
|
914
|
+
@transition.run_callbacks
|
915
|
+
assert_equal [], @callbacks
|
916
|
+
end
|
917
|
+
|
918
|
+
def test_should_not_run_further_callbacks_if_after_yield_halted
|
919
|
+
@callbacks = []
|
920
|
+
@machine.around_transition {|block| block.call; @callbacks << 1}
|
921
|
+
@machine.around_transition {|block| block.call; throw :halt}
|
922
|
+
|
923
|
+
assert_equal true, @transition.run_callbacks
|
924
|
+
assert_equal [], @callbacks
|
925
|
+
end
|
926
|
+
|
927
|
+
def test_should_fail_if_any_fail_to_yield
|
928
|
+
@callbacks = []
|
929
|
+
@machine.around_transition {@callbacks << 1}
|
930
|
+
@machine.around_transition {|block| @callbacks << 2; block.call; @callbacks << 3}
|
931
|
+
|
932
|
+
assert_equal false, @transition.run_callbacks
|
933
|
+
assert_equal [1], @callbacks
|
715
934
|
end
|
716
935
|
end
|
717
936
|
|
718
|
-
class
|
937
|
+
class TransitionWithMixedCallbacksTest < Test::Unit::TestCase
|
719
938
|
def setup
|
720
|
-
@klass = Class.new
|
721
|
-
class << self; attr_accessor :cancelled_transaction; end
|
722
|
-
attr_reader :saved
|
723
|
-
|
724
|
-
def save
|
725
|
-
@saved = true
|
726
|
-
end
|
727
|
-
end
|
728
|
-
@before_count = 0
|
729
|
-
@after_count = 0
|
939
|
+
@klass = Class.new
|
730
940
|
|
731
|
-
@machine = StateMachine::Machine.new(@klass
|
941
|
+
@machine = StateMachine::Machine.new(@klass)
|
732
942
|
@machine.state :parked, :idling
|
733
943
|
@machine.event :ignite
|
734
|
-
class << @machine
|
735
|
-
def within_transaction(object)
|
736
|
-
owner_class.cancelled_transaction = yield == false
|
737
|
-
end
|
738
|
-
end
|
739
|
-
|
740
|
-
@machine.before_transition lambda {@before_count += 1; throw :halt}
|
741
|
-
@machine.before_transition lambda {@before_count += 1}
|
742
|
-
@machine.after_transition lambda {@after_count += 1}
|
743
944
|
|
744
945
|
@object = @klass.new
|
745
946
|
@object.state = 'parked'
|
746
947
|
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
747
|
-
@result = @transition.perform
|
748
948
|
end
|
749
949
|
|
750
|
-
def
|
751
|
-
|
950
|
+
def test_should_before_and_around_callbacks_in_order_defined
|
951
|
+
@callbacks = []
|
952
|
+
@machine.before_transition {@callbacks << :before_1}
|
953
|
+
@machine.around_transition {|block| @callbacks << :around; block.call}
|
954
|
+
@machine.before_transition {@callbacks << :before_2}
|
955
|
+
|
956
|
+
assert_equal true, @transition.run_callbacks
|
957
|
+
assert_equal [:before_1, :around, :before_2], @callbacks
|
752
958
|
end
|
753
959
|
|
754
|
-
def
|
755
|
-
|
960
|
+
def test_should_run_around_callbacks_before_after_callbacks
|
961
|
+
@callbacks = []
|
962
|
+
@machine.after_transition {@callbacks << :after_1}
|
963
|
+
@machine.around_transition {|block| block.call; @callbacks << :after_2}
|
964
|
+
@machine.after_transition {@callbacks << :after_3}
|
965
|
+
|
966
|
+
assert_equal true, @transition.run_callbacks
|
967
|
+
assert_equal [:after_2, :after_1, :after_3], @callbacks
|
756
968
|
end
|
757
969
|
|
758
|
-
def
|
759
|
-
|
970
|
+
def test_should_have_access_to_result_for_both_after_and_around_callbacks
|
971
|
+
@machine.after_transition {@after_result = @transition.result}
|
972
|
+
@machine.around_transition {|block| block.call; @around_result = @transition.result}
|
973
|
+
|
974
|
+
@transition.run_callbacks {{:result => 1, :success => true}}
|
975
|
+
assert_equal 1, @after_result
|
976
|
+
assert_equal 1, @around_result
|
760
977
|
end
|
761
978
|
|
762
|
-
def
|
763
|
-
|
979
|
+
def test_should_not_run_further_callbacks_if_before_callback_halts
|
980
|
+
@callbacks = []
|
981
|
+
@machine.before_transition {@callbacks << :before_1}
|
982
|
+
@machine.around_transition {|block| @callbacks << :before_around_1; block.call; @callbacks << :after_around_1}
|
983
|
+
@machine.before_transition {@callbacks << :before_2; throw :halt}
|
984
|
+
@machine.around_transition {|block| @callbacks << :before_around_2; block.call; @callbacks << :after_around_2}
|
985
|
+
@machine.after_transition {@callbacks << :after}
|
986
|
+
|
987
|
+
assert_equal false, @transition.run_callbacks
|
988
|
+
assert_equal [:before_1, :before_around_1, :before_2], @callbacks
|
764
989
|
end
|
765
990
|
|
766
|
-
def
|
767
|
-
|
991
|
+
def test_should_not_run_further_callbacks_if_before_yield_halts
|
992
|
+
@callbacks = []
|
993
|
+
@machine.before_transition {@callbacks << :before_1}
|
994
|
+
@machine.around_transition {|block| @callbacks << :before_around_1; throw :halt}
|
995
|
+
@machine.before_transition {@callbacks << :before_2; throw :halt}
|
996
|
+
@machine.around_transition {|block| @callbacks << :before_around_2; block.call; @callbacks << :after_around_2}
|
997
|
+
@machine.after_transition {@callbacks << :after}
|
998
|
+
|
999
|
+
assert_equal false, @transition.run_callbacks
|
1000
|
+
assert_equal [:before_1, :before_around_1], @callbacks
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
def test_should_not_run_further_callbacks_if_around_callback_fails_to_yield
|
1004
|
+
@callbacks = []
|
1005
|
+
@machine.before_transition {@callbacks << :before_1}
|
1006
|
+
@machine.around_transition {|block| @callbacks << :before_around_1}
|
1007
|
+
@machine.before_transition {@callbacks << :before_2; throw :halt}
|
1008
|
+
@machine.around_transition {|block| @callbacks << :before_around_2; block.call; @callbacks << :after_around_2}
|
1009
|
+
@machine.after_transition {@callbacks << :after}
|
1010
|
+
|
1011
|
+
assert_equal false, @transition.run_callbacks
|
1012
|
+
assert_equal [:before_1, :before_around_1], @callbacks
|
1013
|
+
end
|
1014
|
+
|
1015
|
+
def test_should_not_run_further_callbacks_if_after_yield_halts
|
1016
|
+
@callbacks = []
|
1017
|
+
@machine.before_transition {@callbacks << :before_1}
|
1018
|
+
@machine.around_transition {|block| @callbacks << :before_around_1; block.call; @callbacks << :after_around_1; throw :halt}
|
1019
|
+
@machine.before_transition {@callbacks << :before_2}
|
1020
|
+
@machine.around_transition {|block| @callbacks << :before_around_2; block.call; @callbacks << :after_around_2}
|
1021
|
+
@machine.after_transition {@callbacks << :after}
|
1022
|
+
|
1023
|
+
assert_equal true, @transition.run_callbacks
|
1024
|
+
assert_equal [:before_1, :before_around_1, :before_2, :before_around_2, :after_around_2, :after_around_1], @callbacks
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
def test_should_not_run_further_callbacks_if_after_callback_halts
|
1028
|
+
@callbacks = []
|
1029
|
+
@machine.before_transition {@callbacks << :before_1}
|
1030
|
+
@machine.around_transition {|block| @callbacks << :before_around_1; block.call; @callbacks << :after_around_1}
|
1031
|
+
@machine.before_transition {@callbacks << :before_2}
|
1032
|
+
@machine.around_transition {|block| @callbacks << :before_around_2; block.call; @callbacks << :after_around_2}
|
1033
|
+
@machine.after_transition {@callbacks << :after_1; throw :halt}
|
1034
|
+
@machine.after_transition {@callbacks << :after_2}
|
1035
|
+
|
1036
|
+
assert_equal true, @transition.run_callbacks
|
1037
|
+
assert_equal [:before_1, :before_around_1, :before_2, :before_around_2, :after_around_2, :after_around_1, :after_1], @callbacks
|
768
1038
|
end
|
769
1039
|
|
770
|
-
def
|
771
|
-
|
1040
|
+
def test_should_run_any_callbacks_that_include_failures_if_block_success_is_false
|
1041
|
+
@callbacks = []
|
1042
|
+
@machine.around_transition {|block| block.call; @callbacks << :after_around_1}
|
1043
|
+
@machine.around_transition(:include_failures => true) {|block| block.call; @callbacks << :after_around_2}
|
1044
|
+
@machine.after_transition {@callbacks << :after_1}
|
1045
|
+
@machine.after_transition(:include_failures => true) {@callbacks << :after_2}
|
1046
|
+
|
1047
|
+
assert_equal true, @transition.run_callbacks {{:success => false}}
|
1048
|
+
assert_equal [:after_around_2, :after_2], @callbacks
|
772
1049
|
end
|
773
1050
|
end
|
774
1051
|
|
775
|
-
class
|
1052
|
+
class TransitionWithAfterCallbacksSkippedTest < Test::Unit::TestCase
|
776
1053
|
def setup
|
777
|
-
@klass = Class.new
|
778
|
-
class << self; attr_accessor :cancelled_transaction; end
|
779
|
-
attr_reader :saved
|
780
|
-
|
781
|
-
def save
|
782
|
-
@saved = true
|
783
|
-
end
|
784
|
-
end
|
785
|
-
@before_count = 0
|
786
|
-
@after_count = 0
|
1054
|
+
@klass = Class.new
|
787
1055
|
|
788
|
-
@machine = StateMachine::Machine.new(@klass
|
1056
|
+
@machine = StateMachine::Machine.new(@klass)
|
789
1057
|
@machine.state :parked, :idling
|
790
1058
|
@machine.event :ignite
|
791
|
-
class << @machine
|
792
|
-
def within_transaction(object)
|
793
|
-
owner_class.cancelled_transaction = yield == false
|
794
|
-
end
|
795
|
-
end
|
796
|
-
|
797
|
-
@machine.before_transition lambda {@before_count += 1}
|
798
|
-
@machine.after_transition lambda {@after_count += 1; throw :halt}
|
799
|
-
@machine.after_transition lambda {@after_count += 1}
|
800
1059
|
|
801
1060
|
@object = @klass.new
|
802
1061
|
@object.state = 'parked'
|
803
1062
|
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
804
|
-
@result = @transition.perform
|
805
1063
|
end
|
806
1064
|
|
807
|
-
def
|
808
|
-
|
1065
|
+
def test_should_run_before_callbacks
|
1066
|
+
@machine.before_transition {@run = true}
|
1067
|
+
|
1068
|
+
assert_equal true, @transition.run_callbacks(:after => false)
|
1069
|
+
assert @run
|
809
1070
|
end
|
810
1071
|
|
811
|
-
def
|
812
|
-
|
1072
|
+
def test_should_run_around_callbacks_before_yield
|
1073
|
+
@machine.around_transition {|block| @run = true; block.call}
|
1074
|
+
|
1075
|
+
assert_equal true, @transition.run_callbacks(:after => false)
|
1076
|
+
assert @run
|
813
1077
|
end
|
814
1078
|
|
815
|
-
def
|
816
|
-
|
1079
|
+
def test_should_not_run_after_callbacks
|
1080
|
+
@machine.after_transition {@run = true}
|
1081
|
+
|
1082
|
+
assert_equal true, @transition.run_callbacks(:after => false)
|
1083
|
+
assert !@run
|
817
1084
|
end
|
818
1085
|
|
819
|
-
def
|
820
|
-
|
1086
|
+
def test_should_not_run_around_callbacks_after_yield
|
1087
|
+
@machine.around_transition {|block| block.call; @run = true}
|
1088
|
+
|
1089
|
+
assert_equal true, @transition.run_callbacks(:after => false)
|
1090
|
+
assert !@run
|
1091
|
+
end
|
1092
|
+
|
1093
|
+
def test_should_run_after_callbacks_that_include_failures_if_block_success_is_false
|
1094
|
+
@machine.after_transition(:include_failures => true) {@run = true}
|
1095
|
+
|
1096
|
+
assert_equal true, @transition.run_callbacks(:after => false) {{:success => false}}
|
1097
|
+
assert @run
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
def test_should_run_around_callbacks_that_include_failures_if_block_success_is_false
|
1101
|
+
@machine.around_transition(:include_failures => true) {|block| block.call; @run = true}
|
1102
|
+
|
1103
|
+
assert_equal true, @transition.run_callbacks(:after => false) {{:success => false}}
|
1104
|
+
assert @run
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
def test_should_continue_around_transition_execution_on_second_call
|
1108
|
+
@callbacks = []
|
1109
|
+
@machine.around_transition {|block| @callbacks << :before_around_1; block.call; @callbacks << :after_around_1}
|
1110
|
+
@machine.around_transition {|block| @callbacks << :before_around_2; block.call; @callbacks << :after_around_2}
|
1111
|
+
@machine.after_transition {@callbacks << :after}
|
1112
|
+
|
1113
|
+
assert_equal true, @transition.run_callbacks(:after => false)
|
1114
|
+
assert_equal [:before_around_1, :before_around_2], @callbacks
|
1115
|
+
|
1116
|
+
assert_equal true, @transition.run_callbacks
|
1117
|
+
assert_equal [:before_around_1, :before_around_2, :after_around_2, :after_around_1, :after], @callbacks
|
1118
|
+
end
|
1119
|
+
|
1120
|
+
def test_should_not_run_further_callbacks_if_halted_during_continue_around_transition
|
1121
|
+
@callbacks = []
|
1122
|
+
@machine.around_transition {|block| @callbacks << :before_around_1; block.call; @callbacks << :after_around_1}
|
1123
|
+
@machine.around_transition {|block| @callbacks << :before_around_2; block.call; @callbacks << :after_around_2; throw :halt}
|
1124
|
+
@machine.after_transition {@callbacks << :after}
|
1125
|
+
|
1126
|
+
assert_equal true, @transition.run_callbacks(:after => false)
|
1127
|
+
assert_equal [:before_around_1, :before_around_2], @callbacks
|
1128
|
+
|
1129
|
+
assert_equal true, @transition.run_callbacks
|
1130
|
+
assert_equal [:before_around_1, :before_around_2, :after_around_2], @callbacks
|
1131
|
+
end
|
1132
|
+
|
1133
|
+
def test_should_not_be_able_to_continue_twice
|
1134
|
+
@count = 0
|
1135
|
+
@machine.around_transition {|block| block.call; @count += 1}
|
1136
|
+
@machine.after_transition {@count += 1}
|
1137
|
+
|
1138
|
+
@transition.run_callbacks(:after => false)
|
1139
|
+
|
1140
|
+
2.times do
|
1141
|
+
assert_equal true, @transition.run_callbacks
|
1142
|
+
assert_equal 2, @count
|
1143
|
+
end
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
def test_should_not_be_able_to_continue_again_after_halted
|
1147
|
+
@count = 0
|
1148
|
+
@machine.around_transition {|block| block.call; @count += 1; throw :halt}
|
1149
|
+
@machine.after_transition {@count += 1}
|
1150
|
+
|
1151
|
+
@transition.run_callbacks(:after => false)
|
1152
|
+
|
1153
|
+
2.times do
|
1154
|
+
assert_equal true, @transition.run_callbacks
|
1155
|
+
assert_equal 1, @count
|
1156
|
+
end
|
1157
|
+
end
|
1158
|
+
|
1159
|
+
def test_should_have_access_to_result_after_continued
|
1160
|
+
@machine.around_transition {|block| @around_before_result = @transition.result; block.call; @around_after_result = @transition.result}
|
1161
|
+
@machine.after_transition {@after_result = @transition.result}
|
1162
|
+
|
1163
|
+
@transition.run_callbacks(:after => false)
|
1164
|
+
@transition.run_callbacks {{:result => 1}}
|
1165
|
+
|
1166
|
+
assert_nil @around_before_result
|
1167
|
+
assert_equal 1, @around_after_result
|
1168
|
+
assert_equal 1, @after_result
|
821
1169
|
end
|
822
1170
|
|
823
|
-
def
|
824
|
-
|
1171
|
+
def test_should_raise_exceptions_during_around_callbacks_after_yield_in_second_execution
|
1172
|
+
@machine.around_transition {|block| block.call; raise ArgumentError}
|
1173
|
+
|
1174
|
+
assert_nothing_raised { @transition.run_callbacks(:after => false) }
|
1175
|
+
assert_raise(ArgumentError) { @transition.run_callbacks }
|
825
1176
|
end
|
826
1177
|
end
|
827
1178
|
|
828
|
-
class
|
1179
|
+
class TransitionAfterBeingPerformedTest < Test::Unit::TestCase
|
829
1180
|
def setup
|
830
1181
|
@klass = Class.new do
|
831
|
-
|
832
|
-
attr_reader :saved
|
1182
|
+
attr_reader :saved, :save_state
|
833
1183
|
|
834
1184
|
def save
|
835
|
-
|
1185
|
+
@save_state = state
|
1186
|
+
@saved = true
|
1187
|
+
1
|
836
1188
|
end
|
837
1189
|
end
|
838
|
-
@before_count = 0
|
839
|
-
@after_count = 0
|
840
1190
|
|
841
1191
|
@machine = StateMachine::Machine.new(@klass, :action => :save)
|
842
1192
|
@machine.state :parked, :idling
|
843
1193
|
@machine.event :ignite
|
844
|
-
class << @machine
|
845
|
-
def within_transaction(object)
|
846
|
-
owner_class.cancelled_transaction = yield == false
|
847
|
-
end
|
848
|
-
end
|
849
|
-
|
850
|
-
@machine.before_transition lambda {@before_count += 1}
|
851
|
-
@machine.after_transition lambda {@after_count += 1}
|
852
|
-
@machine.after_transition lambda {@after_count += 1}, :include_failures => true
|
853
1194
|
|
854
1195
|
@object = @klass.new
|
1196
|
+
@object.state = 'parked'
|
855
1197
|
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1198
|
+
@result = @transition.perform
|
856
1199
|
end
|
857
1200
|
|
858
|
-
def
|
859
|
-
assert_equal
|
1201
|
+
def test_should_have_empty_args
|
1202
|
+
assert_equal [], @transition.args
|
860
1203
|
end
|
861
1204
|
|
862
|
-
def
|
863
|
-
@transition.
|
864
|
-
assert_nil @object.state
|
1205
|
+
def test_should_have_a_result
|
1206
|
+
assert_equal 1, @transition.result
|
865
1207
|
end
|
866
1208
|
|
867
|
-
def
|
868
|
-
@
|
869
|
-
assert_equal 1, @before_count
|
1209
|
+
def test_should_be_successful
|
1210
|
+
assert_equal true, @result
|
870
1211
|
end
|
871
1212
|
|
872
|
-
def
|
873
|
-
@
|
874
|
-
assert_equal 1, @after_count
|
1213
|
+
def test_should_change_the_current_state
|
1214
|
+
assert_equal 'idling', @object.state
|
875
1215
|
end
|
876
1216
|
|
877
|
-
def
|
878
|
-
@
|
879
|
-
assert @klass.cancelled_transaction
|
1217
|
+
def test_should_run_the_action
|
1218
|
+
assert @object.saved
|
880
1219
|
end
|
881
1220
|
|
882
|
-
def
|
883
|
-
@
|
884
|
-
def save
|
885
|
-
nil
|
886
|
-
end
|
887
|
-
end
|
888
|
-
|
889
|
-
assert_equal false, @transition.perform
|
1221
|
+
def test_should_run_the_action_after_saving_the_state
|
1222
|
+
assert_equal 'idling', @object.save_state
|
890
1223
|
end
|
891
1224
|
end
|
892
1225
|
|
893
|
-
class
|
1226
|
+
class TransitionWithPerformArgumentsTest < Test::Unit::TestCase
|
894
1227
|
def setup
|
895
1228
|
@klass = Class.new do
|
1229
|
+
attr_reader :saved
|
1230
|
+
|
896
1231
|
def save
|
897
|
-
|
1232
|
+
@saved = true
|
898
1233
|
end
|
899
1234
|
end
|
900
1235
|
|
@@ -905,308 +1240,125 @@ class TransitionWithActionErrorTest < Test::Unit::TestCase
|
|
905
1240
|
@object = @klass.new
|
906
1241
|
@object.state = 'parked'
|
907
1242
|
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
908
|
-
|
909
|
-
@raised = true
|
910
|
-
begin
|
911
|
-
@transition.perform
|
912
|
-
@raised = false
|
913
|
-
rescue ArgumentError
|
914
|
-
end
|
915
1243
|
end
|
916
1244
|
|
917
|
-
def
|
918
|
-
|
1245
|
+
def test_should_have_arguments
|
1246
|
+
@transition.perform(1, 2)
|
1247
|
+
|
1248
|
+
assert_equal [1, 2], @transition.args
|
1249
|
+
assert @object.saved
|
919
1250
|
end
|
920
1251
|
|
921
|
-
def
|
922
|
-
|
1252
|
+
def test_should_not_include_run_action_in_arguments
|
1253
|
+
@transition.perform(1, 2, false)
|
1254
|
+
|
1255
|
+
assert_equal [1, 2], @transition.args
|
1256
|
+
assert !@object.saved
|
923
1257
|
end
|
924
1258
|
end
|
925
1259
|
|
926
|
-
class
|
1260
|
+
class TransitionWithoutRunningActionTest < Test::Unit::TestCase
|
927
1261
|
def setup
|
928
1262
|
@klass = Class.new do
|
929
|
-
attr_reader :
|
930
|
-
|
931
|
-
def initialize
|
932
|
-
@persisted = []
|
933
|
-
@state = 'parked'
|
934
|
-
@status = 'first_gear'
|
935
|
-
super
|
936
|
-
end
|
937
|
-
|
938
|
-
def state=(value)
|
939
|
-
@persisted << value
|
940
|
-
@state = value
|
941
|
-
end
|
1263
|
+
attr_reader :saved
|
942
1264
|
|
943
|
-
def
|
944
|
-
@
|
945
|
-
@status = value
|
1265
|
+
def save
|
1266
|
+
@saved = true
|
946
1267
|
end
|
947
1268
|
end
|
948
1269
|
|
949
|
-
@
|
950
|
-
@state
|
951
|
-
@
|
952
|
-
|
953
|
-
@status = StateMachine::Machine.new(@klass, :status)
|
954
|
-
@status.event :shift_up
|
955
|
-
@status.state :first_gear, :second_gear
|
956
|
-
|
957
|
-
@object = @klass.new
|
958
|
-
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling)
|
959
|
-
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
960
|
-
|
961
|
-
@result = StateMachine::Transition.perform([@state_transition, @status_transition])
|
962
|
-
end
|
963
|
-
|
964
|
-
def test_should_raise_exception_if_attempted_on_the_same_state_machine
|
965
|
-
exception = assert_raise(ArgumentError) { StateMachine::Transition.perform([@state_transition, @state_transition]) }
|
966
|
-
assert_equal 'Cannot perform multiple transitions in parallel for the same state machine attribute', exception.message
|
967
|
-
end
|
968
|
-
|
969
|
-
def test_should_perform
|
970
|
-
assert_equal true, @result
|
971
|
-
end
|
972
|
-
|
973
|
-
def test_should_persist_first_state
|
974
|
-
assert_equal 'idling', @object.state
|
975
|
-
end
|
976
|
-
|
977
|
-
def test_should_persist_second_state
|
978
|
-
assert_equal 'second_gear', @object.status
|
979
|
-
end
|
980
|
-
|
981
|
-
def test_should_persist_in_order
|
982
|
-
assert_equal ['idling', 'second_gear'], @object.persisted
|
983
|
-
end
|
984
|
-
|
985
|
-
def test_should_have_args_in_transitions
|
986
|
-
assert_equal [], @state_transition.args
|
987
|
-
assert_equal [], @status_transition.args
|
988
|
-
end
|
989
|
-
end
|
990
|
-
|
991
|
-
class TransitionsInParallelWithCallbacksTest < Test::Unit::TestCase
|
992
|
-
def setup
|
993
|
-
@klass = Class.new
|
994
|
-
|
995
|
-
@before_callbacks = []
|
996
|
-
@after_callbacks = []
|
997
|
-
|
998
|
-
@state = StateMachine::Machine.new(@klass, :state, :initial => :parked)
|
999
|
-
@state.event :ignite
|
1000
|
-
@state.state :parked, :idling
|
1001
|
-
@state.before_transition lambda {@before_callbacks << :state}
|
1002
|
-
@state.after_transition lambda {@after_callbacks << :state}
|
1003
|
-
|
1004
|
-
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
|
1005
|
-
@status.event :shift_up
|
1006
|
-
@status.state :first_gear, :second_gear
|
1007
|
-
@status.before_transition lambda {@before_callbacks << :status}
|
1008
|
-
@status.after_transition lambda {@after_callbacks << :status}
|
1270
|
+
@machine = StateMachine::Machine.new(@klass, :action => :save)
|
1271
|
+
@machine.state :parked, :idling
|
1272
|
+
@machine.event :ignite
|
1273
|
+
@machine.after_transition {|object| @run_after = true}
|
1009
1274
|
|
1010
1275
|
@object = @klass.new
|
1011
|
-
@
|
1012
|
-
@
|
1013
|
-
|
1014
|
-
|
1015
|
-
def test_should_run_before_callbacks_in_order
|
1016
|
-
perform
|
1017
|
-
assert_equal [:state, :status], @before_callbacks
|
1018
|
-
end
|
1019
|
-
|
1020
|
-
def test_should_run_after_callbacks_in_order
|
1021
|
-
perform
|
1022
|
-
assert_equal [:state, :status], @after_callbacks
|
1276
|
+
@object.state = 'parked'
|
1277
|
+
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1278
|
+
@result = @transition.perform(false)
|
1023
1279
|
end
|
1024
1280
|
|
1025
|
-
def
|
1026
|
-
|
1027
|
-
assert_equal [], @after_callbacks
|
1281
|
+
def test_should_have_empty_args
|
1282
|
+
assert_equal [], @transition.args
|
1028
1283
|
end
|
1029
1284
|
|
1030
|
-
def
|
1031
|
-
@
|
1032
|
-
|
1033
|
-
assert_equal false, perform
|
1034
|
-
assert_equal [:state], @before_callbacks
|
1035
|
-
assert_equal 'parked', @object.state
|
1036
|
-
assert_equal 'first_gear', @object.status
|
1037
|
-
assert_equal [], @after_callbacks
|
1285
|
+
def test_should_not_have_a_result
|
1286
|
+
assert_nil @transition.result
|
1038
1287
|
end
|
1039
1288
|
|
1040
|
-
def
|
1041
|
-
|
1042
|
-
|
1043
|
-
assert_equal false, perform
|
1044
|
-
assert_equal [:state, :status], @before_callbacks
|
1045
|
-
assert_equal 'parked', @object.state
|
1046
|
-
assert_equal 'first_gear', @object.status
|
1047
|
-
assert_equal [], @after_callbacks
|
1289
|
+
def test_should_be_successful
|
1290
|
+
assert_equal true, @result
|
1048
1291
|
end
|
1049
1292
|
|
1050
|
-
def
|
1051
|
-
@state.after_transition lambda {throw :halt}
|
1052
|
-
@state.after_transition lambda {@after_callbacks << :invalid}
|
1053
|
-
|
1054
|
-
assert_equal true, perform
|
1055
|
-
assert_equal [:state, :status], @before_callbacks
|
1293
|
+
def test_should_change_the_current_state
|
1056
1294
|
assert_equal 'idling', @object.state
|
1057
|
-
assert_equal 'second_gear', @object.status
|
1058
|
-
assert_equal [:state, :status], @after_callbacks
|
1059
1295
|
end
|
1060
1296
|
|
1061
|
-
def
|
1062
|
-
|
1063
|
-
@status.after_transition lambda {@after_callbacks << :invalid}
|
1064
|
-
|
1065
|
-
assert_equal true, perform
|
1066
|
-
assert_equal [:state, :status], @before_callbacks
|
1067
|
-
assert_equal 'idling', @object.state
|
1068
|
-
assert_equal 'second_gear', @object.status
|
1069
|
-
assert_equal [:state, :status], @after_callbacks
|
1297
|
+
def test_should_not_run_the_action
|
1298
|
+
assert !@object.saved
|
1070
1299
|
end
|
1071
1300
|
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
end
|
1301
|
+
def test_should_run_after_callbacks
|
1302
|
+
assert @run_after
|
1303
|
+
end
|
1076
1304
|
end
|
1077
1305
|
|
1078
|
-
class
|
1306
|
+
class TransitionWithTransactionsTest < Test::Unit::TestCase
|
1079
1307
|
def setup
|
1080
1308
|
@klass = Class.new do
|
1081
|
-
|
1082
|
-
|
1083
|
-
def save_state
|
1084
|
-
(@actions ||= []) << :save_state
|
1085
|
-
:save_state
|
1309
|
+
class << self
|
1310
|
+
attr_accessor :running_transaction
|
1086
1311
|
end
|
1087
1312
|
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1313
|
+
attr_accessor :result
|
1314
|
+
|
1315
|
+
def save
|
1316
|
+
@result = self.class.running_transaction
|
1317
|
+
true
|
1091
1318
|
end
|
1092
1319
|
end
|
1093
1320
|
|
1094
|
-
@
|
1095
|
-
@state
|
1096
|
-
@
|
1097
|
-
|
1098
|
-
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save_status)
|
1099
|
-
@status.event :shift_up
|
1100
|
-
@status.state :first_gear, :second_gear
|
1321
|
+
@machine = StateMachine::Machine.new(@klass, :action => :save)
|
1322
|
+
@machine.state :parked, :idling
|
1323
|
+
@machine.event :ignite
|
1101
1324
|
|
1102
1325
|
@object = @klass.new
|
1103
|
-
@
|
1104
|
-
@
|
1105
|
-
end
|
1106
|
-
|
1107
|
-
def test_should_run_actions_in_order
|
1108
|
-
perform
|
1109
|
-
assert_equal [:save_state, :save_status], @object.actions
|
1110
|
-
end
|
1111
|
-
|
1112
|
-
def test_should_store_action_specific_results
|
1113
|
-
perform
|
1114
|
-
assert_equal :save_state, @state_transition.result
|
1115
|
-
assert_equal :save_status, @status_transition.result
|
1116
|
-
end
|
1117
|
-
|
1118
|
-
def test_should_not_perform_if_action_fails_for_first_transition
|
1119
|
-
@klass.class_eval do
|
1120
|
-
def save_state
|
1121
|
-
false
|
1122
|
-
end
|
1123
|
-
end
|
1124
|
-
|
1125
|
-
assert_equal false, perform
|
1126
|
-
assert_equal 'parked', @object.state
|
1127
|
-
assert_equal 'first_gear', @object.status
|
1128
|
-
end
|
1129
|
-
|
1130
|
-
def test_should_not_perform_if_action_fails_for_second_transition
|
1131
|
-
@klass.class_eval do
|
1132
|
-
def save_status
|
1133
|
-
false
|
1134
|
-
end
|
1135
|
-
end
|
1326
|
+
@object.state = 'parked'
|
1327
|
+
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1136
1328
|
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
def test_should_rollback_if_action_errors_for_first_transition
|
1143
|
-
@klass.class_eval do
|
1144
|
-
def save_state
|
1145
|
-
raise ArgumentError
|
1329
|
+
class << @machine
|
1330
|
+
def within_transaction(object)
|
1331
|
+
owner_class.running_transaction = object
|
1332
|
+
yield
|
1333
|
+
owner_class.running_transaction = false
|
1146
1334
|
end
|
1147
1335
|
end
|
1148
|
-
|
1149
|
-
begin; perform; rescue; end
|
1150
|
-
assert_equal 'parked', @object.state
|
1151
|
-
assert_equal 'first_gear', @object.status
|
1152
1336
|
end
|
1153
1337
|
|
1154
|
-
def
|
1155
|
-
@
|
1156
|
-
|
1157
|
-
raise ArgumentError
|
1158
|
-
end
|
1338
|
+
def test_should_run_blocks_within_transaction_for_object
|
1339
|
+
@transition.within_transaction do
|
1340
|
+
@result = @klass.running_transaction
|
1159
1341
|
end
|
1160
1342
|
|
1161
|
-
|
1162
|
-
assert_equal 'parked', @object.state
|
1163
|
-
assert_equal 'first_gear', @object.status
|
1343
|
+
assert_equal @object, @result
|
1164
1344
|
end
|
1165
|
-
|
1166
|
-
private
|
1167
|
-
def perform(options = {})
|
1168
|
-
StateMachine::Transition.perform([@state_transition, @status_transition], options)
|
1169
|
-
end
|
1170
1345
|
end
|
1171
1346
|
|
1172
|
-
class
|
1347
|
+
class TransitionTransientTest < Test::Unit::TestCase
|
1173
1348
|
def setup
|
1174
1349
|
@klass = Class.new
|
1175
1350
|
|
1176
|
-
@
|
1177
|
-
@state
|
1178
|
-
@
|
1179
|
-
|
1180
|
-
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
|
1181
|
-
@status.event :shift_up
|
1182
|
-
@status.state :first_gear, :second_gear
|
1351
|
+
@machine = StateMachine::Machine.new(@klass)
|
1352
|
+
@machine.state :parked, :idling
|
1353
|
+
@machine.event :ignite
|
1183
1354
|
|
1184
1355
|
@object = @klass.new
|
1185
|
-
@
|
1186
|
-
@
|
1187
|
-
|
1188
|
-
|
1189
|
-
def test_should_be_perform_if_result_is_not_false
|
1190
|
-
assert_equal true, StateMachine::Transition.perform([@state_transition, @status_transition]) { true }
|
1191
|
-
assert_equal 'idling', @object.state
|
1192
|
-
assert_equal 'second_gear', @object.status
|
1193
|
-
end
|
1194
|
-
|
1195
|
-
def test_should_not_perform_if_result_is_false
|
1196
|
-
assert_equal false, StateMachine::Transition.perform([@state_transition, @status_transition]) { false }
|
1197
|
-
assert_equal 'parked', @object.state
|
1198
|
-
assert_equal 'first_gear', @object.status
|
1199
|
-
end
|
1200
|
-
|
1201
|
-
def test_should_not_perform_if_result_is_nil
|
1202
|
-
assert_equal false, StateMachine::Transition.perform([@state_transition, @status_transition]) { nil }
|
1203
|
-
assert_equal 'parked', @object.state
|
1204
|
-
assert_equal 'first_gear', @object.status
|
1356
|
+
@object.state = 'parked'
|
1357
|
+
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1358
|
+
@transition.transient = true
|
1205
1359
|
end
|
1206
1360
|
|
1207
|
-
def
|
1208
|
-
|
1209
|
-
assert_equal 1, @state_transition.result
|
1210
|
-
assert_equal 1, @status_transition.result
|
1361
|
+
def test_should_be_transient
|
1362
|
+
assert @transition.transient?
|
1211
1363
|
end
|
1212
1364
|
end
|