state_machines-activerecord 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.travis.yml +20 -0
  4. data/Appraisals +11 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE.txt +23 -0
  7. data/README.md +65 -0
  8. data/Rakefile +9 -0
  9. data/gemfiles/active_record_4.1.gemfile +13 -0
  10. data/gemfiles/active_record_4.2.gemfile +13 -0
  11. data/lib/state_machines-activerecord.rb +1 -0
  12. data/lib/state_machines/integrations/active_record.rb +588 -0
  13. data/lib/state_machines/integrations/active_record/locale.rb +12 -0
  14. data/lib/state_machines/integrations/active_record/version.rb +7 -0
  15. data/log/.gitkeep +0 -0
  16. data/state_machines-activerecord.gemspec +27 -0
  17. data/test/files/en.yml +5 -0
  18. data/test/files/models/post.rb +11 -0
  19. data/test/integration_test.rb +23 -0
  20. data/test/machine_by_default_test.rb +16 -0
  21. data/test/machine_errors_test.rb +19 -0
  22. data/test/machine_multiple_test.rb +17 -0
  23. data/test/machine_nested_action_test.rb +38 -0
  24. data/test/machine_unmigrated_test.rb +14 -0
  25. data/test/machine_with_aliased_attribute_test.rb +23 -0
  26. data/test/machine_with_callbacks_test.rb +172 -0
  27. data/test/machine_with_column_state_attribute_test.rb +44 -0
  28. data/test/machine_with_complex_pluralization_scopes_test.rb +16 -0
  29. data/test/machine_with_conflicting_predicate_test.rb +18 -0
  30. data/test/machine_with_conflicting_state_name_test.rb +29 -0
  31. data/test/machine_with_custom_attribute_test.rb +21 -0
  32. data/test/machine_with_default_scope_test.rb +18 -0
  33. data/test/machine_with_different_column_default_test.rb +27 -0
  34. data/test/machine_with_different_integer_column_default_test.rb +29 -0
  35. data/test/machine_with_dirty_attribute_and_custom_attributes_during_loopback_test.rb +24 -0
  36. data/test/machine_with_dirty_attribute_and_state_events_test.rb +20 -0
  37. data/test/machine_with_dirty_attributes_and_custom_attribute_test.rb +32 -0
  38. data/test/machine_with_dirty_attributes_during_loopback_test.rb +22 -0
  39. data/test/machine_with_dirty_attributes_test.rb +35 -0
  40. data/test/machine_with_dynamic_initial_state_test.rb +99 -0
  41. data/test/machine_with_event_attributes_on_autosave_test.rb +48 -0
  42. data/test/machine_with_event_attributes_on_custom_action_test.rb +41 -0
  43. data/test/machine_with_event_attributes_on_save_bang_test.rb +82 -0
  44. data/test/machine_with_event_attributes_on_save_test.rb +184 -0
  45. data/test/machine_with_event_attributes_on_validation_test.rb +126 -0
  46. data/test/machine_with_events_test.rb +13 -0
  47. data/test/machine_with_failed_action_test.rb +40 -0
  48. data/test/machine_with_failed_after_callbacks_test.rb +35 -0
  49. data/test/machine_with_failed_before_callbacks_test.rb +36 -0
  50. data/test/machine_with_initialized_state_test.rb +35 -0
  51. data/test/machine_with_internationalization_test.rb +180 -0
  52. data/test/machine_with_loopback_test.rb +22 -0
  53. data/test/machine_with_non_column_state_attribute_defined_test.rb +35 -0
  54. data/test/machine_with_non_column_state_attribute_undefined_test.rb +33 -0
  55. data/test/machine_with_same_column_default_test.rb +26 -0
  56. data/test/machine_with_scopes_and_joins_test.rb +37 -0
  57. data/test/machine_with_scopes_and_owner_subclass_test.rb +27 -0
  58. data/test/machine_with_scopes_test.rb +70 -0
  59. data/test/machine_with_state_driven_validations_test.rb +30 -0
  60. data/test/machine_with_states_test.rb +13 -0
  61. data/test/machine_with_static_initial_state_test.rb +166 -0
  62. data/test/machine_with_transactions_test.rb +26 -0
  63. data/test/machine_with_validations_and_custom_attribute_test.rb +21 -0
  64. data/test/machine_with_validations_test.rb +47 -0
  65. data/test/machine_without_database_test.rb +20 -0
  66. data/test/machine_without_transactions_test.rb +26 -0
  67. data/test/model_test.rb +12 -0
  68. data/test/test_helper.rb +42 -0
  69. metadata +264 -0
