state_machine 0.6.3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/CHANGELOG.rdoc +31 -1
  2. data/README.rdoc +33 -21
  3. data/Rakefile +2 -2
  4. data/examples/merb-rest/controller.rb +51 -0
  5. data/examples/merb-rest/model.rb +28 -0
  6. data/examples/merb-rest/view_edit.html.erb +24 -0
  7. data/examples/merb-rest/view_index.html.erb +23 -0
  8. data/examples/merb-rest/view_new.html.erb +13 -0
  9. data/examples/merb-rest/view_show.html.erb +17 -0
  10. data/examples/rails-rest/controller.rb +43 -0
  11. data/examples/rails-rest/migration.rb +11 -0
  12. data/examples/rails-rest/model.rb +23 -0
  13. data/examples/rails-rest/view_edit.html.erb +25 -0
  14. data/examples/rails-rest/view_index.html.erb +23 -0
  15. data/examples/rails-rest/view_new.html.erb +14 -0
  16. data/examples/rails-rest/view_show.html.erb +17 -0
  17. data/lib/state_machine/assertions.rb +2 -2
  18. data/lib/state_machine/callback.rb +14 -8
  19. data/lib/state_machine/condition_proxy.rb +3 -3
  20. data/lib/state_machine/event.rb +19 -21
  21. data/lib/state_machine/event_collection.rb +114 -0
  22. data/lib/state_machine/extensions.rb +127 -11
  23. data/lib/state_machine/guard.rb +1 -1
  24. data/lib/state_machine/integrations/active_record/locale.rb +2 -1
  25. data/lib/state_machine/integrations/active_record.rb +117 -39
  26. data/lib/state_machine/integrations/data_mapper/observer.rb +20 -64
  27. data/lib/state_machine/integrations/data_mapper.rb +71 -26
  28. data/lib/state_machine/integrations/sequel.rb +69 -21
  29. data/lib/state_machine/machine.rb +267 -139
  30. data/lib/state_machine/machine_collection.rb +145 -0
  31. data/lib/state_machine/matcher.rb +2 -2
  32. data/lib/state_machine/node_collection.rb +9 -4
  33. data/lib/state_machine/state.rb +22 -32
  34. data/lib/state_machine/state_collection.rb +66 -17
  35. data/lib/state_machine/transition.rb +259 -28
  36. data/lib/state_machine.rb +121 -56
  37. data/tasks/state_machine.rake +1 -0
  38. data/tasks/state_machine.rb +26 -0
  39. data/test/active_record.log +116877 -0
  40. data/test/functional/state_machine_test.rb +118 -12
  41. data/test/sequel.log +28542 -0
  42. data/test/unit/callback_test.rb +46 -1
  43. data/test/unit/condition_proxy_test.rb +55 -28
  44. data/test/unit/event_collection_test.rb +228 -0
  45. data/test/unit/event_test.rb +51 -46
  46. data/test/unit/integrations/active_record_test.rb +128 -70
  47. data/test/unit/integrations/data_mapper_test.rb +150 -58
  48. data/test/unit/integrations/sequel_test.rb +63 -6
  49. data/test/unit/invalid_event_test.rb +7 -0
  50. data/test/unit/machine_collection_test.rb +678 -0
  51. data/test/unit/machine_test.rb +198 -91
  52. data/test/unit/node_collection_test.rb +33 -30
  53. data/test/unit/state_collection_test.rb +112 -5
  54. data/test/unit/state_test.rb +23 -3
  55. data/test/unit/transition_test.rb +750 -89
  56. metadata +28 -3
@@ -17,6 +17,10 @@ class EventByDefaultTest < Test::Unit::TestCase
17
17
  assert_equal :ignite, @event.name
18
18
  end
19
19
 
20
+ def test_should_have_a_qualified_name
21
+ assert_equal :ignite, @event.qualified_name
22
+ end
23
+
20
24
  def test_should_not_have_any_guards
21
25
  assert @event.guards.empty?
22
26
  end
