aasm 5.1.1 → 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 (228) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +74 -15
  3. data/lib/aasm/base.rb +44 -12
  4. data/lib/aasm/configuration.rb +3 -0
  5. data/lib/aasm/core/event.rb +12 -6
  6. data/lib/aasm/core/invokers/class_invoker.rb +1 -1
  7. data/lib/aasm/core/invokers/literal_invoker.rb +3 -1
  8. data/lib/aasm/core/state.rb +6 -5
  9. data/lib/aasm/core/transition.rb +1 -1
  10. data/lib/aasm/dsl_helper.rb +24 -22
  11. data/lib/aasm/errors.rb +1 -0
  12. data/lib/aasm/instance_base.rb +14 -3
  13. data/lib/aasm/localizer.rb +13 -3
  14. data/lib/aasm/persistence/active_record_persistence.rb +1 -1
  15. data/lib/aasm/persistence/base.rb +13 -2
  16. data/lib/aasm/version.rb +1 -1
  17. data/lib/generators/aasm/orm_helpers.rb +1 -1
  18. data/lib/generators/active_record/templates/migration.rb +1 -1
  19. metadata +6 -402
  20. data/.document +0 -6
  21. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -27
  22. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  23. data/.gitignore +0 -20
  24. data/.travis.yml +0 -82
  25. data/API +0 -34
  26. data/Appraisals +0 -67
  27. data/CHANGELOG.md +0 -442
  28. data/CODE_OF_CONDUCT.md +0 -13
  29. data/CONTRIBUTING.md +0 -24
  30. data/Dockerfile +0 -44
  31. data/Gemfile +0 -6
  32. data/Gemfile.lock_old +0 -151
  33. data/HOWTO +0 -12
  34. data/PLANNED_CHANGES.md +0 -11
  35. data/README_FROM_VERSION_3_TO_4.md +0 -240
  36. data/Rakefile +0 -31
  37. data/TESTING.md +0 -25
  38. data/aasm.gemspec +0 -37
  39. data/docker-compose.yml +0 -40
  40. data/gemfiles/norails.gemfile +0 -10
  41. data/gemfiles/rails_4.2.gemfile +0 -17
  42. data/gemfiles/rails_4.2_mongoid_5.gemfile +0 -12
  43. data/gemfiles/rails_4.2_nobrainer.gemfile +0 -9
  44. data/gemfiles/rails_5.0.gemfile +0 -14
  45. data/gemfiles/rails_5.0_nobrainer.gemfile +0 -9
  46. data/gemfiles/rails_5.1.gemfile +0 -14
  47. data/gemfiles/rails_5.2.gemfile +0 -14
  48. data/spec/database.rb +0 -59
  49. data/spec/database.yml +0 -3
  50. data/spec/en.yml +0 -9
  51. data/spec/generators/active_record_generator_spec.rb +0 -53
  52. data/spec/generators/mongoid_generator_spec.rb +0 -31
  53. data/spec/generators/no_brainer_generator_spec.rb +0 -29
  54. data/spec/localizer_test_model_deprecated_style.yml +0 -6
  55. data/spec/localizer_test_model_new_style.yml +0 -5
  56. data/spec/models/active_record/active_record_callback.rb +0 -93
  57. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +0 -25
  58. data/spec/models/active_record/complex_active_record_example.rb +0 -37
  59. data/spec/models/active_record/derivate_new_dsl.rb +0 -7
  60. data/spec/models/active_record/false_state.rb +0 -35
  61. data/spec/models/active_record/gate.rb +0 -39
  62. data/spec/models/active_record/instance_level_skip_validation_example.rb +0 -19
  63. data/spec/models/active_record/invalid_persistor.rb +0 -29
  64. data/spec/models/active_record/localizer_test_model.rb +0 -34
  65. data/spec/models/active_record/no_direct_assignment.rb +0 -21
  66. data/spec/models/active_record/no_scope.rb +0 -21
  67. data/spec/models/active_record/persisted_state.rb +0 -12
  68. data/spec/models/active_record/person.rb +0 -23
  69. data/spec/models/active_record/provided_and_persisted_state.rb +0 -24
  70. data/spec/models/active_record/reader.rb +0 -7
  71. data/spec/models/active_record/readme_job.rb +0 -21
  72. data/spec/models/active_record/silent_persistor.rb +0 -29
  73. data/spec/models/active_record/simple_new_dsl.rb +0 -32
  74. data/spec/models/active_record/thief.rb +0 -29
  75. data/spec/models/active_record/transactor.rb +0 -124
  76. data/spec/models/active_record/transient.rb +0 -6
  77. data/spec/models/active_record/validator.rb +0 -118
  78. data/spec/models/active_record/with_enum.rb +0 -39
  79. data/spec/models/active_record/with_enum_without_column.rb +0 -38
  80. data/spec/models/active_record/with_false_enum.rb +0 -31
  81. data/spec/models/active_record/with_true_enum.rb +0 -39
  82. data/spec/models/active_record/work.rb +0 -3
  83. data/spec/models/active_record/worker.rb +0 -2
  84. data/spec/models/active_record/writer.rb +0 -6
  85. data/spec/models/basic_two_state_machines_example.rb +0 -25
  86. data/spec/models/callbacks/basic.rb +0 -98
  87. data/spec/models/callbacks/basic_multiple.rb +0 -75
  88. data/spec/models/callbacks/guard_within_block.rb +0 -67
  89. data/spec/models/callbacks/guard_within_block_multiple.rb +0 -66
  90. data/spec/models/callbacks/multiple_transitions_transition_guard.rb +0 -66
  91. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +0 -65
  92. data/spec/models/callbacks/private_method.rb +0 -44
  93. data/spec/models/callbacks/private_method_multiple.rb +0 -44
  94. data/spec/models/callbacks/with_args.rb +0 -62
  95. data/spec/models/callbacks/with_args_multiple.rb +0 -61
  96. data/spec/models/callbacks/with_state_arg.rb +0 -34
  97. data/spec/models/callbacks/with_state_arg_multiple.rb +0 -29
  98. data/spec/models/complex_example.rb +0 -222
  99. data/spec/models/conversation.rb +0 -93
  100. data/spec/models/default_state.rb +0 -12
  101. data/spec/models/double_definer.rb +0 -21
  102. data/spec/models/dynamoid/complex_dynamoid_example.rb +0 -37
  103. data/spec/models/dynamoid/dynamoid_multiple.rb +0 -18
  104. data/spec/models/dynamoid/dynamoid_simple.rb +0 -18
  105. data/spec/models/foo.rb +0 -106
  106. data/spec/models/foo_callback_multiple.rb +0 -45
  107. data/spec/models/guard_arguments_check.rb +0 -17
  108. data/spec/models/guard_with_params.rb +0 -24
  109. data/spec/models/guard_with_params_multiple.rb +0 -18
  110. data/spec/models/guardian.rb +0 -58
  111. data/spec/models/guardian_multiple.rb +0 -48
  112. data/spec/models/guardian_without_from_specified.rb +0 -18
  113. data/spec/models/initial_state_proc.rb +0 -31
  114. data/spec/models/mongoid/complex_mongoid_example.rb +0 -37
  115. data/spec/models/mongoid/invalid_persistor_mongoid.rb +0 -39
  116. data/spec/models/mongoid/mongoid_relationships.rb +0 -26
  117. data/spec/models/mongoid/no_scope_mongoid.rb +0 -21
  118. data/spec/models/mongoid/silent_persistor_mongoid.rb +0 -39
  119. data/spec/models/mongoid/simple_mongoid.rb +0 -23
  120. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +0 -25
  121. data/spec/models/mongoid/validator_mongoid.rb +0 -100
  122. data/spec/models/multi_transitioner.rb +0 -34
  123. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +0 -31
  124. data/spec/models/namespaced_multiple_example.rb +0 -42
  125. data/spec/models/no_initial_state.rb +0 -25
  126. data/spec/models/nobrainer/complex_no_brainer_example.rb +0 -36
  127. data/spec/models/nobrainer/invalid_persistor_no_brainer.rb +0 -39
  128. data/spec/models/nobrainer/no_scope_no_brainer.rb +0 -21
  129. data/spec/models/nobrainer/nobrainer_relationships.rb +0 -25
  130. data/spec/models/nobrainer/silent_persistor_no_brainer.rb +0 -39
  131. data/spec/models/nobrainer/simple_new_dsl_nobrainer.rb +0 -25
  132. data/spec/models/nobrainer/simple_no_brainer.rb +0 -23
  133. data/spec/models/nobrainer/validator_no_brainer.rb +0 -98
  134. data/spec/models/not_auto_loaded/process.rb +0 -21
  135. data/spec/models/parametrised_event.rb +0 -42
  136. data/spec/models/parametrised_event_multiple.rb +0 -29
  137. data/spec/models/process_with_new_dsl.rb +0 -31
  138. data/spec/models/provided_state.rb +0 -24
  139. data/spec/models/redis/complex_redis_example.rb +0 -40
  140. data/spec/models/redis/redis_multiple.rb +0 -20
  141. data/spec/models/redis/redis_simple.rb +0 -20
  142. data/spec/models/sequel/complex_sequel_example.rb +0 -46
  143. data/spec/models/sequel/invalid_persistor.rb +0 -52
  144. data/spec/models/sequel/sequel_multiple.rb +0 -25
  145. data/spec/models/sequel/sequel_simple.rb +0 -26
  146. data/spec/models/sequel/silent_persistor.rb +0 -50
  147. data/spec/models/sequel/transactor.rb +0 -112
  148. data/spec/models/sequel/validator.rb +0 -93
  149. data/spec/models/sequel/worker.rb +0 -12
  150. data/spec/models/silencer.rb +0 -27
  151. data/spec/models/simple_custom_example.rb +0 -53
  152. data/spec/models/simple_example.rb +0 -23
  153. data/spec/models/simple_example_with_guard_args.rb +0 -17
  154. data/spec/models/simple_multiple_example.rb +0 -42
  155. data/spec/models/state_machine_with_failed_event.rb +0 -20
  156. data/spec/models/states_on_one_line_example.rb +0 -8
  157. data/spec/models/sub_class.rb +0 -41
  158. data/spec/models/sub_class_with_more_states.rb +0 -18
  159. data/spec/models/sub_classing.rb +0 -3
  160. data/spec/models/super_class.rb +0 -46
  161. data/spec/models/this_name_better_not_be_in_use.rb +0 -11
  162. data/spec/models/valid_state_name.rb +0 -23
  163. data/spec/spec_helper.rb +0 -41
  164. data/spec/spec_helpers/active_record.rb +0 -8
  165. data/spec/spec_helpers/dynamoid.rb +0 -35
  166. data/spec/spec_helpers/mongoid.rb +0 -26
  167. data/spec/spec_helpers/nobrainer.rb +0 -15
  168. data/spec/spec_helpers/redis.rb +0 -18
  169. data/spec/spec_helpers/remove_warnings.rb +0 -1
  170. data/spec/spec_helpers/sequel.rb +0 -7
  171. data/spec/unit/abstract_class_spec.rb +0 -27
  172. data/spec/unit/api_spec.rb +0 -104
  173. data/spec/unit/basic_two_state_machines_example_spec.rb +0 -10
  174. data/spec/unit/callback_multiple_spec.rb +0 -304
  175. data/spec/unit/callbacks_spec.rb +0 -521
  176. data/spec/unit/complex_example_spec.rb +0 -93
  177. data/spec/unit/complex_multiple_example_spec.rb +0 -115
  178. data/spec/unit/edge_cases_spec.rb +0 -16
  179. data/spec/unit/event_multiple_spec.rb +0 -73
  180. data/spec/unit/event_naming_spec.rb +0 -16
  181. data/spec/unit/event_spec.rb +0 -394
  182. data/spec/unit/exception_spec.rb +0 -11
  183. data/spec/unit/guard_arguments_check_spec.rb +0 -9
  184. data/spec/unit/guard_multiple_spec.rb +0 -60
  185. data/spec/unit/guard_spec.rb +0 -89
  186. data/spec/unit/guard_with_params_multiple_spec.rb +0 -10
  187. data/spec/unit/guard_with_params_spec.rb +0 -14
  188. data/spec/unit/guard_without_from_specified_spec.rb +0 -10
  189. data/spec/unit/initial_state_multiple_spec.rb +0 -15
  190. data/spec/unit/initial_state_spec.rb +0 -12
  191. data/spec/unit/inspection_multiple_spec.rb +0 -205
  192. data/spec/unit/inspection_spec.rb +0 -153
  193. data/spec/unit/invoker_spec.rb +0 -189
  194. data/spec/unit/invokers/base_invoker_spec.rb +0 -72
  195. data/spec/unit/invokers/class_invoker_spec.rb +0 -95
  196. data/spec/unit/invokers/literal_invoker_spec.rb +0 -86
  197. data/spec/unit/invokers/proc_invoker_spec.rb +0 -86
  198. data/spec/unit/localizer_spec.rb +0 -77
  199. data/spec/unit/memory_leak_spec.rb +0 -38
  200. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +0 -14
  201. data/spec/unit/namespaced_multiple_example_spec.rb +0 -75
  202. data/spec/unit/new_dsl_spec.rb +0 -12
  203. data/spec/unit/override_warning_spec.rb +0 -94
  204. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +0 -618
  205. data/spec/unit/persistence/active_record_persistence_spec.rb +0 -840
  206. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +0 -135
  207. data/spec/unit/persistence/dynamoid_persistence_spec.rb +0 -84
  208. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +0 -200
  209. data/spec/unit/persistence/mongoid_persistence_spec.rb +0 -165
  210. data/spec/unit/persistence/no_brainer_persistence_multiple_spec.rb +0 -198
  211. data/spec/unit/persistence/no_brainer_persistence_spec.rb +0 -158
  212. data/spec/unit/persistence/redis_persistence_multiple_spec.rb +0 -88
  213. data/spec/unit/persistence/redis_persistence_spec.rb +0 -53
  214. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +0 -148
  215. data/spec/unit/persistence/sequel_persistence_spec.rb +0 -368
  216. data/spec/unit/readme_spec.rb +0 -41
  217. data/spec/unit/reloading_spec.rb +0 -15
  218. data/spec/unit/rspec_matcher_spec.rb +0 -88
  219. data/spec/unit/simple_custom_example_spec.rb +0 -39
  220. data/spec/unit/simple_example_spec.rb +0 -57
  221. data/spec/unit/simple_multiple_example_spec.rb +0 -91
  222. data/spec/unit/state_spec.rb +0 -105
  223. data/spec/unit/states_on_one_line_example_spec.rb +0 -16
  224. data/spec/unit/subclassing_multiple_spec.rb +0 -74
  225. data/spec/unit/subclassing_spec.rb +0 -46
  226. data/spec/unit/transition_spec.rb +0 -436
  227. data/test/minitest_helper.rb +0 -57
  228. data/test/unit/minitest_matcher_test.rb +0 -80
