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