@@ -29,8 +33,8 @@ class EventByDefaultTest < Test::Unit::TestCase
29
33
  assert !@event.can_fire?(@object)
30
34
  end
31
35
 
32
- def test_should_not_have_a_next_transition
33
- assert_nil @event.next_transition(@object)
36
+ def test_should_not_have_a_transition
37
+ assert_nil @event.transition_for(@object)
34
38
  end
35
39
 
36
40
  def test_should_define_a_predicate
@@ -38,7 +42,7 @@ class EventByDefaultTest < Test::Unit::TestCase
38
42
  end
39
43
 
40
44
  def test_should_define_a_transition_accessor
41
- assert @object.respond_to?(:next_ignite_transition)
45
+ assert @object.respond_to?(:ignite_transition)
42
46
  end
43
47
 
44
48
  def test_should_define_an_action
@@ -85,7 +89,7 @@ class EventWithConflictingHelpersTest < Test::Unit::TestCase
85
89
  0
86
90
  end
87
91
 
88
- def next_ignite_transition
92
+ def ignite_transition
89
93
  0
90
94
  end
91
95
 
@@ -107,7 +111,7 @@ class EventWithConflictingHelpersTest < Test::Unit::TestCase
107
111
  end
108
112
 
109
113
  def test_should_not_redefine_transition_accessor
110
- assert_equal 0, @object.next_ignite_transition
114
+ assert_equal 0, @object.ignite_transition
111
115
  end
112
116
 
113
117
  def test_should_not_redefine_action
@@ -124,7 +128,7 @@ class EventWithConflictingHelpersTest < Test::Unit::TestCase
124
128
  super ? 1 : 0
125
129
  end
126
130
 
127
- def next_ignite_transition
131
+ def ignite_transition
128
132
  super ? 1 : 0
129
133
  end
130
134
 
@@ -143,34 +147,42 @@ class EventWithConflictingHelpersTest < Test::Unit::TestCase
143
147
  end
144
148
 
145
149
  assert_equal 0, @object.can_ignite?
146
- assert_equal 0, @object.next_ignite_transition
150
+ assert_equal 0, @object.ignite_transition
147
151
  assert_equal 0, @object.ignite
148
- assert_equal 0, @object.ignite!
152
+ assert_equal 1, @object.ignite!
149
153
  end
150
154
  end
151
155
 
152
156
  class EventWithNamespaceTest < Test::Unit::TestCase
153
157
  def setup
154
158
  @klass = Class.new
155
- @machine = StateMachine::Machine.new(@klass, :namespace => 'car')
156
- @event = StateMachine::Event.new(@machine, :ignite)
159
+ @machine = StateMachine::Machine.new(@klass, :namespace => 'alarm')
160
+ @event = StateMachine::Event.new(@machine, :enable)
157
161
  @object = @klass.new
158
162
  end
159
163
 
164
+ def test_should_have_a_name
165
+ assert_equal :enable, @event.name
166
+ end
167
+
168
+ def test_should_have_a_qualified_name
169
+ assert_equal :enable_alarm, @event.qualified_name
170
+ end
171
+
160
172
  def test_should_namespace_predicate
161
- assert @object.respond_to?(:can_ignite_car?)
173
+ assert @object.respond_to?(:can_enable_alarm?)
162
174
  end
163
175
 
164
176
  def test_should_namespace_transition_accessor
165
- assert @object.respond_to?(:next_ignite_car_transition)
177
+ assert @object.respond_to?(:enable_alarm_transition)
166
178
  end
167
179
 
168
180
  def test_should_namespace_action
169
- assert @object.respond_to?(:ignite_car)
181
+ assert @object.respond_to?(:enable_alarm)
170
182
  end
171
183
 
172
184
  def test_should_namespace_bang_action
173
- assert @object.respond_to?(:ignite_car!)
185
+ assert @object.respond_to?(:enable_alarm!)
174
186
  end
175
187
  end
176
188
 
@@ -253,19 +265,14 @@ class EventWithoutTransitionsTest < Test::Unit::TestCase
253
265
  assert !@event.can_fire?(@object)