@@ -1,840 +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
- # Scopes on abstract classes didn't work until Rails 5.
337
- #
338
- # Reference:
339
- # https://github.com/rails/rails/issues/10658
340
- if ActiveRecord::VERSION::MAJOR >= 5
341
- context "For a descendant of an abstract model" do
342
- it "should add the scope without the table_name" do
343
- expect(ImplementedAbstractClassDsl).to respond_to(:unknown_scope)
344
- expect(ImplementedAbstractClassDsl).to respond_to(:another_unknown_scope)
345
-
346
- expect(ImplementedAbstractClassDsl.unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
347
- expect(ImplementedAbstractClassDsl.another_unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
348
- end
349
- end
350
- end
351
-
352
- it "does not create scopes if requested" do
353
- expect(NoScope).not_to respond_to(:pending)
354
- end
355
-
356
- context "result of scope" do
357
- let!(:dsl1) { SimpleNewDsl.create!(status: :new) }
358
- let!(:dsl2) { SimpleNewDsl.create!(status: :unknown_scope) }
359
-
360
- after do
361
- SimpleNewDsl.destroy_all
362
- end
363
-
364
- it "created scope works as where(name: :scope_name)" do
365
- expect(SimpleNewDsl.unknown_scope).to contain_exactly(dsl2)
366
- end
367
- end
368
- end # scopes
369
-
370
- describe "direct assignment" do
371
- it "is allowed by default" do
372
- obj = NoScope.create
373
- expect(obj.aasm_state.to_sym).to eql :pending
374
-
375
- obj.aasm_state = :running
376
- expect(obj.aasm_state.to_sym).to eql :running
377
- end
378
-
379
- it "is forbidden if configured" do
380
- obj = NoDirectAssignment.create
381
- expect(obj.aasm_state.to_sym).to eql :pending
382
-
383
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
384
- expect(obj.aasm_state.to_sym).to eql :pending
385
- end
386
-
387
- it 'can be turned off and on again' do
388
- obj = NoDirectAssignment.create
389
- expect(obj.aasm_state.to_sym).to eql :pending
390
-
391
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
392
- expect(obj.aasm_state.to_sym).to eql :pending
393
-
394
- # allow it temporarily
395
- NoDirectAssignment.aasm.state_machine.config.no_direct_assignment = false
396
- obj.aasm_state = :running
397
- expect(obj.aasm_state.to_sym).to eql :running
398
-
399
- # and forbid it again
400
- NoDirectAssignment.aasm.state_machine.config.no_direct_assignment = true
401
- expect {obj.aasm_state = :pending}.to raise_error(AASM::NoDirectAssignmentError)
402
- expect(obj.aasm_state.to_sym).to eql :running
403
- end
404
- end # direct assignment
405
-
406
- describe 'initial states' do
407
-
408
- it 'should support conditions' do
409
- expect(Thief.new(:skilled => true).aasm.current_state).to eq(:rich)
410
- expect(Thief.new(:skilled => false).aasm.current_state).to eq(:jailed)
411
- end
412
- end
413
-
414
- describe 'transitions with persistence' do
415
-
416
- it "should work for valid models" do
417
- valid_object = Validator.create(:name => 'name')
418
- expect(valid_object).to be_sleeping
419
- valid_object.status = :running
420
- expect(valid_object).to be_running
421
- end
422
-
423
- it 'should not store states for invalid models' do
424
- validator = Validator.create(:name => 'name')
425
- expect(validator).to be_valid
426
- expect(validator).to be_sleeping
427
-
428
- validator.name = nil
429
- expect(validator).not_to be_valid
430
- expect { validator.run! }.to raise_error(ActiveRecord::RecordInvalid)
431
- expect(validator).to be_sleeping
432
-
433
- validator.reload
434
- expect(validator).not_to be_running
435
- expect(validator).to be_sleeping
436
-
437
- validator.name = 'another name'
438
- expect(validator).to be_valid
439
- expect(validator.run!).to be_truthy
440
- expect(validator).to be_running
441
-
442
- validator.reload
443
- expect(validator).to be_running
444
- expect(validator).not_to be_sleeping
445
- end
446
-
447
- it 'should not store states for invalid models silently if configured' do
448
- validator = SilentPersistor.create(:name => 'name')
449
- expect(validator).to be_valid
450
- expect(validator).to be_sleeping
451
-
452
- validator.name = nil
453
- expect(validator).not_to be_valid
454
- expect(validator.run!).to be_falsey
455
- expect(validator).to be_sleeping
456
-
457
- validator.reload
458
- expect(validator).not_to be_running
459
- expect(validator).to be_sleeping
460
-
461
- validator.name = 'another name'
462
- expect(validator).to be_valid
463
- expect(validator.run!).to be_truthy
464
- expect(validator).to be_running
465
-
466
- validator.reload
467
- expect(validator).to be_running
468
- expect(validator).not_to be_sleeping
469
- end
470
-
471
- it 'should store states for invalid models if configured' do
472
- persistor = InvalidPersistor.create(:name => 'name')
473
- expect(persistor).to be_valid
474
- expect(persistor).to be_sleeping
475
-
476
- persistor.name = nil
477
- expect(persistor).not_to be_valid
478
- expect(persistor.run!).to be_truthy
479
- expect(persistor).to be_running
480
-
481
- persistor = InvalidPersistor.find(persistor.id)
482
- persistor.valid?
483
- expect(persistor).to be_valid
484
- expect(persistor).to be_running
485
- expect(persistor).not_to be_sleeping
486
-
487
- persistor.reload
488
- expect(persistor).to be_running
489
- expect(persistor).not_to be_sleeping
490
- end
491
-
492
- describe 'pessimistic locking' do
493
- let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
494
-
495
- subject { transactor.run! }
496
-
497
- context 'no lock' do
498
- let(:transactor) { NoLockTransactor.create!(:name => 'no_lock_transactor', :worker => worker) }
499
-
500
- it 'should not invoke lock!' do
501
- expect(transactor).to_not receive(:lock!)
502
- subject
503
- end
504
- end
505
-
506
- context 'a default lock' do
507
- let(:transactor) { LockTransactor.create!(:name => 'lock_transactor', :worker => worker) }
508
-
509
- it 'should invoke lock! with true' do
510
- expect(transactor).to receive(:lock!).with(true).and_call_original
511
- subject
512
- end
513
- end
514
-
515
- context 'a FOR UPDATE NOWAIT lock' do
516
- let(:transactor) { LockNoWaitTransactor.create!(:name => 'lock_no_wait_transactor', :worker => worker) }
517
-
518
- it 'should invoke lock! with FOR UPDATE NOWAIT' do
519
- expect(transactor).to receive(:lock!).with('FOR UPDATE NOWAIT').and_call_original
520
- subject
521
- end
522
- end
523
- end
524
-
525
- describe 'without transactions' do
526
- let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
527
- let(:no_transactor) { NoTransactor.create!(:name => 'transactor', :worker => worker) }
528
-
529
- it 'should not rollback all changes' do
530
- expect(no_transactor).to be_sleeping
531
- expect(worker.status).to eq('sleeping')
532
-
533
- expect {no_transactor.run!}.to raise_error(StandardError, 'failed on purpose')
534
- expect(no_transactor).to be_running
535
- expect(worker.reload.status).to eq('running')
536
- end
537
- end
538
-
539
- describe 'transactions' do
540
- let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
541
- let(:transactor) { Transactor.create!(:name => 'transactor', :worker => worker) }
542
-
543
- it 'should rollback all changes' do
544
- expect(transactor).to be_sleeping
545
- expect(worker.status).to eq('sleeping')
546
-
547
- expect {transactor.run!}.to raise_error(StandardError, 'failed on purpose')
548
- expect(transactor).to be_running
549
- expect(worker.reload.status).to eq('sleeping')
550
- end
551
-
552
- context "nested transactions" do
553
- it "should rollback all changes in nested transaction" do
554
- expect(transactor).to be_sleeping
555
- expect(worker.status).to eq('sleeping')
556
-
557
- Worker.transaction do
558
- expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
559
- end
560
-
561
- expect(transactor).to be_running
562
- expect(worker.reload.status).to eq('sleeping')
563
- end
564
-
565
- it "should only rollback changes in the main transaction not the nested one" do
566
- # change configuration to not require new transaction
567
- AASM::StateMachineStore[Transactor][:default].config.requires_new_transaction = false
568
-
569
- expect(transactor).to be_sleeping
570
- expect(worker.status).to eq('sleeping')
571
-
572
- Worker.transaction do
573
- expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
574
- end
575
-
576
- expect(transactor).to be_running
577
- expect(worker.reload.status).to eq('running')
578
- end
579
- end
580
-
581
- describe "after_commit callback" do
582
- it "should fire :after_commit if transaction was successful" do
583
- validator = Validator.create(:name => 'name')
584
- expect(validator).to be_sleeping
585
-
586
- validator.run!
587
- expect(validator).to be_running
588
- expect(validator.name).to eq("name changed")
589
-
590
- validator.sleep!("sleeper")
591
- expect(validator).to be_sleeping
592
- expect(validator.name).to eq("sleeper")
593
- end
594
-
595
- it "should not fire :after_commit if transaction failed" do
596
- validator = Validator.create(:name => 'name')
597
- expect { validator.fail! }.to raise_error(StandardError, 'failed on purpose')
598
- expect(validator.name).to eq("name")
599
- end
600
-
601
- it "should not fire :after_commit if validation failed when saving object" do
602
- validator = Validator.create(:name => 'name')
603
- validator.invalid = true
604
- expect { validator.run! }.to raise_error(ActiveRecord::RecordInvalid, 'Invalid record')
605
- expect(validator).to be_sleeping
606
- expect(validator.name).to eq("name")
607
- end
608
-
609
- it "should not fire if not saving" do
610
- validator = Validator.create(:name => 'name')
611
- expect(validator).to be_sleeping
612
- validator.run
613
- expect(validator).to be_running
614
- expect(validator.name).to eq("name")
615
- end
616
-
617
- context "nested transaction" do
618
- it "should fire :after_commit if root transaction was successful" do
619
- validator = Validator.create(:name => 'name')
620
- expect(validator).to be_sleeping
621
-
622
- validator.transaction do
623
- validator.run!
624
- expect(validator.name).to eq("name")
625
- expect(validator).to be_running
626
- end
627
-
628
- expect(validator.name).to eq("name changed")
629
- expect(validator.reload).to be_running
630
- end
631
-
632
- it "should not fire :after_commit if root transaction failed" do
633
- validator = Validator.create(:name => 'name')
634
- expect(validator).to be_sleeping
635
-
636
- validator.transaction do
637
- validator.run!
638
- expect(validator.name).to eq("name")
639
- expect(validator).to be_running
640
-
641
- raise ActiveRecord::Rollback, "failed on purpose"
642
- end
643
-
644
- expect(validator.name).to eq("name")
645
- expect(validator.reload).to be_sleeping
646
- end
647
- end
648
- end
649
-
650
- describe 'callbacks for the new DSL' do
651
-
652
- it "be called in order" do
653
- show_debug_log = false
654
-
655
- callback = ActiveRecordCallback.create
656
- callback.aasm.current_state
657
-
658
- unless show_debug_log
659
- expect(callback).to receive(:before_all_events).once.ordered
660
- expect(callback).to receive(:before_event).once.ordered
661
- expect(callback).to receive(:event_guard).once.ordered.and_return(true)
662
- expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
663
- expect(callback).to receive(:before_exit_open).once.ordered # these should be before the state changes
664
- expect(callback).to receive(:exit_open).once.ordered
665
- # expect(callback).to receive(:event_guard).once.ordered.and_return(true)
666
- # expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
667
- expect(callback).to receive(:after_all_transitions).once.ordered
668
- expect(callback).to receive(:after_transition).once.ordered
669
- expect(callback).to receive(:before_enter_closed).once.ordered
670
- expect(callback).to receive(:enter_closed).once.ordered
671
- expect(callback).to receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
672
- expect(callback).to receive(:after_exit_open).once.ordered # these should be after the state changes
673
- expect(callback).to receive(:after_enter_closed).once.ordered
674
- expect(callback).to receive(:after_event).once.ordered
675
- expect(callback).to receive(:after_all_events).once.ordered
676
- expect(callback).to receive(:ensure_event).once.ordered
677
- expect(callback).to receive(:ensure_on_all_events).once.ordered
678
- expect(callback).to receive(:event_after_commit).once.ordered
679
- end
680
-
681
- callback.close!
682
- end
683
- end
684
-
685
- describe 'before and after transaction callbacks' do
686
- [:after, :before].each do |event_type|
687
- describe "#{event_type}_transaction callback" do
688
- it "should fire :#{event_type}_transaction if transaction was successful" do
689
- validator = Validator.create(:name => 'name')
690
- expect(validator).to be_sleeping
691
-
692
- expect { validator.run! }.to change { validator.send("#{event_type}_transaction_performed_on_run") }.from(nil).to(true)
693
- expect(validator).to be_running
694
- end
695
-
696
- it "should fire :#{event_type}_transaction if transaction failed" do
697
- validator = Validator.create(:name => 'name')
698
- expect do
699
- begin
700
- validator.fail!
701
- rescue => ignored
702
- end
703
- end.to change { validator.send("#{event_type}_transaction_performed_on_fail") }.from(nil).to(true)
704
- expect(validator).to_not be_running
705
- end
706
-
707
- it "should not fire :#{event_type}_transaction if not saving" do
708
- validator = Validator.create(:name => 'name')
709
- expect(validator).to be_sleeping
710
- expect { validator.run }.to_not change { validator.send("#{event_type}_transaction_performed_on_run") }
711
- expect(validator).to be_running
712
- expect(validator.name).to eq("name")
713
- end
714
- end
715
- end
716
- end
717
-
718
- describe 'before and after all transactions callbacks' do
719
- [:after, :before].each do |event_type|
720
- describe "#{event_type}_all_transactions callback" do
721
- it "should fire :#{event_type}_all_transactions if transaction was successful" do
722
- validator = Validator.create(:name => 'name')
723
- expect(validator).to be_sleeping
724
-
725
- expect { validator.run! }.to change { validator.send("#{event_type}_all_transactions_performed") }.from(nil).to(true)
726
- expect(validator).to be_running
727
- end
728
-
729
- it "should fire :#{event_type}_all_transactions if transaction failed" do
730
- validator = Validator.create(:name => 'name')
731
- expect do
732
- begin
733
- validator.fail!
734
- rescue => ignored
735
- end
736
- end.to change { validator.send("#{event_type}_all_transactions_performed") }.from(nil).to(true)
737
- expect(validator).to_not be_running
738
- end
739
-
740
- it "should not fire :#{event_type}_all_transactions if not saving" do
741
- validator = Validator.create(:name => 'name')
742
- expect(validator).to be_sleeping
743
- expect { validator.run }.to_not change { validator.send("#{event_type}_all_transactions_performed") }
744
- expect(validator).to be_running
745
- expect(validator.name).to eq("name")
746
- end
747
- end
748
- end
749
- end
750
-
751
- context "when not persisting" do
752
- it 'should not rollback all changes' do
753
- expect(transactor).to be_sleeping
754
- expect(worker.status).to eq('sleeping')
755
-
756
- # Notice here we're calling "run" and not "run!" with a bang.
757
- expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
758
- expect(transactor).to be_running
759
- expect(worker.reload.status).to eq('running')
760
- end
761
-
762
- it 'should not create a database transaction' do
763
- expect(transactor.class).not_to receive(:transaction)
764
- expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
765
- end
766
- end
767
- end
768
- end
769
-
770
- describe "invalid states with persistence" do
771
-
772
- it "should not store states" do
773
- validator = Validator.create(:name => 'name')
774
- validator.status = 'invalid_state'
775
- expect(validator.save).to be_falsey
776
- expect {validator.save!}.to raise_error(ActiveRecord::RecordInvalid)
777
-
778
- validator.reload
779
- expect(validator).to be_sleeping
780
- end
781
-
782
- it "should store invalid states if configured" do
783
- persistor = InvalidPersistor.create(:name => 'name')
784
- persistor.status = 'invalid_state'
785
- expect(persistor.save).to be_truthy
786
-
787
- persistor.reload
788
- expect(persistor.status).to eq('invalid_state')
789
- end
790
-
791
- end
792
-
793
- describe 'basic example with two state machines' do
794
- let(:example) { BasicActiveRecordTwoStateMachinesExample.new }
795
-
796
- it 'should initialise properly' do
797
- expect(example.aasm(:search).current_state).to eql :initialised
798
- expect(example.aasm(:sync).current_state).to eql :unsynced
799
- end
800
- end
801
-
802
- describe 'testing the README examples' do
803
- it 'Usage' do
804
- job = ReadmeJob.new
805
-
806
- expect(job.sleeping?).to eql true
807
- expect(job.may_run?).to eql true
808
-
809
- job.run
810
-
811
- expect(job.running?).to eql true
812
- expect(job.sleeping?).to eql false
813
- expect(job.may_run?).to eql false
814
-
815
- expect { job.run }.to raise_error(AASM::InvalidTransition)
816
- end
817
- end
818
-
819
- describe 'testing the instance_level skip validation with _without_validation method' do
820
- let(:example) do
821
- obj = InstanceLevelSkipValidationExample.new(state: 'new')
822
- obj.save(validate: false)
823
- obj
824
- end
825
-
826
- it 'should be able to change the state with invalid record' do
827
- expect(example.valid?).to be_falsey
828
- expect(example.complete!).to be_falsey
829
- expect(example.complete_without_validation!).to be_truthy
830
- expect(example.state).to eq('complete')
831
- end
832
-
833
- it 'shouldn\'t affect the behaviour of existing method after calling _without_validation! method' do
834
- expect(example.set_draft!).to be_falsey
835
- expect(example.set_draft_without_validation!).to be_truthy
836
- expect(example.state).to eq('draft')
837
- expect(example.complete!).to be_falsey
838
- end
839
- end
840
- end