state_machine 0.6.3 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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.'