254
266
  end
255
267
 
256
- def test_should_not_have_a_next_transition
257
- assert_nil @event.next_transition(@object)
268
+ def test_should_not_have_a_transition
269
+ assert_nil @event.transition_for(@object)
258
270
  end
259
271
 
260
272
  def test_should_not_fire
261
273
  assert !@event.fire(@object)
262
274
  end
263
275
 
264
- def test_should_raise_exception_on_fire!
265
- exception = assert_raise(StateMachine::InvalidTransition) { @event.fire!(@object) }
266
- assert_equal 'Cannot transition state via :ignite from nil', exception.message
267
- end
268
-
269
276
  def test_should_not_change_the_current_state
270
277
  @event.fire(@object)
271
278
  assert_nil @object.state
@@ -314,19 +321,14 @@ class EventWithoutMatchingTransitionsTest < Test::Unit::TestCase
314
321
  assert !@event.can_fire?(@object)
315
322
  end
316
323
 
317
- def test_should_not_have_a_next_transition
318
- assert_nil @event.next_transition(@object)
324
+ def test_should_not_have_a_transition
325
+ assert_nil @event.transition_for(@object)
319
326
  end
320
327
 
321
328
  def test_should_not_fire
322
329
  assert !@event.fire(@object)
323
330
  end
324
331
 
325
- def test_should_raise_exception_on_fire!
326
- exception = assert_raise(StateMachine::InvalidTransition) { @event.fire!(@object) }
327
- assert_equal 'Cannot transition state via :ignite from :idling', exception.message
328
- end
329
-
330
332
  def test_should_not_change_the_current_state
331
333
  @event.fire(@object)
332
334
  assert_equal 'idling', @object.state
@@ -336,8 +338,8 @@ end
336
338
  class EventWithMatchingDisabledTransitionsTest < Test::Unit::TestCase
337
339
  def setup
