aasm 5.0.0 → 5.5.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 (231) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +243 -118
  3. data/lib/aasm/aasm.rb +29 -27
  4. data/lib/aasm/base.rb +61 -11
  5. data/lib/aasm/configuration.rb +3 -0
  6. data/lib/aasm/core/event.rb +21 -9
  7. data/lib/aasm/core/invokers/class_invoker.rb +1 -1
  8. data/lib/aasm/core/invokers/literal_invoker.rb +3 -1
  9. data/lib/aasm/core/state.rb +6 -5
  10. data/lib/aasm/core/transition.rb +1 -1
  11. data/lib/aasm/dsl_helper.rb +24 -22
  12. data/lib/aasm/errors.rb +3 -1
  13. data/lib/aasm/instance_base.rb +28 -5
  14. data/lib/aasm/localizer.rb +13 -3
  15. data/lib/aasm/persistence/active_record_persistence.rb +25 -5
  16. data/lib/aasm/persistence/base.rb +14 -3
  17. data/lib/aasm/persistence/core_data_query_persistence.rb +2 -1
  18. data/lib/aasm/persistence/dynamoid_persistence.rb +1 -1
  19. data/lib/aasm/persistence/mongoid_persistence.rb +1 -1
  20. data/lib/aasm/persistence/no_brainer_persistence.rb +1 -1
  21. data/lib/aasm/persistence/orm.rb +23 -19
  22. data/lib/aasm/persistence/redis_persistence.rb +1 -1
  23. data/lib/aasm/rspec/transition_from.rb +5 -1
  24. data/lib/aasm/version.rb +1 -1
  25. data/lib/aasm.rb +0 -2
  26. data/lib/generators/aasm/orm_helpers.rb +7 -1
  27. data/lib/generators/active_record/aasm_generator.rb +3 -1
  28. data/lib/generators/active_record/templates/migration.rb +1 -1
  29. metadata +35 -385
  30. data/.document +0 -6
  31. data/.gitignore +0 -20
  32. data/.travis.yml +0 -54
  33. data/API +0 -34
  34. data/Appraisals +0 -66
  35. data/CHANGELOG.md +0 -377
  36. data/CODE_OF_CONDUCT.md +0 -13
  37. data/CONTRIBUTING.md +0 -24
  38. data/Dockerfile +0 -44
  39. data/Gemfile +0 -6
  40. data/Gemfile.lock_old +0 -151
  41. data/HOWTO +0 -12
  42. data/PLANNED_CHANGES.md +0 -11
  43. data/README_FROM_VERSION_3_TO_4.md +0 -240
  44. data/Rakefile +0 -31
  45. data/TESTING.md +0 -25
  46. data/aasm.gemspec +0 -35
  47. data/callbacks.txt +0 -51
  48. data/docker-compose.yml +0 -40
  49. data/gemfiles/rails_3.2.gemfile +0 -13
  50. data/gemfiles/rails_4.0.gemfile +0 -15
  51. data/gemfiles/rails_4.2.gemfile +0 -16
  52. data/gemfiles/rails_4.2_mongoid_5.gemfile +0 -11
  53. data/gemfiles/rails_4.2_nobrainer.gemfile +0 -9
  54. data/gemfiles/rails_5.0.gemfile +0 -13
  55. data/gemfiles/rails_5.0_nobrainer.gemfile +0 -9
  56. data/gemfiles/rails_5.1.gemfile +0 -13
  57. data/spec/database.rb +0 -44
  58. data/spec/database.yml +0 -3
  59. data/spec/en.yml +0 -12
  60. data/spec/en_deprecated_style.yml +0 -10
  61. data/spec/generators/active_record_generator_spec.rb +0 -47
  62. data/spec/generators/mongoid_generator_spec.rb +0 -31
  63. data/spec/generators/no_brainer_generator_spec.rb +0 -29
  64. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +0 -25
  65. data/spec/models/active_record/complex_active_record_example.rb +0 -37
  66. data/spec/models/active_record/derivate_new_dsl.rb +0 -7
  67. data/spec/models/active_record/false_state.rb +0 -35
  68. data/spec/models/active_record/gate.rb +0 -39
  69. data/spec/models/active_record/invalid_persistor.rb +0 -29
  70. data/spec/models/active_record/localizer_test_model.rb +0 -34
  71. data/spec/models/active_record/no_direct_assignment.rb +0 -21
  72. data/spec/models/active_record/no_scope.rb +0 -21
  73. data/spec/models/active_record/persisted_state.rb +0 -12
  74. data/spec/models/active_record/provided_and_persisted_state.rb +0 -24
  75. data/spec/models/active_record/reader.rb +0 -7
  76. data/spec/models/active_record/readme_job.rb +0 -21
  77. data/spec/models/active_record/silent_persistor.rb +0 -29
  78. data/spec/models/active_record/simple_new_dsl.rb +0 -17
  79. data/spec/models/active_record/thief.rb +0 -29
  80. data/spec/models/active_record/transactor.rb +0 -124
  81. data/spec/models/active_record/transient.rb +0 -6
  82. data/spec/models/active_record/validator.rb +0 -118
  83. data/spec/models/active_record/with_enum.rb +0 -39
  84. data/spec/models/active_record/with_enum_without_column.rb +0 -38
  85. data/spec/models/active_record/with_false_enum.rb +0 -31
  86. data/spec/models/active_record/with_true_enum.rb +0 -39
  87. data/spec/models/active_record/worker.rb +0 -2
  88. data/spec/models/active_record/writer.rb +0 -6
  89. data/spec/models/basic_two_state_machines_example.rb +0 -25
  90. data/spec/models/callbacks/basic.rb +0 -98
  91. data/spec/models/callbacks/basic_multiple.rb +0 -75
  92. data/spec/models/callbacks/guard_within_block.rb +0 -67
  93. data/spec/models/callbacks/guard_within_block_multiple.rb +0 -66
  94. data/spec/models/callbacks/multiple_transitions_transition_guard.rb +0 -66
  95. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +0 -65
  96. data/spec/models/callbacks/private_method.rb +0 -44
  97. data/spec/models/callbacks/private_method_multiple.rb +0 -44
  98. data/spec/models/callbacks/with_args.rb +0 -62
  99. data/spec/models/callbacks/with_args_multiple.rb +0 -61
  100. data/spec/models/callbacks/with_state_arg.rb +0 -30
  101. data/spec/models/callbacks/with_state_arg_multiple.rb +0 -26
  102. data/spec/models/complex_example.rb +0 -222
  103. data/spec/models/conversation.rb +0 -93
  104. data/spec/models/default_state.rb +0 -12
  105. data/spec/models/double_definer.rb +0 -21
  106. data/spec/models/dynamoid/complex_dynamoid_example.rb +0 -37
  107. data/spec/models/dynamoid/dynamoid_multiple.rb +0 -18
  108. data/spec/models/dynamoid/dynamoid_simple.rb +0 -18
  109. data/spec/models/foo.rb +0 -106
  110. data/spec/models/foo_callback_multiple.rb +0 -45
  111. data/spec/models/guard_arguments_check.rb +0 -17
  112. data/spec/models/guard_with_params.rb +0 -24
  113. data/spec/models/guard_with_params_multiple.rb +0 -18
  114. data/spec/models/guardian.rb +0 -58
  115. data/spec/models/guardian_multiple.rb +0 -48
  116. data/spec/models/guardian_without_from_specified.rb +0 -18
  117. data/spec/models/initial_state_proc.rb +0 -31
  118. data/spec/models/mongoid/complex_mongoid_example.rb +0 -37
  119. data/spec/models/mongoid/invalid_persistor_mongoid.rb +0 -39
  120. data/spec/models/mongoid/mongoid_relationships.rb +0 -26
  121. data/spec/models/mongoid/no_scope_mongoid.rb +0 -21
  122. data/spec/models/mongoid/silent_persistor_mongoid.rb +0 -39
  123. data/spec/models/mongoid/simple_mongoid.rb +0 -23
  124. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +0 -25
  125. data/spec/models/mongoid/validator_mongoid.rb +0 -100
  126. data/spec/models/multi_transitioner.rb +0 -34
  127. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +0 -31
  128. data/spec/models/namespaced_multiple_example.rb +0 -42
  129. data/spec/models/no_initial_state.rb +0 -25
  130. data/spec/models/nobrainer/complex_no_brainer_example.rb +0 -36
  131. data/spec/models/nobrainer/invalid_persistor_no_brainer.rb +0 -39
  132. data/spec/models/nobrainer/no_scope_no_brainer.rb +0 -21
  133. data/spec/models/nobrainer/nobrainer_relationships.rb +0 -25
  134. data/spec/models/nobrainer/silent_persistor_no_brainer.rb +0 -39
  135. data/spec/models/nobrainer/simple_new_dsl_nobrainer.rb +0 -25
  136. data/spec/models/nobrainer/simple_no_brainer.rb +0 -23
  137. data/spec/models/nobrainer/validator_no_brainer.rb +0 -98
  138. data/spec/models/not_auto_loaded/process.rb +0 -21
  139. data/spec/models/parametrised_event.rb +0 -42
  140. data/spec/models/parametrised_event_multiple.rb +0 -29
  141. data/spec/models/process_with_new_dsl.rb +0 -31
  142. data/spec/models/provided_state.rb +0 -24
  143. data/spec/models/redis/complex_redis_example.rb +0 -40
  144. data/spec/models/redis/redis_multiple.rb +0 -20
  145. data/spec/models/redis/redis_simple.rb +0 -20
  146. data/spec/models/sequel/complex_sequel_example.rb +0 -46
  147. data/spec/models/sequel/invalid_persistor.rb +0 -52
  148. data/spec/models/sequel/sequel_multiple.rb +0 -25
  149. data/spec/models/sequel/sequel_simple.rb +0 -26
  150. data/spec/models/sequel/silent_persistor.rb +0 -50
  151. data/spec/models/sequel/transactor.rb +0 -112
  152. data/spec/models/sequel/validator.rb +0 -93
  153. data/spec/models/sequel/worker.rb +0 -12
  154. data/spec/models/silencer.rb +0 -27
  155. data/spec/models/simple_custom_example.rb +0 -53
  156. data/spec/models/simple_example.rb +0 -17
  157. data/spec/models/simple_example_with_guard_args.rb +0 -17
  158. data/spec/models/simple_multiple_example.rb +0 -42
  159. data/spec/models/state_machine_with_failed_event.rb +0 -20
  160. data/spec/models/states_on_one_line_example.rb +0 -8
  161. data/spec/models/sub_class.rb +0 -41
  162. data/spec/models/sub_class_with_more_states.rb +0 -18
  163. data/spec/models/sub_classing.rb +0 -3
  164. data/spec/models/super_class.rb +0 -46
  165. data/spec/models/this_name_better_not_be_in_use.rb +0 -11
  166. data/spec/models/valid_state_name.rb +0 -23
  167. data/spec/spec_helper.rb +0 -26
  168. data/spec/spec_helpers/active_record.rb +0 -8
  169. data/spec/spec_helpers/dynamoid.rb +0 -35
  170. data/spec/spec_helpers/mongoid.rb +0 -26
  171. data/spec/spec_helpers/nobrainer.rb +0 -15
  172. data/spec/spec_helpers/redis.rb +0 -18
  173. data/spec/spec_helpers/remove_warnings.rb +0 -1
  174. data/spec/spec_helpers/sequel.rb +0 -7
  175. data/spec/unit/api_spec.rb +0 -100
  176. data/spec/unit/basic_two_state_machines_example_spec.rb +0 -10
  177. data/spec/unit/callback_multiple_spec.rb +0 -300
  178. data/spec/unit/callbacks_spec.rb +0 -491
  179. data/spec/unit/complex_example_spec.rb +0 -94
  180. data/spec/unit/complex_multiple_example_spec.rb +0 -115
  181. data/spec/unit/edge_cases_spec.rb +0 -16
  182. data/spec/unit/event_multiple_spec.rb +0 -73
  183. data/spec/unit/event_naming_spec.rb +0 -16
  184. data/spec/unit/event_spec.rb +0 -381
  185. data/spec/unit/exception_spec.rb +0 -11
  186. data/spec/unit/guard_arguments_check_spec.rb +0 -9
  187. data/spec/unit/guard_multiple_spec.rb +0 -60
  188. data/spec/unit/guard_spec.rb +0 -89
  189. data/spec/unit/guard_with_params_multiple_spec.rb +0 -10
  190. data/spec/unit/guard_with_params_spec.rb +0 -14
  191. data/spec/unit/guard_without_from_specified_spec.rb +0 -10
  192. data/spec/unit/initial_state_multiple_spec.rb +0 -15
  193. data/spec/unit/initial_state_spec.rb +0 -12
  194. data/spec/unit/inspection_multiple_spec.rb +0 -201
  195. data/spec/unit/inspection_spec.rb +0 -149
  196. data/spec/unit/invoker_spec.rb +0 -189
  197. data/spec/unit/invokers/base_invoker_spec.rb +0 -72
  198. data/spec/unit/invokers/class_invoker_spec.rb +0 -95
  199. data/spec/unit/invokers/literal_invoker_spec.rb +0 -86
  200. data/spec/unit/invokers/proc_invoker_spec.rb +0 -86
  201. data/spec/unit/localizer_spec.rb +0 -78
  202. data/spec/unit/memory_leak_spec.rb +0 -38
  203. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +0 -14
  204. data/spec/unit/namespaced_multiple_example_spec.rb +0 -75
  205. data/spec/unit/new_dsl_spec.rb +0 -12
  206. data/spec/unit/override_warning_spec.rb +0 -94
  207. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +0 -618
  208. data/spec/unit/persistence/active_record_persistence_spec.rb +0 -735
  209. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +0 -135
  210. data/spec/unit/persistence/dynamoid_persistence_spec.rb +0 -84
  211. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +0 -200
  212. data/spec/unit/persistence/mongoid_persistence_spec.rb +0 -165
  213. data/spec/unit/persistence/no_brainer_persistence_multiple_spec.rb +0 -198
  214. data/spec/unit/persistence/no_brainer_persistence_spec.rb +0 -158
  215. data/spec/unit/persistence/redis_persistence_multiple_spec.rb +0 -88
  216. data/spec/unit/persistence/redis_persistence_spec.rb +0 -53
  217. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +0 -148
  218. data/spec/unit/persistence/sequel_persistence_spec.rb +0 -368
  219. data/spec/unit/readme_spec.rb +0 -41
  220. data/spec/unit/reloading_spec.rb +0 -15
  221. data/spec/unit/rspec_matcher_spec.rb +0 -85
  222. data/spec/unit/simple_custom_example_spec.rb +0 -39
  223. data/spec/unit/simple_example_spec.rb +0 -42
  224. data/spec/unit/simple_multiple_example_spec.rb +0 -91
  225. data/spec/unit/state_spec.rb +0 -89
  226. data/spec/unit/states_on_one_line_example_spec.rb +0 -16
  227. data/spec/unit/subclassing_multiple_spec.rb +0 -74
  228. data/spec/unit/subclassing_spec.rb +0 -46
  229. data/spec/unit/transition_spec.rb +0 -436
  230. data/test/minitest_helper.rb +0 -57
  231. data/test/unit/minitest_matcher_test.rb +0 -80