@@ -0,0 +1,41 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithEventAttributesOnCustomActionTest < BaseTestCase
4
+ def setup
5
+ @superclass = new_model do
6
+ def persist
7
+ create_or_update
8
+ end
9
+ end
10
+ @model = Class.new(@superclass)
11
+ @machine = StateMachines::Machine.new(@model, :action => :persist)
12
+ @machine.event :ignite do
13
+ transition :parked => :idling
14
+ end
15
+
16
+ @record = @model.new
17
+ @record.state = 'parked'
18
+ @record.state_event = 'ignite'
19
+ end
20
+
21
+ def test_should_not_transition_on_valid?
22
+ @record.valid?
23
+ assert_equal 'parked', @record.state
24
+ end
25
+
26
+ def test_should_not_transition_on_save
27
+ @record.save
28
+ assert_equal 'parked', @record.state
29
+ end
30
+
31
+ def test_should_not_transition_on_save!
32
+ @record.save!
33
+ assert_equal 'parked', @record.state
34
+ end
35
+
36
+ def test_should_transition_on_custom_action
37
+ @record.persist
38
+ assert_equal 'idling', @record.state
39
+ end
40
+ end
41
+
@@ -0,0 +1,82 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithEventAttributesOnSaveBangTest < BaseTestCase
4
+ def setup
5
+ @model = new_model
6
+ @machine = StateMachines::Machine.new(@model)
7
+ @machine.event :ignite do
8
+ transition :parked => :idling
9
+ end
10
+
11
+ @record = @model.new
12
+ @record.state = 'parked'
13
+ @record.state_event = 'ignite'
14
+ end
15
+
16
+ def test_should_fail_if_event_is_invalid
17
+ @record.state_event = 'invalid'
18
+ assert_raise(ActiveRecord::RecordInvalid) { @record.save! }
19
+ end
20
+
21
+ def test_should_fail_if_event_has_no_transition
22
+ @record.state = 'idling'
23
+ assert_raise(ActiveRecord::RecordInvalid) { @record.save! }
24
+ end
25
+
26
+ def test_should_be_successful_if_event_has_transition
27
+ assert_equal true, @record.save!
28
+ end
29
+
30
+ def test_should_run_before_callbacks
31
+ ran_callback = false
32
+ @machine.before_transition { ran_callback = true }
33
+
34
+ @record.save!
35
+ assert ran_callback
36
+ end
37
+
38
+ def test_should_run_before_callbacks_once
39
+ before_count = 0
40
+ @machine.before_transition { before_count += 1 }
41
+
42
+ @record.save!
43
+ assert_equal 1, before_count
44
+ end
45
+
46
+ def test_should_run_around_callbacks_before_yield
47
+ ran_callback = false
48
+ @machine.around_transition { |block| ran_callback = true; block.call }
49
+
50
+ @record.save!
51
+ assert ran_callback
52
+ end
53
+
54
+ def test_should_run_around_callbacks_before_yield_once
55
+ around_before_count = 0
56
+ @machine.around_transition { |block| around_before_count += 1; block.call }
57
+
58
+ @record.save!
59
+ assert_equal 1, around_before_count
60
+ end
61
+
62
+ def test_should_persist_new_state
63
+ @record.save!
64
+ assert_equal 'idling', @record.state
65
+ end
66
+
67
+ def test_should_run_after_callbacks
68
+ ran_callback = false
69
+ @machine.after_transition { ran_callback = true }
70
+
71
+ @record.save!
72
+ assert ran_callback
73
+ end
74
+
75
+ def test_should_run_around_callbacks_after_yield
76
+ ran_callback = false
77
+ @machine.around_transition { |block| block.call; ran_callback = true }
78
+
79
+ @record.save!
80
+ assert ran_callback
81
+ end
82
+ end
@@ -0,0 +1,184 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithEventAttributesOnSaveTest < BaseTestCase
4
+ def setup
5
+ @model = new_model
6
+ @machine = StateMachines::Machine.new(@model)
7
+ @machine.event :ignite do
8
+ transition :parked => :idling
9
+ end
10
+
11
+ @record = @model.new
12
+ @record.state = 'parked'
13
+ @record.state_event = 'ignite'
14
+ end
15
+
16
+ def test_should_fail_if_event_is_invalid
17
+ @record.state_event = 'invalid'
18
+ assert_equal false, @record.save
19
+ end
20
+
21
+ def test_should_fail_if_event_has_no_transition
22
+ @record.state = 'idling'
23
+ assert_equal false, @record.save
24
+ end
25
+
26
+ def test_should_run_before_callbacks
27
+ ran_callback = false
28
+ @machine.before_transition { ran_callback = true }
29
+
30
+ @record.save
31
+ assert ran_callback
32
+ end
33
+
34
+ def test_should_run_before_callbacks_once
35
+ before_count = 0
36
+ @machine.before_transition { before_count += 1 }
37
+
38
+ @record.save
39
+ assert_equal 1, before_count
40
+ end
41
+
42
+ def test_should_run_around_callbacks_before_yield
43
+ ran_callback = false
44
+ @machine.around_transition { |block| ran_callback = true; block.call }
45
+
46
+ @record.save
47
+ assert ran_callback
48
+ end
49
+
50
+ def test_should_run_around_callbacks_before_yield_once
51
+ around_before_count = 0
52
+ @machine.around_transition { |block| around_before_count += 1; block.call }
53
+
54
+ @record.save
55
+ assert_equal 1, around_before_count
56
+ end
57
+
58
+ def test_should_persist_new_state
59
+ @record.save
60
+ assert_equal 'idling', @record.state
61
+ end
62
+
63
+ def test_should_run_after_callbacks
64
+ ran_callback = false
65
+ @machine.after_transition { ran_callback = true }
66
+
67
+ @record.save
68
+ assert ran_callback
69
+ end
70
+
71
+ def test_should_not_run_after_callbacks_with_failures_disabled_if_fails
72
+ @model.before_create { |record| false }
73
+
74
+ ran_callback = false
75
+ @machine.after_transition { ran_callback = true }
76
+
77
+ begin
78
+ ; @record.save;
79
+ rescue;
80
+ end
81
+ refute ran_callback
82
+ end
83
+
84
+ def test_should_run_failure_callbacks__if_fails
85
+ @model.before_create { |record| false }
86
+
87
+ ran_callback = false
88
+ @machine.after_failure { ran_callback = true }
89
+
90
+ begin
91
+ ; @record.save;
92
+ rescue;
93
+ end
94
+ assert ran_callback
95
+ end
96
+
97
+ def test_should_not_run_around_callbacks_if_fails
98
+ @model.before_create { |record| false }
99
+
100
+ ran_callback = false
101
+ @machine.around_transition { |block| block.call; ran_callback = true }
102
+
103
+ begin
104
+ ; @record.save;
105
+ rescue;
106
+ end
107
+ refute ran_callback
108
+ end
109
+
110
+ def test_should_run_around_callbacks_after_yield
111
+ ran_callback = false
112
+ @machine.around_transition { |block| block.call; ran_callback = true }
113
+
114
+ @record.save
115
+ assert ran_callback
116
+ end
117
+
118
+ def test_should_run_before_transitions_within_transaction
119
+ @machine.before_transition { @model.create; raise ActiveRecord::Rollback }
120
+
121
+ begin
122
+ @record.save
123
+ rescue Exception
124
+ end
125
+
126
+ assert_equal 0, @model.count
127
+ end
128
+
129
+ def test_should_run_after_transitions_within_transaction
130
+ @machine.after_transition { @model.create; raise ActiveRecord::Rollback }
131
+
132
+ begin
133
+ @record.save
134
+ rescue Exception
135
+ end
136
+
137
+ assert_equal 0, @model.count
138
+ end
139
+
140
+ def test_should_run_around_transition_within_transaction
141
+ @machine.around_transition { @model.create; raise ActiveRecord::Rollback }
142
+
143
+ begin
144
+ @record.save
145
+ rescue Exception
146
+ end
147
+
148
+ assert_equal 0, @model.count
149
+ end
150
+
151
+ def test_should_allow_additional_transitions_to_new_state_in_after_transitions
152
+ @machine.event :park do
153
+ transition :idling => :parked
154
+ end
155
+
156
+ @machine.after_transition(:on => :ignite) { @record.park }
157
+
158
+ @record.save
159
+ assert_equal 'parked', @record.state
160
+
161
+ @record.reload
162
+ assert_equal 'parked', @record.state
163
+ end
164
+
165
+ def test_should_allow_additional_transitions_to_previous_state_in_after_transitions
166
+ @machine.event :shift_up do
167
+ transition :idling => :first_gear
168
+ end
169
+
170
+ @machine.after_transition(:on => :ignite) { @record.shift_up }
171
+
172
+ @record.save
173
+ assert_equal 'first_gear', @record.state
174
+
175
+ @record.reload
176
+ assert_equal 'first_gear', @record.state
177
+ end
178
+
179
+ def test_should_return_nil_on_manual_rollback
180
+ @machine.before_transition { raise ActiveRecord::Rollback }
181
+
182
+ assert_equal nil, @record.save
183
+ end
184
+ end
@@ -0,0 +1,126 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithEventAttributesOnValidationTest < BaseTestCase
4
+ def setup
5
+ @model = new_model
6
+ @machine = StateMachines::Machine.new(@model)
7
+ @machine.event :ignite do
8
+ transition :parked => :idling
9
+ end
10
+
11
+ @record = @model.new
12
+ @record.state = 'parked'
13
+ @record.state_event = 'ignite'
14
+ end
15
+
16
+ def test_should_fail_if_event_is_invalid
17
+ @record.state_event = 'invalid'
18
+ refute @record.valid?
19
+ assert_equal ['State event is invalid'], @record.errors.full_messages
20
+ end
21
+
22
+ def test_should_fail_if_event_has_no_transition
23
+ @record.state = 'idling'
24
+ refute @record.valid?
25
+ assert_equal ['State event cannot transition when idling'], @record.errors.full_messages
26
+ end
27
+
28
+ def test_should_be_successful_if_event_has_transition
29
+ assert @record.valid?
30
+ end
31
+
32
+ def test_should_run_before_callbacks
33
+ ran_callback = false
34
+ @machine.before_transition { ran_callback = true }
35
+
36
+ @record.valid?
37
+ assert ran_callback
38
+ end
39
+
40
+ def test_should_run_around_callbacks_before_yield
41
+ ran_callback = false
42
+ @machine.around_transition { |block| ran_callback = true; block.call }
43
+
44
+ begin
45
+ @record.valid?
46
+ rescue ArgumentError
47
+ raise if StateMachines::Transition.pause_supported?
48
+ end
49
+ assert ran_callback
50
+ end
51
+
52
+ def test_should_persist_new_state
53
+ @record.valid?
54
+ assert_equal 'idling', @record.state
55
+ end
56
+
57
+ def test_should_not_run_after_callbacks
58
+ ran_callback = false
59
+ @machine.after_transition { ran_callback = true }
60
+
61
+ @record.valid?
62
+ refute ran_callback
63
+ end
64
+
65
+ def test_should_not_run_after_callbacks_with_failures_disabled_if_validation_fails
66
+ @model.class_eval do
67
+ attr_accessor :seatbelt
68
+ validates_presence_of :seatbelt
69
+ end
70
+
71
+ ran_callback = false
72
+ @machine.after_transition { ran_callback = true }
73
+
74
+ @record.valid?
75
+ refute ran_callback
76
+ end
77
+
78
+ def test_should_run_after_callbacks_if_validation_fails
79
+ @model.class_eval do
80
+ attr_accessor :seatbelt
81
+ validates_presence_of :seatbelt
82
+ end
83
+
84
+ ran_callback = false
85
+ @machine.after_failure { ran_callback = true }
86
+
87
+ @record.valid?
88
+ assert ran_callback
89
+ end
90
+
91
+ def test_should_not_run_around_callbacks_after_yield
92
+ ran_callback = false
93
+ @machine.around_transition { |block| block.call; ran_callback = true }
94
+
95
+ begin
96
+ @record.valid?
97
+ rescue ArgumentError
98
+ raise if StateMachines::Transition.pause_supported?
99
+ end
100
+ refute ran_callback
101
+ end
102
+
103
+ def test_should_not_run_around_callbacks_after_yield_with_failures_disabled_if_validation_fails
104
+ @model.class_eval do
105
+ attr_accessor :seatbelt
106
+ validates_presence_of :seatbelt
107
+ end
108
+
109
+ ran_callback = false
110
+ @machine.around_transition { |block| block.call; ran_callback = true }
111
+
112
+ @record.valid?
113
+ refute ran_callback
114
+ end
115
+
116
+ def test_should_not_run_before_transitions_within_transaction
117
+ @machine.before_transition { @model.create; raise ActiveRecord::Rollback }
118
+
119
+ begin
120
+ @record.valid?
121
+ rescue Exception
122
+ end
123
+
124
+ assert_equal 1, @model.count
125
+ end
126
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithEventsTest < BaseTestCase
4
+ def setup
5
+ @model = new_model
6
+ @machine = StateMachines::Machine.new(@model)
7
+ @machine.event :shift_up
8
+ end
9
+
10
+ def test_should_humanize_name
11
+ assert_equal 'shift up', @machine.event(:shift_up).human_name
12
+ end
13
+ end