338
340
  StateMachine::Integrations.const_set('Custom', Module.new do
339
- def invalidate(object, event)
340
- (object.errors ||= []) << invalid_message(object, event)
341
+ def invalidate(object, attribute, message, values = [])
342
+ (object.errors ||= []) << generate_message(message, values)
341
343
  end
342
344
 
343
345
  def reset(object)
@@ -363,8 +365,8 @@ class EventWithMatchingDisabledTransitionsTest < Test::Unit::TestCase
363
365
  assert !@event.can_fire?(@object)
364
366
  end
365
367
 
366
- def test_should_not_have_a_next_transition
367
- assert_nil @event.next_transition(@object)
368
+ def test_should_not_have_a_transition
369
+ assert_nil @event.transition_for(@object)
368
370
  end
369
371
 
370
372
  def test_should_not_fire
@@ -378,14 +380,14 @@ class EventWithMatchingDisabledTransitionsTest < Test::Unit::TestCase
378
380
 
379
381
  def test_should_invalidate_the_state
380
382
  @event.fire(@object)
381
- assert_equal ['cannot be transitioned via :ignite from :parked'], @object.errors
383
+ assert_equal ['cannot transition via "ignite"'], @object.errors
382
384
  end
383
385
 
384
386
  def test_should_reset_existing_error
385
387
  @object.errors = ['invalid']
386
388
 
387
389
  @event.fire(@object)
388
- assert_equal ['cannot be transitioned via :ignite from :parked'], @object.errors
390
+ assert_equal ['cannot transition via "ignite"'], @object.errors
389
391
  end
390
392
 
391
393
  def teardown
@@ -396,8 +398,8 @@ end
396
398
  class EventWithMatchingEnabledTransitionsTest < Test::Unit::TestCase
397
399
  def setup
398
400
  StateMachine::Integrations.const_set('Custom', Module.new do
399
- def invalidate(object, event)
400
- (object.errors ||= []) << invalid_message(object, event)
401
+ def invalidate(object, attribute, message, values = [])
402
+ (object.errors ||= []) << generate_message(message, values)
401
403
  end
402
404
 
403
405
  def reset(object)
@@ -411,6 +413,7 @@ class EventWithMatchingEnabledTransitionsTest < Test::Unit::TestCase
411
413
 
412
414
  @machine = StateMachine::Machine.new(@klass, :integration => :custom)
413
415
  @machine.state :parked, :idling
416
+ @machine.event :ignite
414
417
 
415
418
  @event = StateMachine::Event.new(@machine, :ignite)
416
419
  @event.transition(:parked => :idling)
@@ -423,8 +426,8 @@ class EventWithMatchingEnabledTransitionsTest < Test::Unit::TestCase
423
426
  assert @event.can_fire?(@object)
424
427
  end
425
428
 
426
- def test_should_have_a_next_transition
427
- transition = @event.next_transition(@object)
429
+ def test_should_have_a_transition
430
+ transition = @event.transition_for(@object)
428
431
  assert_not_nil transition
429
432
  assert_equal 'parked', transition.from
430
433
  assert_equal 'idling', transition.to
@@ -462,6 +465,7 @@ class EventWithTransitionWithoutToStateTest < Test::Unit::TestCase
462
465
  @klass = Class.new
463
466
  @machine = StateMachine::Machine.new(@klass)
464
467
  @machine.state :parked
468
+ @machine.event :park
465
469
 
466
470
  @event = StateMachine::Event.new(@machine, :park)
467
471
  @event.transition(:from => :parked)
@@ -474,8 +478,8 @@ class EventWithTransitionWithoutToStateTest < Test::Unit::TestCase
474
478
  assert @event.can_fire?(@object)
475
479
  end
476
480
 
477
- def test_should_have_a_next_transition
478
- transition = @event.next_transition(@object)
481
+ def test_should_have_a_transition
482
+ transition = @event.transition_for(@object)
479
483
  assert_not_nil transition
480
484
  assert_equal 'parked', transition.from
481
485
  assert_equal 'parked', transition.to
@@ -496,8 +500,8 @@ class EventWithTransitionWithNilToStateTest < Test::Unit::TestCase
496
500
  def setup
497
501
  @klass = Class.new
498
502
  @machine = StateMachine::Machine.new(@klass)
499
- @machine.state nil
500
- @machine.state :idling
503
+ @machine.state nil, :idling
504
+ @machine.event :park
501
505
 
502
506
  @event = StateMachine::Event.new(@machine, :park)
503
507
  @event.transition(:idling => nil)
@@ -510,8 +514,8 @@ class EventWithTransitionWithNilToStateTest < Test::Unit::TestCase
510
514
  assert @event.can_fire?(@object)
511
515
  end
512
516
 
513
- def test_should_have_a_next_transition
514
- transition = @event.next_transition(@object)
517
+ def test_should_have_a_transition
518
+ transition = @event.transition_for(@object)
515
519
  assert_not_nil transition
516
520
  assert_equal 'idling', transition.from
517
521
  assert_equal nil, transition.to
@@ -533,6 +537,7 @@ class EventWithMultipleTransitionsTest < Test::Unit::TestCase
533
537
  @klass = Class.new
534
538
  @machine = StateMachine::Machine.new(@klass)
535
539
  @machine.state :parked, :idling
540
+ @machine.event :ignite
536
541
 
537
542
  @event = StateMachine::Event.new(@machine, :ignite)
538
543
  @event.transition(:idling => :idling)
@@ -546,8 +551,8 @@ class EventWithMultipleTransitionsTest < Test::Unit::TestCase
546
551
  assert @event.can_fire?(@object)
547
552
  end
548
553
 
549
- def test_should_have_a_next_transition
550
- transition = @event.next_transition(@object)
554
+ def test_should_have_a_transition
555
+ transition = @event.transition_for(@object)
551
556
  assert_not_nil transition
552
557
  assert_equal 'parked', transition.from
553
558
  assert_equal 'idling', transition.to
@@ -14,13 +14,6 @@ begin
14
14
  require 'active_record/fixtures'
15
15
  require 'active_record/test_case'
16
16
 
17
- # Set default fixtures configuration
18
- ActiveSupport::TestCase.class_eval do
19
- self.fixture_path = File.dirname(__FILE__) + '/../../fixtures/'
20
- self.use_instantiated_fixtures = false
21
- self.use_transactional_fixtures = true
22
- end
23
-
24
17
  # Establish database connection
25
18
  ActiveRecord::Base.establish_connection({'adapter' => 'sqlite3', 'database' => ':memory:'})
26
19
  ActiveRecord::Base.logger = Logger.new("#{File.dirname(__FILE__)}/../../active_record.log")
@@ -76,6 +69,10 @@ begin
76
69
  assert_equal :save, @machine.action
77
70
  end
78
71
 
72
+ def test_should_use_transactions
73
+ assert_equal true, @machine.use_transactions
74
+ end
75
+
79
76
  def test_should_create_notifier_before_callback
80
77
  assert_equal 1, @machine.callbacks[:before].size
81
78
  end
@@ -168,10 +165,10 @@ begin
168
165
  record = @model.new
169
166
  record.state = 'parked'
170
167
 
171
- @machine.invalidate(record, StateMachine::Event.new(@machine, :park))
168
+ @machine.invalidate(record, :state, :invalid_transition, [[:event, :park]])
172
169
 
173
170
  assert record.errors.invalid?(:state)
174
- assert_equal 'cannot be transitioned via :park from :parked', record.errors.on(:state)
171
+ assert_equal 'cannot transition via "park"', record.errors.on(:state)
175
172
  end
176
173
 
177
174
  def test_should_clear_errors_on_reset
@@ -236,6 +233,23 @@ begin
236
233
  end
237
234
  end
238
235
 
236
+ class MachineWithConflictingPredicateTest < ActiveRecord::TestCase
237
+ def setup
238
+ @model = new_model do
239
+ def state?(*args)
240
+ true
241
+ end
242
+ end
243
+
244
+ @machine = StateMachine::Machine.new(@model)
245
+ @record = @model.new
246
+ end
247
+
248
+ def test_should_not_define_attribute_predicate
249
+ assert @record.state?
250
+ end
251
+ end
252
+
239
253
  class MachineWithColumnStateAttributeTest < ActiveRecord::TestCase
240
254
  def setup
241
255
  @model = new_model
@@ -265,7 +279,7 @@ begin
265
279
  end
266
280
 
267
281
  def test_should_raise_exception_for_predicate_if_invalid_state_specified
268
- assert_raise(ArgumentError) { @record.state?(:invalid) }
282
+ assert_raise(IndexError) { @record.state?(:invalid) }
269
283
  end
270
284
  end
271
285
 
@@ -322,7 +336,7 @@ begin
322
336
  end
323
337
 
324
338
  def test_should_raise_exception_for_predicate_if_invalid_state_specified
325
- assert_raise(ArgumentError) { @record.status?(:invalid) }
339
+ assert_raise(IndexError) { @record.status?(:invalid) }
326
340
  end
327
341
 
328
342
  def test_should_set_initial_state_on_created_object
@@ -350,6 +364,7 @@ begin
350
364
  @model = new_model
351
365
  @machine = StateMachine::Machine.new(@model, :initial => :parked)
352
366
  @machine.other_states :idling
367
+ @machine.event :ignite
353
368
 
354
369
  @record = @model.new(:state => 'parked')
355
370
  @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
@@ -363,7 +378,7 @@ begin
363
378
  assert called
364
379
  end
365
380
 
366
- def test_should_pass_record_into_before_callbacks_with_one_argument
381
+ def test_should_pass_record_to_before_callbacks_with_one_argument
367
382
  record = nil
368
383
  @machine.before_transition(lambda {|arg| record = arg})
369
384
 
@@ -371,7 +386,7 @@ begin
371
386
  assert_equal @record, record
372
387
  end
373
388
 
374
- def test_should_pass_record_and_transition_into_before_callbacks_with_multiple_arguments
389
+ def test_should_pass_record_and_transition_to_before_callbacks_with_multiple_arguments
375
390
  callback_args = nil
376
391
  @machine.before_transition(lambda {|*args| callback_args = args})
377
392
 
@@ -395,7 +410,7 @@ begin
395
410
  assert called
396
411
  end
397
412
 
398
- def test_should_pass_record_into_after_callbacks_with_one_argument
413
+ def test_should_pass_record_to_after_callbacks_with_one_argument
399
414
  record = nil
400
415
  @machine.after_transition(lambda {|arg| record = arg})
401
416
 
@@ -403,12 +418,12 @@ begin
403
418
  assert_equal @record, record
404
419
  end
405
420
 
406
- def test_should_pass_record_transition_and_result_into_after_callbacks_with_multiple_arguments
421
+ def test_should_pass_record_and_transition_to_after_callbacks_with_multiple_arguments
407
422
  callback_args = nil
408
423
  @machine.after_transition(lambda {|*args| callback_args = args})
409
424
 
410
425
  @transition.perform
411
- assert_equal [@record, @transition, true], callback_args
426
+ assert_equal [@record, @transition], callback_args
412
427
  end
413
428
 
414
429
  def test_should_run_after_callbacks_outside_the_context_of_the_record
@@ -458,6 +473,7 @@ begin
458
473
  @model = new_model
459
474
  @machine = StateMachine::Machine.new(@model)
460
475
  @machine.state :parked, :idling
476
+ @machine.event :ignite
461
477
  @machine.before_transition(lambda {@before_count += 1; false})
462
478
  @machine.before_transition(lambda {@before_count += 1})
463
479
 
@@ -491,6 +507,7 @@ begin
491
507
 
492
508
  @machine = StateMachine::Machine.new(@model)
493
509
  @machine.state :parked, :idling
510
+ @machine.event :ignite
494
511
  @record = @model.new(:state => 'parked')
495
512
  @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
496
513
  @result = @transition.perform
@@ -500,8 +517,8 @@ begin
500
517
  assert !@result
501
518
  end
502
519
 
503
- def test_should_change_current_state
504
- assert_equal 'idling', @record.state
520
+ def test_should_not_change_current_state
521
+ assert_equal 'parked', @record.state
505
522
  end
506
523
 
507
524
  def test_should_not_save_record
@@ -545,6 +562,7 @@ begin
545
562
  @model = new_model
546
563
  @machine = StateMachine::Machine.new(@model)
547
564
  @machine.state :parked, :idling
565
+ @machine.event :ignite
548
566
  @machine.after_transition(lambda {@after_count += 1; false})
549
567
  @machine.after_transition(lambda {@after_count += 1})
550
568
 
@@ -570,42 +588,98 @@ begin
570
588
  end
571
589
  end
572
590
 
591
+ class MachineWithEventAttributesOnValidationTest < ActiveRecord::TestCase
592
+ def setup
593
+ @model = new_model
594
+ @machine = StateMachine::Machine.new(@model)
595
+ @machine.event :ignite do
596
+ transition :parked => :idling
597
+ end
598
+
599
+ @record = @model.new
600
+ @record.state = 'parked'
601
+ @record.state_event = 'ignite'
602
+ end
603
+
604
+ def test_should_fail_if_event_is_invalid
605
+ @record.state_event = 'invalid'
606
+ assert !@record.valid?
607
+ assert_equal ['State event is invalid'], @record.errors.full_messages
608
+ end
609
+
610
+ def test_should_fail_if_event_has_no_transition
611
+ @record.state = 'idling'
612
+ assert !@record.valid?
613
+ assert_equal ['State event cannot transition when idling'], @record.errors.full_messages
614
+ end
615
+
616
+ def test_should_be_successful_if_event_has_transition
617
+ assert @record.valid?
618
+ end
619
+
620
+ def test_should_run_before_callbacks
621
+ ran_callback = false
622
+ @machine.before_transition { ran_callback = true }
623
+
624
+ @record.valid?
625
+ assert ran_callback
626
+ end
627
+
628
+ def test_should_persist_new_state
629
+ @record.valid?
630
+ assert_equal 'idling', @record.state
631
+ end
632
+
633
+ def test_should_not_run_after_callbacks
634
+ ran_callback = false
635
+ @machine.after_transition { ran_callback = true }
636
+
637
+ @record.valid?
638
+ assert !ran_callback
639
+ end
640
+ end
641
+
573
642
  class MachineWithObserversTest < ActiveRecord::TestCase
574
643
  def setup
575
644
  @model = new_model
576
645
  @machine = StateMachine::Machine.new(@model)
577
646
  @machine.state :parked, :idling
647
+ @machine.event :ignite
578
648
  @record = @model.new(:state => 'parked')
579
649
  @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
580
650
  end
581
651
 
582
- def test_should_call_before_event_method
583
- observer = new_observer(@model) do
584
- def before_ignite(*args)
585
- notifications << args
586
- end
587
- end
588
- instance = observer.instance
652
+ def test_should_call_all_transition_callback_permutations
653
+ callbacks = [
654
+ :before_ignite_from_parked_to_idling,
655
+ :before_ignite_from_parked,
656
+ :before_ignite_to_idling,
657
+ :before_ignite,
658
+ :before_transition_state_from_parked_to_idling,
659
+ :before_transition_state_from_parked,
660
+ :before_transition_state_to_idling,
661
+ :before_transition_state,
662
+ :before_transition
663
+ ]
589
664
 
590
- @transition.perform
591
- assert_equal [[@record, @transition]], instance.notifications
592
- end
593
-
594
- def test_should_call_before_transition_method
665
+ notified = false
595
666
  observer = new_observer(@model) do
596
- def before_transition(*args)
597
- notifications << args
667
+ callbacks.each do |callback|
668
+ define_method(callback) do |*args|
669
+ notifications << callback
670
+ end
598
671
  end
599
672
  end
673
+
600
674
  instance = observer.instance
601
675
 
602
676
  @transition.perform
603
- assert_equal [[@record, @transition]], instance.notifications
677
+ assert_equal callbacks, instance.notifications
604
678
  end
605
679
 
606
- def test_should_call_after_event_method
680
+ def test_should_pass_record_and_transition_to_before_callbacks
607
681
  observer = new_observer(@model) do
608
- def after_ignite(*args)
682
+ def before_transition(*args)
609
683
  notifications << args
610
684
  end
611
685
  end
@@ -615,7 +689,7 @@ begin
615
689
  assert_equal [[@record, @transition]], instance.notifications
616
690
  end
617
691
 
618
- def test_should_call_after_transition_method
692
+ def test_should_pass_record_and_transition_to_after_callbacks
619
693
  observer = new_observer(@model) do
620
694
  def after_transition(*args)
621
695
  notifications << args
@@ -627,22 +701,6 @@ begin
627
701
  assert_equal [[@record, @transition]], instance.notifications
628
702
  end
629
703
 
630
- def test_should_call_event_method_before_transition_method
631
- observer = new_observer(@model) do
632
- def before_ignite(*args)
633
- notifications << :before_ignite
634
- end
635
-
636
- def before_transition(*args)
637
- notifications << :before_transition
638
- end
639
- end
640
- instance = observer.instance
641
-
642
- @transition.perform
643
- assert_equal [:before_ignite, :before_transition], instance.notifications
644
- end
645
-
646
704
  def test_should_call_methods_outside_the_context_of_the_record
647
705
  observer = new_observer(@model) do
648
706
  def before_ignite(*args)
@@ -659,15 +717,16 @@ begin
659
717
  class MachineWithNamespacedObserversTest < ActiveRecord::TestCase
660
718
  def setup
661
719
  @model = new_model
662
- @machine = StateMachine::Machine.new(@model, :namespace => 'car')
663
- @machine.state :parked, :idling
664
- @record = @model.new(:state => 'parked')
665
- @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
720
+ @machine = StateMachine::Machine.new(@model, :state, :namespace => 'alarm')
721
+ @machine.state :active, :off
722
+ @machine.event :enable
723
+ @record = @model.new(:state => 'off')
724
+ @transition = StateMachine::Transition.new(@record, @machine, :enable, :off, :active)
666
725
  end
667
726
 
668
727
  def test_should_call_namespaced_before_event_method
669
728
  observer = new_observer(@model) do
670
- def before_ignite_car(*args)
729
+ def before_enable_alarm(*args)
671
730
  notifications << args
672
731
  end
673
732
  end
@@ -679,7 +738,7 @@ begin
679
738
 
680
739
  def test_should_call_namespaced_after_event_method
681
740
  observer = new_observer(@model) do
682
- def after_ignite_car(*args)
741
+ def after_enable_alarm(*args)
683
742
  notifications << args
684
743
  end
685
744
  end
@@ -695,6 +754,7 @@ begin
695
754
  @model = new_model
696
755
  @machine = StateMachine::Machine.new(@model)
697
756
  @machine.state :parked, :idling
757
+ @machine.event :ignite
698
758
  @record = @model.new(:state => 'parked')
699
759
  @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
700
760
 
@@ -758,7 +818,7 @@ begin
758
818
  :activerecord => {
759
819
  :errors => {
760
820
  :messages => {
761
- :invalid_transition => 'cannot {{event}} when {{value}}'
821
+ :invalid_transition => 'cannot {{event}}'
762
822
  }
763
823
  }
764
824
  }
@@ -770,8 +830,8 @@ begin
770
830
 
771
831
  record = @model.new(:state => 'idling')
772
832
 
773
- machine.invalidate(record, event)
774
- assert_equal 'cannot ignite when idling', record.errors.on(:state)
833
+ machine.invalidate(record, :state, :invalid_transition, [[:event, :ignite]])
834
+ assert_equal 'cannot ignite', record.errors.on(:state)
775
835
  end
776
836
 
777
837
  def test_should_invalidate_using_customized_i18n_key_if_specified
@@ -779,32 +839,30 @@ begin
779
839
  :activerecord => {
780
840
  :errors => {
781
841
  :messages => {
782
- :bad_transition => 'cannot {{event}} when {{value}}'
842
+ :bad_transition => 'cannot {{event}}'
783
843
  }
784
844
  }
785
845
  }
786
846
  })