@@ -1,735 +0,0 @@
1
- require 'spec_helper'
2
-
3
- if defined?(ActiveRecord)
4
-
5
- Dir[File.dirname(__FILE__) + "/../../models/active_record/*.rb"].sort.each do |f|
6
- require File.expand_path(f)
7
- end
8
-
9
- load_schema
10
-
11
- # if you want to see the statements while running the spec enable the following line
12
- # require 'logger'
13
- # ActiveRecord::Base.logger = Logger.new(STDERR)
14
-
15
- describe "instance methods" do
16
- let(:gate) {Gate.new}
17
-
18
- it "should respond to aasm persistence methods" do
19
- expect(gate).to respond_to(:aasm_read_state)
20
- expect(gate).to respond_to(:aasm_write_state)
21
- expect(gate).to respond_to(:aasm_write_state_without_persistence)
22
- end
23
-
24
- describe "aasm_column_looks_like_enum" do
25
- subject { lambda{ gate.send(:aasm_column_looks_like_enum) } }
26
-
27
- let(:column_name) { "value" }
28
- let(:columns_hash) { Hash[column_name, column] }
29
-
30
- before :each do
31
- allow(gate.class.aasm).to receive(:attribute_name).and_return(column_name.to_sym)
32
- allow(gate.class).to receive(:columns_hash).and_return(columns_hash)
33
- end
34
-
35
- context "when AASM column has integer type" do
36
- let(:column) { double(Object, type: :integer) }
37
-
38
- it "returns true" do
39
- expect(subject.call).to be_truthy
40
- end
41
- end
42
-
43
- context "when AASM column has string type" do
44
- let(:column) { double(Object, type: :string) }
45
-
46
- it "returns false" do
47
- expect(subject.call).to be_falsey
48
- end
49
- end
50
- end
51
-
52
- describe "aasm_guess_enum_method" do
53
- subject { lambda{ gate.send(:aasm_guess_enum_method) } }
54
-
55
- before :each do
56
- allow(gate.class.aasm).to receive(:attribute_name).and_return(:value)
57
- end
58
-
59
- it "pluralizes AASM column name" do
60
- expect(subject.call).to eq :values
61
- end
62
- end
63
-
64
- describe "aasm_enum" do
65
- context "when AASM enum setting contains an explicit enum method name" do
66
- let(:with_enum) { WithEnum.new }
67
-
68
- it "returns whatever value was set in AASM config" do
69
- expect(with_enum.send(:aasm_enum)).to eq :test
70
- end
71
- end
72
-
73
- context "when AASM enum setting is simply set to true" do
74
- let(:with_true_enum) { WithTrueEnum.new }
75
- before :each do
76
- allow(WithTrueEnum.aasm).to receive(:attribute_name).and_return(:value)
77
- end
78
-
79
- it "infers enum method name from pluralized column name" do
80
- expect(with_true_enum.send(:aasm_enum)).to eq :values
81
- end
82
- end
83
-
84
- context "when AASM enum setting is explicitly disabled" do
85
- let(:with_false_enum) { WithFalseEnum.new }
86
-
87
- it "returns nil" do
88
- expect(with_false_enum.send(:aasm_enum)).to be_nil
89
- end
90
- end
91
-
92
- context "when AASM enum setting is not enabled" do
93
- before :each do
94
- allow(Gate.aasm).to receive(:attribute_name).and_return(:value)
95
- end
96
-
97
- context "when AASM column looks like enum" do
98
- before :each do
99
- allow(gate).to receive(:aasm_column_looks_like_enum).and_return(true)
100
- end
101
-
102
- it "infers enum method name from pluralized column name" do
103
- expect(gate.send(:aasm_enum)).to eq :values
104
- end
105
- end
106
-
107
- context "when AASM column doesn't look like enum'" do
108
- before :each do
109
- allow(gate).to receive(:aasm_column_looks_like_enum)
110
- .and_return(false)
111
- end
112
-
113
- it "returns nil, as we're not using enum" do
114
- expect(gate.send(:aasm_enum)).to be_nil
115
- end
116
- end
117
- end
118
-
119
- if ActiveRecord::VERSION::MAJOR >= 4 && ActiveRecord::VERSION::MINOR >= 1 # won't work with Rails <= 4.1
120
- # Enum are introduced from Rails 4.1, therefore enum syntax will not work on Rails <= 4.1
121
- context "when AASM enum setting is not enabled and aasm column not present" do
122
-
123
- let(:with_enum_without_column) {WithEnumWithoutColumn.new}
124
-
125
- it "should raise NoMethodError for transitions" do
126
- expect{with_enum_without_column.send(:view)}.to raise_error(NoMethodError, /undefined method .status./)
127
- end
128
- end
129
-
130
- end
131
-
132
- end
133
-
134
- context "when AASM is configured to use enum" do
135
- let(:state_sym) { :running }
136
- let(:state_code) { 2 }
137
- let(:enum_name) { :states }
138
- let(:enum) { Hash[state_sym, state_code] }
139
-
140
- before :each do
141
- allow(gate).to receive(:aasm_enum).and_return(enum_name)
142
- allow(gate).to receive(:aasm_write_state_attribute)
143
- allow(gate).to receive(:write_attribute)
144
-
145
- allow(Gate).to receive(enum_name).and_return(enum)
146
- end
147
-
148
- describe "aasm_write_state" do
149
- context "when AASM is configured to skip validations on save" do
150
- before :each do
151
- allow(gate).to receive(:aasm_skipping_validations).and_return(true)
152
- end
153
-
154
- it "passes state code instead of state symbol to update_all" do
155
- # stub_chain does not allow us to give expectations on call
156
- # parameters in the middle of the chain, so we need to use
157
- # intermediate object instead.
158
- obj = double(Object, update_all: 1)
159
- allow(Gate).to receive_message_chain(:unscoped, :where).and_return(obj)
160
-
161
- gate.aasm_write_state state_sym
162
-
163
- expect(obj).to have_received(:update_all)
164
- .with(Hash[gate.class.aasm.attribute_name, state_code])
165
- end
166
-
167
- it "searches model outside of default_scope when update_all" do
168
- # stub_chain does not allow us to give expectations on call
169
- # parameters in the middle of the chain, so we need to use
170
- # intermediate object instead.
171
- unscoped = double(Object, update_all: 1)
172
- scoped = double(Object, update_all: 1)
173
-
174
- allow(Gate).to receive(:unscoped).and_return(unscoped)
175
- allow(Gate).to receive(:where).and_return(scoped)
176
- allow(unscoped).to receive(:where).and_return(unscoped)
177
-
178
- gate.aasm_write_state state_sym
179
-
180
- expect(unscoped).to have_received(:update_all)
181
- .with(Hash[gate.class.aasm.attribute_name, state_code])
182
- expect(scoped).to_not have_received(:update_all)
183
- .with(Hash[gate.class.aasm.attribute_name, state_code])
184
- end
185
- end
186
-
187
- context "when AASM is not skipping validations" do
188
- it "delegates state update to the helper method" do
189
- # Let's pretend that validation is passed
190
- allow(gate).to receive(:save).and_return(true)
191
-
192
- gate.aasm_write_state state_sym
193
-
194
- expect(gate).to have_received(:aasm_write_state_attribute).with(state_sym, :default)
195
- expect(gate).to_not have_received :write_attribute
196
- end
197
- end
198
- end
199
-
200
- describe "aasm_write_state_without_persistence" do
201
- it "delegates state update to the helper method" do
202
- gate.aasm_write_state_without_persistence state_sym
203
-
204
- expect(gate).to have_received(:aasm_write_state_attribute).with(state_sym, :default)
205
- expect(gate).to_not have_received :write_attribute
206
- end
207
- end
208
-
209
- describe "aasm_raw_attribute_value" do
210
- it "converts state symbol to state code" do
211
- expect(gate.send(:aasm_raw_attribute_value, state_sym))
212
- .to eq state_code
213
- end
214
- end
215
- end
216
-
217
- context "when AASM is configured to use string field" do
218
- let(:state_sym) { :running }
219
-
220
- before :each do
221
- allow(gate).to receive(:aasm_enum).and_return(nil)
222
- end
223
-
224
- describe "aasm_raw_attribute_value" do
225
- it "converts state symbol to string" do
226
- expect(gate.send(:aasm_raw_attribute_value, state_sym))
227
- .to eq state_sym.to_s
228
- end
229
- end
230
- end
231
-
232
- describe "aasm_write_attribute helper method" do
233
- let(:sym) { :sym }
234
- let(:value) { 42 }
235
-
236
- before :each do
237
- allow(gate).to receive(:write_attribute)
238
- allow(gate).to receive(:aasm_raw_attribute_value).and_return(value)
239
-
240
- gate.send(:aasm_write_state_attribute, sym)
241
- end
242
-
243
- it "generates attribute value using a helper method" do
244
- expect(gate).to have_received(:aasm_raw_attribute_value).with(sym, :default)
245
- end
246
-
247
- it "writes attribute to the model" do
248
- expect(gate).to have_received(:write_attribute).with(:aasm_state, value)
249
- end
250
- end
251
-
252
- it "should return the initial state when new and the aasm field is nil" do
253
- expect(gate.aasm.current_state).to eq(:opened)
254
- end
255
-
256
- it "should return the aasm column when new and the aasm field is not nil" do
257
- gate.aasm_state = "closed"
258
- expect(gate.aasm.current_state).to eq(:closed)
259
- end
260
-
261
- it "should return the aasm column when not new and the aasm.attribute_name is not nil" do
262
- allow(gate).to receive(:new_record?).and_return(false)
263
- gate.aasm_state = "state"
264
- expect(gate.aasm.current_state).to eq(:state)
265
- end
266
-
267
- it "should allow a nil state" do
268
- allow(gate).to receive(:new_record?).and_return(false)
269
- gate.aasm_state = nil
270
- expect(gate.aasm.current_state).to be_nil
271
- end
272
-
273
- context 'on initialization' do
274
- it "should initialize the aasm state" do
275
- expect(Gate.new.aasm_state).to eql 'opened'
276
- expect(Gate.new.aasm.current_state).to eql :opened
277
- end
278
-
279
- it "should not initialize the aasm state if it has not been loaded" do
280
- # we have to create a gate in the database, for which we only want to
281
- # load the id, and not the state
282
- gate = Gate.create!
283
-
284
- # then we just load the gate ids
285
- Gate.select(:id).where(id: gate.id).first
286
- end
287
- end
288
-
289
- end
290
-
291
- if ActiveRecord::VERSION::MAJOR < 4 && ActiveRecord::VERSION::MINOR < 2 # won't work with Rails >= 4.2
292
- describe "direct state column access" do
293
- it "accepts false states" do
294
- f = FalseState.create!
295
- expect(f.aasm_state).to eql false
296
- expect {
297
- f.aasm.events.map(&:name)
298
- }.to_not raise_error
299
- end
300
- end
301
- end
302
-
303
- describe 'subclasses' do
304
- it "should have the same states as its parent class" do
305
- expect(DerivateNewDsl.aasm.states).to eq(SimpleNewDsl.aasm.states)
306
- end
307
-
308
- it "should have the same events as its parent class" do
309
- expect(DerivateNewDsl.aasm.events).to eq(SimpleNewDsl.aasm.events)
310
- end
311
-
312
- it "should have the same column as its parent even for the new dsl" do
313
- expect(SimpleNewDsl.aasm.attribute_name).to eq(:status)
314
- expect(DerivateNewDsl.aasm.attribute_name).to eq(:status)
315
- end
316
- end
317
-
318
- describe "named scopes with the new DSL" do
319
- context "Does not already respond_to? the scope name" do
320
- it "should add a scope for each state" do
321
- expect(SimpleNewDsl).to respond_to(:unknown_scope)
322
- expect(SimpleNewDsl).to respond_to(:another_unknown_scope)
323
-
324
- expect(SimpleNewDsl.unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
325
- expect(SimpleNewDsl.another_unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
326
- end
327
- end
328
-
329
- context "Already respond_to? the scope name" do
330
- it "should not add a scope" do
331
- expect(SimpleNewDsl).to respond_to(:new)
332
- expect(SimpleNewDsl.new.class).to eq(SimpleNewDsl)
333
- end
334
- end
335
-
336
- it "does not create scopes if requested" do
337
- expect(NoScope).not_to respond_to(:pending)
338
- end
339
-
340
- context "result of scope" do
341
- let!(:dsl1) { SimpleNewDsl.create!(status: :new) }
342
- let!(:dsl2) { SimpleNewDsl.create!(status: :unknown_scope) }
343
-
344
- after do
345
- SimpleNewDsl.destroy_all
346
- end
347
-
348
- it "created scope works as where(name: :scope_name)" do
349
- expect(SimpleNewDsl.unknown_scope).to contain_exactly(dsl2)
350
- end
351
- end
352
- end # scopes
353
-
354
- describe "direct assignment" do
355
- it "is allowed by default" do
356
- obj = NoScope.create
357
- expect(obj.aasm_state.to_sym).to eql :pending
358
-
359
- obj.aasm_state = :running
360
- expect(obj.aasm_state.to_sym).to eql :running
361
- end
362
-
363
- it "is forbidden if configured" do
364
- obj = NoDirectAssignment.create
365
- expect(obj.aasm_state.to_sym).to eql :pending
366
-
367
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
368
- expect(obj.aasm_state.to_sym).to eql :pending
369
- end
370
-
371
- it 'can be turned off and on again' do
372
- obj = NoDirectAssignment.create
373
- expect(obj.aasm_state.to_sym).to eql :pending
374
-
375
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
376
- expect(obj.aasm_state.to_sym).to eql :pending
377
-
378
- # allow it temporarily
379
- NoDirectAssignment.aasm.state_machine.config.no_direct_assignment = false
380
- obj.aasm_state = :pending
381
- expect(obj.aasm_state.to_sym).to eql :pending
382
-
383
- # and forbid it again
384
- NoDirectAssignment.aasm.state_machine.config.no_direct_assignment = true
385
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
386
- expect(obj.aasm_state.to_sym).to eql :pending
387
- end
388
- end # direct assignment
389
-
390
- describe 'initial states' do
391
-
392
- it 'should support conditions' do
393
- expect(Thief.new(:skilled => true).aasm.current_state).to eq(:rich)
394
- expect(Thief.new(:skilled => false).aasm.current_state).to eq(:jailed)
395
- end
396
- end
397
-
398
- describe 'transitions with persistence' do
399
-
400
- it "should work for valid models" do
401
- valid_object = Validator.create(:name => 'name')
402
- expect(valid_object).to be_sleeping
403
- valid_object.status = :running
404
- expect(valid_object).to be_running
405
- end
406
-
407
- it 'should not store states for invalid models' do
408
- validator = Validator.create(:name => 'name')
409
- expect(validator).to be_valid
410
- expect(validator).to be_sleeping
411
-
412
- validator.name = nil
413
- expect(validator).not_to be_valid
414
- expect { validator.run! }.to raise_error(ActiveRecord::RecordInvalid)
415
- expect(validator).to be_sleeping
416
-
417
- validator.reload
418
- expect(validator).not_to be_running
419
- expect(validator).to be_sleeping
420
-
421
- validator.name = 'another name'
422
- expect(validator).to be_valid
423
- expect(validator.run!).to be_truthy
424
- expect(validator).to be_running
425
-
426
- validator.reload
427
- expect(validator).to be_running
428
- expect(validator).not_to be_sleeping
429
- end
430
-
431
- it 'should not store states for invalid models silently if configured' do
432
- validator = SilentPersistor.create(:name => 'name')
433
- expect(validator).to be_valid
434
- expect(validator).to be_sleeping
435
-
436
- validator.name = nil
437
- expect(validator).not_to be_valid
438
- expect(validator.run!).to be_falsey
439
- expect(validator).to be_sleeping
440
-
441
- validator.reload
442
- expect(validator).not_to be_running
443
- expect(validator).to be_sleeping
444
-
445
- validator.name = 'another name'
446
- expect(validator).to be_valid
447
- expect(validator.run!).to be_truthy
448
- expect(validator).to be_running
449
-
450
- validator.reload
451
- expect(validator).to be_running
452
- expect(validator).not_to be_sleeping
453
- end
454
-
455
- it 'should store states for invalid models if configured' do
456
- persistor = InvalidPersistor.create(:name => 'name')
457
- expect(persistor).to be_valid
458
- expect(persistor).to be_sleeping
459
-
460
- persistor.name = nil
461
- expect(persistor).not_to be_valid
462
- expect(persistor.run!).to be_truthy
463
- expect(persistor).to be_running
464
-
465
- persistor = InvalidPersistor.find(persistor.id)
466
- persistor.valid?
467
- expect(persistor).to be_valid
468
- expect(persistor).to be_running
469
- expect(persistor).not_to be_sleeping
470
-
471
- persistor.reload
472
- expect(persistor).to be_running
473
- expect(persistor).not_to be_sleeping
474
- end
475
-
476
- describe 'pessimistic locking' do
477
- let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
478
-
479
- subject { transactor.run! }
480
-
481
- context 'no lock' do
482
- let(:transactor) { NoLockTransactor.create!(:name => 'no_lock_transactor', :worker => worker) }
483
-
484
- it 'should not invoke lock!' do
485
- expect(transactor).to_not receive(:lock!)
486
- subject
487
- end
488
- end
489
-
490
- context 'a default lock' do
491
- let(:transactor) { LockTransactor.create!(:name => 'lock_transactor', :worker => worker) }
492
-
493
- it 'should invoke lock! with true' do
494
- expect(transactor).to receive(:lock!).with(true).and_call_original
495
- subject
496
- end
497
- end
498
-
499
- context 'a FOR UPDATE NOWAIT lock' do
500
- let(:transactor) { LockNoWaitTransactor.create!(:name => 'lock_no_wait_transactor', :worker => worker) }
501
-
502
- it 'should invoke lock! with FOR UPDATE NOWAIT' do
503
- expect(transactor).to receive(:lock!).with('FOR UPDATE NOWAIT').and_call_original
504
- subject
505
- end
506
- end
507
- end
508
-
509
- describe 'without transactions' do
510
- let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
511
- let(:no_transactor) { NoTransactor.create!(:name => 'transactor', :worker => worker) }
512
-
513
- it 'should not rollback all changes' do
514
- expect(no_transactor).to be_sleeping
515
- expect(worker.status).to eq('sleeping')
516
-
517
- expect {no_transactor.run!}.to raise_error(StandardError, 'failed on purpose')
518
- expect(no_transactor).to be_running
519
- expect(worker.reload.status).to eq('running')
520
- end
521
- end
522
-
523
- describe 'transactions' do
524
- let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
525
- let(:transactor) { Transactor.create!(:name => 'transactor', :worker => worker) }
526
-
527
- it 'should rollback all changes' do
528
- expect(transactor).to be_sleeping
529
- expect(worker.status).to eq('sleeping')
530
-
531
- expect {transactor.run!}.to raise_error(StandardError, 'failed on purpose')
532
- expect(transactor).to be_running
533
- expect(worker.reload.status).to eq('sleeping')
534
- end
535
-
536
- context "nested transactions" do
537
- it "should rollback all changes in nested transaction" do
538
- expect(transactor).to be_sleeping
539
- expect(worker.status).to eq('sleeping')
540
-
541
- Worker.transaction do
542
- expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
543
- end
544
-
545
- expect(transactor).to be_running
546
- expect(worker.reload.status).to eq('sleeping')
547
- end
548
-
549
- it "should only rollback changes in the main transaction not the nested one" do
550
- # change configuration to not require new transaction
551
- AASM::StateMachineStore[Transactor][:default].config.requires_new_transaction = false
552
-
553
- expect(transactor).to be_sleeping
554
- expect(worker.status).to eq('sleeping')
555
-
556
- Worker.transaction do
557
- expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
558
- end
559
-
560
- expect(transactor).to be_running
561
- expect(worker.reload.status).to eq('running')
562
- end
563
- end
564
-
565
- describe "after_commit callback" do
566
- it "should fire :after_commit if transaction was successful" do
567
- validator = Validator.create(:name => 'name')
568
- expect(validator).to be_sleeping
569
-
570
- validator.run!
571
- expect(validator).to be_running
572
- expect(validator.name).to eq("name changed")
573
-
574
- validator.sleep!("sleeper")
575
- expect(validator).to be_sleeping
576
- expect(validator.name).to eq("sleeper")
577
- end
578
-
579
- it "should not fire :after_commit if transaction failed" do
580
- validator = Validator.create(:name => 'name')
581
- expect { validator.fail! }.to raise_error(StandardError, 'failed on purpose')
582
- expect(validator.name).to eq("name")
583
- end
584
-
585
- it "should not fire :after_commit if validation failed when saving object" do
586
- validator = Validator.create(:name => 'name')
587
- validator.invalid = true
588
- expect { validator.run! }.to raise_error(ActiveRecord::RecordInvalid, 'Invalid record')
589
- expect(validator).to be_sleeping
590
- expect(validator.name).to eq("name")
591
- end
592
-
593
- it "should not fire if not saving" do
594
- validator = Validator.create(:name => 'name')
595
- expect(validator).to be_sleeping
596
- validator.run
597
- expect(validator).to be_running
598
- expect(validator.name).to eq("name")
599
- end
600
- end
601
-
602
- describe 'before and after transaction callbacks' do
603
- [:after, :before].each do |event_type|
604
- describe "#{event_type}_transaction callback" do
605
- it "should fire :#{event_type}_transaction if transaction was successful" do
606
- validator = Validator.create(:name => 'name')
607
- expect(validator).to be_sleeping
608
-
609
- expect { validator.run! }.to change { validator.send("#{event_type}_transaction_performed_on_run") }.from(nil).to(true)
610
- expect(validator).to be_running
611
- end
612
-
613
- it "should fire :#{event_type}_transaction if transaction failed" do
614
- validator = Validator.create(:name => 'name')
615
- expect do
616
- begin
617
- validator.fail!
618
- rescue => ignored
619
- end
620
- end.to change { validator.send("#{event_type}_transaction_performed_on_fail") }.from(nil).to(true)
621
- expect(validator).to_not be_running
622
- end
623
-
624
- it "should not fire :#{event_type}_transaction if not saving" do
625
- validator = Validator.create(:name => 'name')
626
- expect(validator).to be_sleeping
627
- expect { validator.run }.to_not change { validator.send("#{event_type}_transaction_performed_on_run") }
628
- expect(validator).to be_running
629
- expect(validator.name).to eq("name")
630
- end
631
- end
632
- end
633
- end
634
-
635
- describe 'before and after all transactions callbacks' do
636
- [:after, :before].each do |event_type|
637
- describe "#{event_type}_all_transactions callback" do
638
- it "should fire :#{event_type}_all_transactions if transaction was successful" do
639
- validator = Validator.create(:name => 'name')
640
- expect(validator).to be_sleeping
641
-
642
- expect { validator.run! }.to change { validator.send("#{event_type}_all_transactions_performed") }.from(nil).to(true)
643
- expect(validator).to be_running
644
- end
645
-
646
- it "should fire :#{event_type}_all_transactions if transaction failed" do
647
- validator = Validator.create(:name => 'name')
648
- expect do
649
- begin
650
- validator.fail!
651
- rescue => ignored
652
- end
653
- end.to change { validator.send("#{event_type}_all_transactions_performed") }.from(nil).to(true)
654
- expect(validator).to_not be_running
655
- end
656
-
657
- it "should not fire :#{event_type}_all_transactions if not saving" do
658
- validator = Validator.create(:name => 'name')
659
- expect(validator).to be_sleeping
660
- expect { validator.run }.to_not change { validator.send("#{event_type}_all_transactions_performed") }
661
- expect(validator).to be_running
662
- expect(validator.name).to eq("name")
663
- end
664
- end
665
- end
666
- end
667
-
668
- context "when not persisting" do
669
- it 'should not rollback all changes' do
670
- expect(transactor).to be_sleeping
671
- expect(worker.status).to eq('sleeping')
672
-
673
- # Notice here we're calling "run" and not "run!" with a bang.
674
- expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
675
- expect(transactor).to be_running
676
- expect(worker.reload.status).to eq('running')
677
- end
678
-
679
- it 'should not create a database transaction' do
680
- expect(transactor.class).not_to receive(:transaction)
681
- expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
682
- end
683
- end
684
- end
685
- end
686
-
687
- describe "invalid states with persistence" do
688
-
689
- it "should not store states" do
690
- validator = Validator.create(:name => 'name')
691
- validator.status = 'invalid_state'
692
- expect(validator.save).to be_falsey
693
- expect {validator.save!}.to raise_error(ActiveRecord::RecordInvalid)
694
-
695
- validator.reload
696
- expect(validator).to be_sleeping
697
- end
698
-
699
- it "should store invalid states if configured" do
700
- persistor = InvalidPersistor.create(:name => 'name')
701
- persistor.status = 'invalid_state'
702
- expect(persistor.save).to be_truthy
703
-
704
- persistor.reload
705
- expect(persistor.status).to eq('invalid_state')
706
- end
707
-
708
- end
709
-
710
- describe 'basic example with two state machines' do
711
- let(:example) { BasicActiveRecordTwoStateMachinesExample.new }
712
-
713
- it 'should initialise properly' do
714
- expect(example.aasm(:search).current_state).to eql :initialised
715
- expect(example.aasm(:sync).current_state).to eql :unsynced
716
- end
717
- end
718
-
719
- describe 'testing the README examples' do
720
- it 'Usage' do
721
- job = ReadmeJob.new
722
-
723
- expect(job.sleeping?).to eql true
724
- expect(job.may_run?).to eql true
725
-
726
- job.run
727
-
728
- expect(job.running?).to eql true
729
- expect(job.sleeping?).to eql false
730
- expect(job.may_run?).to eql false
731
-
732
- expect { job.run }.to raise_error(AASM::InvalidTransition)
733
- end
734
- end
735
- end