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,618 +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) {MultipleGate.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, :left) } }
26
-
27
- let(:column_name) { "value" }
28
- let(:columns_hash) { Hash[column_name, column] }
29
-
30
- before :each do
31
- allow(gate.class.aasm(:left)).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, :left) } }
54
-
55
- before :each do
56
- allow(gate.class.aasm(:left)).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) { MultipleWithEnum.new }
67
-
68
- it "returns whatever value was set in AASM config" do
69
- expect(with_enum.send(:aasm_enum, :left)).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) { MultipleWithTrueEnum.new }
75
- before :each do
76
- allow(MultipleWithTrueEnum.aasm(:left)).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, :left)).to eq :values
81
- end
82
- end
83
-
84
- context "when AASM enum setting is explicitly disabled" do
85
- let(:with_false_enum) { MultipleWithFalseEnum.new }
86
-
87
- it "returns nil" do
88
- expect(with_false_enum.send(:aasm_enum, :left)).to be_nil
89
- end
90
- end
91
-
92
- context "when AASM enum setting is not enabled" do
93
- before :each do
94
- allow(MultipleGate.aasm(:left)).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).with(:left).and_return(true)
100
- end
101
-
102
- it "infers enum method name from pluralized column name" do
103
- expect(gate.send(:aasm_enum, :left)).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, :left)).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(:multiple_with_enum_without_column) {MultipleWithEnumWithoutColumn.new}
124
-
125
- it "should raise NoMethodError for transitions" do
126
- expect{multiple_with_enum_without_column.send(:view, :left)}.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(MultipleGate).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(MultipleGate).to receive_message_chain(:unscoped, :where)
160
- .and_return(obj)
161
-
162
- gate.aasm_write_state state_sym, :left
163
-
164
- expect(obj).to have_received(:update_all)
165
- .with(Hash[gate.class.aasm(:left).attribute_name, state_code])
166
- end
167
- end
168
-
169
- context "when AASM is not skipping validations" do
170
- it "delegates state update to the helper method" do
171
- # Let's pretend that validation is passed
172
- allow(gate).to receive(:save).and_return(true)
173
-
174
- gate.aasm_write_state state_sym, :left
175
-
176
- expect(gate).to have_received(:aasm_write_state_attribute).with(state_sym, :left)
177
- expect(gate).to_not have_received :write_attribute
178
- end
179
- end
180
- end
181
-
182
- describe "aasm_write_state_without_persistence" do
183
- it "delegates state update to the helper method" do
184
- gate.aasm_write_state_without_persistence state_sym, :left
185
-
186
- expect(gate).to have_received(:aasm_write_state_attribute).with(state_sym, :left)
187
- expect(gate).to_not have_received :write_attribute
188
- end
189
- end
190
-
191
- describe "aasm_raw_attribute_value" do
192
- it "converts state symbol to state code" do
193
- expect(gate.send(:aasm_raw_attribute_value, state_sym))
194
- .to eq state_code
195
- end
196
- end
197
- end
198
-
199
- context "when AASM is configured to use string field" do
200
- let(:state_sym) { :running }
201
-
202
- before :each do
203
- allow(gate).to receive(:aasm_enum).and_return(nil)
204
- end
205
-
206
- describe "aasm_raw_attribute_value" do
207
- it "converts state symbol to string" do
208
- expect(gate.send(:aasm_raw_attribute_value, state_sym))
209
- .to eq state_sym.to_s
210
- end
211
- end
212
- end
213
-
214
- describe "aasm_write_attribute helper method" do
215
- let(:sym) { :sym }
216
- let(:value) { 42 }
217
-
218
- before :each do
219
- allow(gate).to receive(:write_attribute)
220
- allow(gate).to receive(:aasm_raw_attribute_value).and_return(value)
221
-
222
- gate.send(:aasm_write_state_attribute, sym, :left)
223
- end
224
-
225
- it "generates attribute value using a helper method" do
226
- expect(gate).to have_received(:aasm_raw_attribute_value).with(sym, :left)
227
- end
228
-
229
- it "writes attribute to the model" do
230
- expect(gate).to have_received(:write_attribute).with(:aasm_state, value)
231
- end
232
- end
233
-
234
- it "should return the initial state when new and the aasm field is nil" do
235
- expect(gate.aasm(:left).current_state).to eq(:opened)
236
- end
237
-
238
- it "should return the aasm column when new and the aasm field is not nil" do
239
- gate.aasm_state = "closed"
240
- expect(gate.aasm(:left).current_state).to eq(:closed)
241
- end
242
-
243
- it "should return the aasm column when not new and the aasm.attribute_name is not nil" do
244
- allow(gate).to receive(:new_record?).and_return(false)
245
- gate.aasm_state = "state"
246
- expect(gate.aasm(:left).current_state).to eq(:state)
247
- end
248
-
249
- it "should allow a nil state" do
250
- allow(gate).to receive(:new_record?).and_return(false)
251
- gate.aasm_state = nil
252
- expect(gate.aasm(:left).current_state).to be_nil
253
- end
254
-
255
- context 'on initialization' do
256
- it "should initialize the aasm state" do
257
- expect(MultipleGate.new.aasm_state).to eql 'opened'
258
- expect(MultipleGate.new.aasm(:left).current_state).to eql :opened
259
- end
260
-
261
- it "should not initialize the aasm state if it has not been loaded" do
262
- # we have to create a gate in the database, for which we only want to
263
- # load the id, and not the state
264
- gate = MultipleGate.create!
265
-
266
- # then we just load the gate ids
267
- MultipleGate.select(:id).where(id: gate.id).first
268
- end
269
- end
270
-
271
- end
272
-
273
- if ActiveRecord::VERSION::MAJOR < 4 && ActiveRecord::VERSION::MINOR < 2 # won't work with Rails >= 4.2
274
- describe "direct state column access" do
275
- it "accepts false states" do
276
- f = MultipleFalseState.create!
277
- expect(f.aasm_state).to eql false
278
- expect {
279
- f.aasm(:left).events.map(&:name)
280
- }.to_not raise_error
281
- end
282
- end
283
- end
284
-
285
- describe 'subclasses' do
286
- it "should have the same states as its parent class" do
287
- expect(MultipleDerivateNewDsl.aasm(:left).states).to eq(MultipleSimpleNewDsl.aasm(:left).states)
288
- end
289
-
290
- it "should have the same events as its parent class" do
291
- expect(MultipleDerivateNewDsl.aasm(:left).events).to eq(MultipleSimpleNewDsl.aasm(:left).events)
292
- end
293
-
294
- it "should have the same column as its parent even for the new dsl" do
295
- expect(MultipleSimpleNewDsl.aasm(:left).attribute_name).to eq(:status)
296
- expect(MultipleDerivateNewDsl.aasm(:left).attribute_name).to eq(:status)
297
- end
298
- end
299
-
300
- describe "named scopes with the new DSL" do
301
- context "Does not already respond_to? the scope name" do
302
- it "should add a scope for each state" do
303
- expect(MultipleSimpleNewDsl).to respond_to(:unknown_scope)
304
- expect(MultipleSimpleNewDsl).to respond_to(:another_unknown_scope)
305
-
306
- expect(MultipleSimpleNewDsl.unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
307
- expect(MultipleSimpleNewDsl.another_unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
308
- end
309
- end
310
-
311
- context "Already respond_to? the scope name" do
312
- it "should not add a scope" do
313
- expect(MultipleSimpleNewDsl).to respond_to(:new)
314
- expect(MultipleSimpleNewDsl.new.class).to eq(MultipleSimpleNewDsl)
315
- end
316
- end
317
-
318
- it "does not create scopes if requested" do
319
- expect(MultipleNoScope).not_to respond_to(:pending)
320
- end
321
-
322
- context "result of scope" do
323
- let!(:dsl1) { MultipleSimpleNewDsl.create!(status: :new) }
324
- let!(:dsl2) { MultipleSimpleNewDsl.create!(status: :unknown_scope) }
325
-
326
- after do
327
- MultipleSimpleNewDsl.destroy_all
328
- end
329
-
330
- it "created scope works as where(name: :scope_name)" do
331
- expect(MultipleSimpleNewDsl.unknown_scope).to contain_exactly(dsl2)
332
- end
333
- end
334
- end # scopes
335
-
336
- describe "direct assignment" do
337
- it "is allowed by default" do
338
- obj = MultipleNoScope.create
339
- expect(obj.aasm_state.to_sym).to eql :pending
340
-
341
- obj.aasm_state = :running
342
- expect(obj.aasm_state.to_sym).to eql :running
343
- end
344
-
345
- it "is forbidden if configured" do
346
- obj = MultipleNoDirectAssignment.create
347
- expect(obj.aasm_state.to_sym).to eql :pending
348
-
349
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
350
- expect(obj.aasm_state.to_sym).to eql :pending
351
- end
352
-
353
- it 'can be turned off and on again' do
354
- obj = MultipleNoDirectAssignment.create
355
- expect(obj.aasm_state.to_sym).to eql :pending
356
-
357
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
358
- expect(obj.aasm_state.to_sym).to eql :pending
359
-
360
- # allow it temporarily
361
- MultipleNoDirectAssignment.aasm(:left).state_machine.config.no_direct_assignment = false
362
- obj.aasm_state = :pending
363
- expect(obj.aasm_state.to_sym).to eql :pending
364
-
365
- # and forbid it again
366
- MultipleNoDirectAssignment.aasm(:left).state_machine.config.no_direct_assignment = true
367
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
368
- expect(obj.aasm_state.to_sym).to eql :pending
369
- end
370
- end # direct assignment
371
-
372
- describe 'initial states' do
373
- it 'should support conditions' do
374
- expect(MultipleThief.new(:skilled => true).aasm(:left).current_state).to eq(:rich)
375
- expect(MultipleThief.new(:skilled => false).aasm(:left).current_state).to eq(:jailed)
376
- end
377
- end
378
-
379
- describe 'transitions with persistence' do
380
-
381
- it "should work for valid models" do
382
- valid_object = MultipleValidator.create(:name => 'name')
383
- expect(valid_object).to be_sleeping
384
- valid_object.status = :running
385
- expect(valid_object).to be_running
386
- end
387
-
388
- it 'should not store states for invalid models' do
389
- validator = MultipleValidator.create(:name => 'name')
390
- expect(validator).to be_valid
391
- expect(validator).to be_sleeping
392
-
393
- validator.name = nil
394
- expect(validator).not_to be_valid
395
- expect { validator.run! }.to raise_error(ActiveRecord::RecordInvalid)
396
- expect(validator).to be_sleeping
397
-
398
- validator.reload
399
- expect(validator).not_to be_running
400
- expect(validator).to be_sleeping
401
-
402
- validator.name = 'another name'
403
- expect(validator).to be_valid
404
- expect(validator.run!).to be_truthy
405
- expect(validator).to be_running
406
-
407
- validator.reload
408
- expect(validator).to be_running
409
- expect(validator).not_to be_sleeping
410
- end
411
-
412
- it 'should not store states for invalid models silently if configured' do
413
- validator = MultipleSilentPersistor.create(:name => 'name')
414
- expect(validator).to be_valid
415
- expect(validator).to be_sleeping
416
-
417
- validator.name = nil
418
- expect(validator).not_to be_valid
419
- expect(validator.run!).to be_falsey
420
- expect(validator).to be_sleeping
421
-
422
- validator.reload
423
- expect(validator).not_to be_running
424
- expect(validator).to be_sleeping
425
-
426
- validator.name = 'another name'
427
- expect(validator).to be_valid
428
- expect(validator.run!).to be_truthy
429
- expect(validator).to be_running
430
-
431
- validator.reload
432
- expect(validator).to be_running
433
- expect(validator).not_to be_sleeping
434
- end
435
-
436
- it 'should store states for invalid models if configured' do
437
- persistor = MultipleInvalidPersistor.create(:name => 'name')
438
- expect(persistor).to be_valid
439
- expect(persistor).to be_sleeping
440
-
441
- persistor.name = nil
442
- expect(persistor).not_to be_valid
443
- expect(persistor.run!).to be_truthy
444
- expect(persistor).to be_running
445
-
446
- persistor = MultipleInvalidPersistor.find(persistor.id)
447
- persistor.valid?
448
- expect(persistor).to be_valid
449
- expect(persistor).to be_running
450
- expect(persistor).not_to be_sleeping
451
-
452
- persistor.reload
453
- expect(persistor).to be_running
454
- expect(persistor).not_to be_sleeping
455
- end
456
-
457
- describe 'transactions' do
458
- let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
459
- let(:transactor) { MultipleTransactor.create!(:name => 'transactor', :worker => worker) }
460
-
461
- it 'should rollback all changes' do
462
- expect(transactor).to be_sleeping
463
- expect(worker.status).to eq('sleeping')
464
-
465
- expect {transactor.run!}.to raise_error(StandardError, 'failed on purpose')
466
- expect(transactor).to be_running
467
- expect(worker.reload.status).to eq('sleeping')
468
- end
469
-
470
- context "nested transactions" do
471
- it "should rollback all changes in nested transaction" do
472
- expect(transactor).to be_sleeping
473
- expect(worker.status).to eq('sleeping')
474
-
475
- Worker.transaction do
476
- expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
477
- end
478
-
479
- expect(transactor).to be_running
480
- expect(worker.reload.status).to eq('sleeping')
481
- end
482
-
483
- it "should only rollback changes in the main transaction not the nested one" do
484
- # change configuration to not require new transaction
485
- AASM::StateMachineStore[MultipleTransactor][:left].config.requires_new_transaction = false
486
-
487
- expect(transactor).to be_sleeping
488
- expect(worker.status).to eq('sleeping')
489
-
490
- Worker.transaction do
491
- expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
492
- end
493
-
494
- expect(transactor).to be_running
495
- expect(worker.reload.status).to eq('running')
496
- end
497
- end
498
-
499
- describe "after_commit callback" do
500
- it "should fire :after_commit if transaction was successful" do
501
- validator = MultipleValidator.create(:name => 'name')
502
- expect(validator).to be_sleeping
503
-
504
- validator.run!
505
- expect(validator).to be_running
506
- expect(validator.name).to eq("name changed")
507
-
508
- validator.sleep!("sleeper")
509
- expect(validator).to be_sleeping
510
- expect(validator.name).to eq("sleeper")
511
- end
512
-
513
- it "should not fire :after_commit if transaction failed" do
514
- validator = MultipleValidator.create(:name => 'name')
515
- expect { validator.fail! }.to raise_error(StandardError, 'failed on purpose')
516
- expect(validator.name).to eq("name")
517
- end
518
-
519
- it "should not fire if not saving" do
520
- validator = MultipleValidator.create(:name => 'name')
521
- expect(validator).to be_sleeping
522
- validator.run
523
- expect(validator).to be_running
524
- expect(validator.name).to eq("name")
525
- end
526
-
527
- end
528
-
529
- context "when not persisting" do
530
- it 'should not rollback all changes' do
531
- expect(transactor).to be_sleeping
532
- expect(worker.status).to eq('sleeping')
533
-
534
- # Notice here we're calling "run" and not "run!" with a bang.
535
- expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
536
- expect(transactor).to be_running
537
- expect(worker.reload.status).to eq('running')
538
- end
539
-
540
- it 'should not create a database transaction' do
541
- expect(transactor.class).not_to receive(:transaction)
542
- expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
543
- end
544
- end
545
- end
546
- end
547
-
548
- describe "invalid states with persistence" do
549
- it "should not store states" do
550
- validator = MultipleValidator.create(:name => 'name')
551
- validator.status = 'invalid_state'
552
- expect(validator.save).to be_falsey
553
- expect {validator.save!}.to raise_error(ActiveRecord::RecordInvalid)
554
-
555
- validator.reload
556
- expect(validator).to be_sleeping
557
- end
558
-
559
- it "should store invalid states if configured" do
560
- persistor = MultipleInvalidPersistor.create(:name => 'name')
561
- persistor.status = 'invalid_state'
562
- expect(persistor.save).to be_truthy
563
-
564
- persistor.reload
565
- expect(persistor.status).to eq('invalid_state')
566
- end
567
- end
568
-
569
- describe "complex example" do
570
- it "works" do
571
- record = ComplexActiveRecordExample.new
572
- expect_aasm_states record, :one, :alpha
573
-
574
- record.save!
575
- expect_aasm_states record, :one, :alpha
576
- record.reload
577
- expect_aasm_states record, :one, :alpha
578
-
579
- record.increment!
580
- expect_aasm_states record, :two, :alpha
581
- record.reload
582
- expect_aasm_states record, :two, :alpha
583
-
584
- record.level_up!
585
- expect_aasm_states record, :two, :beta
586
- record.reload
587
- expect_aasm_states record, :two, :beta
588
-
589
- record.increment!
590
- expect { record.increment! }.to raise_error(AASM::InvalidTransition)
591
- expect_aasm_states record, :three, :beta
592
- record.reload
593
- expect_aasm_states record, :three, :beta
594
-
595
- record.level_up!
596
- expect_aasm_states record, :three, :gamma
597
- record.reload
598
- expect_aasm_states record, :three, :gamma
599
-
600
- record.level_down # without saving
601
- expect_aasm_states record, :three, :beta
602
- record.reload
603
- expect_aasm_states record, :three, :gamma
604
-
605
- record.level_down # without saving
606
- expect_aasm_states record, :three, :beta
607
- record.reset!
608
- expect_aasm_states record, :one, :beta
609
- end
610
-
611
- def expect_aasm_states(record, left_state, right_state)
612
- expect(record.aasm(:left).current_state).to eql left_state.to_sym
613
- expect(record.left).to eql left_state.to_s
614
- expect(record.aasm(:right).current_state).to eql right_state.to_sym
615
- expect(record.right).to eql right_state.to_s
616
- end
617
- end
618
- end