state_machines-activerecord 0.0.1

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 (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