787
847
 
788
- machine = StateMachine::Machine.new(@model, :invalid_message => :bad_transition)
848
+ machine = StateMachine::Machine.new(@model, :messages => {:invalid_transition => :bad_transition})
789
849
  machine.state :parked, :idling
790
- event = StateMachine::Event.new(machine, :ignite)
791
850
 
792
851
  record = @model.new(:state => 'idling')
793
852
 
794
- machine.invalidate(record, event)
795
- assert_equal 'cannot ignite when idling', record.errors.on(:state)
853
+ machine.invalidate(record, :state, :invalid_transition, [[:event, :ignite]])
854
+ assert_equal 'cannot ignite', record.errors.on(:state)
796
855
  end
797
856
  end
798
857
 
799
858
  def test_should_invalidate_using_customized_i18n_string_if_specified
800
- machine = StateMachine::Machine.new(@model, :invalid_message => 'cannot {{event}} when {{value}}')
859
+ machine = StateMachine::Machine.new(@model, :messages => {:invalid_transition => 'cannot {{event}}'})
801
860
  machine.state :parked, :idling
802
- event = StateMachine::Event.new(machine, :ignite)
803
861
 
804
862
  record = @model.new(:state => 'idling')
805
863
 
806
- machine.invalidate(record, event)
807
- assert_equal 'cannot ignite when idling', record.errors.on(:state)
864
+ machine.invalidate(record, :state, :invalid_transition, [[:event, :ignite]])
865
+ assert_equal 'cannot ignite', record.errors.on(:state)
808
866
  end
809
867
  else
810
868
  $stderr.puts 'Skipping ActiveRecord I18n tests. `gem install active_record` >= v2.2.0 and try again.'