aasm 4.11.0 → 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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +16 -17
  3. data/Appraisals +44 -0
  4. data/CHANGELOG.md +24 -1
  5. data/CONTRIBUTING.md +24 -0
  6. data/Gemfile +4 -21
  7. data/README.md +81 -34
  8. data/Rakefile +6 -1
  9. data/TESTING.md +25 -0
  10. data/aasm.gemspec +5 -2
  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 +19 -9
  20. data/lib/aasm/core/state.rb +7 -0
  21. data/lib/aasm/core/transition.rb +9 -0
  22. data/lib/aasm/instance_base.rb +8 -8
  23. data/lib/aasm/persistence/active_record_persistence.rb +1 -1
  24. data/lib/aasm/persistence/base.rb +3 -3
  25. data/lib/aasm/persistence/mongoid_persistence.rb +48 -9
  26. data/lib/aasm/persistence.rb +0 -3
  27. data/lib/aasm/state_machine.rb +4 -2
  28. data/lib/aasm/state_machine_store.rb +5 -2
  29. data/lib/aasm/version.rb +1 -1
  30. data/lib/generators/active_record/aasm_generator.rb +1 -1
  31. data/lib/motion-aasm.rb +0 -1
  32. data/spec/en.yml +3 -0
  33. data/spec/generators/active_record_generator_spec.rb +42 -34
  34. data/spec/generators/mongoid_generator_spec.rb +4 -6
  35. data/spec/models/{invalid_persistor.rb → active_record/invalid_persistor.rb} +0 -2
  36. data/spec/models/{silent_persistor.rb → active_record/silent_persistor.rb} +0 -2
  37. data/spec/models/active_record/simple_new_dsl.rb +2 -2
  38. data/spec/models/{transactor.rb → active_record/transactor.rb} +0 -2
  39. data/spec/models/{validator.rb → active_record/validator.rb} +6 -3
  40. data/spec/models/callbacks/basic.rb +5 -2
  41. data/spec/models/guard_with_params.rb +24 -0
  42. data/spec/models/guard_with_params_multiple.rb +18 -0
  43. data/spec/models/mongoid/invalid_persistor_mongoid.rb +39 -0
  44. data/spec/models/mongoid/silent_persistor_mongoid.rb +39 -0
  45. data/spec/models/mongoid/simple_mongoid.rb +2 -2
  46. data/spec/models/mongoid/validator_mongoid.rb +100 -0
  47. data/spec/models/multi_transitioner.rb +10 -0
  48. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +31 -0
  49. data/spec/models/parametrised_event.rb +7 -0
  50. data/spec/models/simple_multiple_example.rb +12 -0
  51. data/spec/models/sub_class.rb +34 -0
  52. data/spec/spec_helper.rb +0 -33
  53. data/spec/spec_helpers/active_record.rb +7 -0
  54. data/spec/spec_helpers/dynamoid.rb +33 -0
  55. data/spec/spec_helpers/mongoid.rb +7 -0
  56. data/spec/spec_helpers/redis.rb +7 -0
  57. data/spec/spec_helpers/remove_warnings.rb +1 -0
  58. data/spec/spec_helpers/sequel.rb +7 -0
  59. data/spec/unit/api_spec.rb +76 -73
  60. data/spec/unit/callbacks_spec.rb +5 -0
  61. data/spec/unit/event_spec.rb +12 -0
  62. data/spec/unit/guard_with_params_multiple_spec.rb +10 -0
  63. data/spec/unit/guard_with_params_spec.rb +14 -0
  64. data/spec/unit/inspection_spec.rb +5 -0
  65. data/spec/unit/localizer_spec.rb +55 -53
  66. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +14 -0
  67. data/spec/unit/override_warning_spec.rb +8 -0
  68. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +452 -445
  69. data/spec/unit/persistence/active_record_persistence_spec.rb +523 -490
  70. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +4 -9
  71. data/spec/unit/persistence/dynamoid_persistence_spec.rb +4 -9
  72. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +87 -10
  73. data/spec/unit/persistence/mongoid_persistence_spec.rb +89 -10
  74. data/spec/unit/persistence/redis_persistence_spec.rb +3 -7
  75. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +4 -9
  76. data/spec/unit/persistence/sequel_persistence_spec.rb +4 -9
  77. data/spec/unit/simple_multiple_example_spec.rb +28 -0
  78. data/spec/unit/subclassing_multiple_spec.rb +37 -2
  79. data/spec/unit/subclassing_spec.rb +17 -2
  80. metadata +77 -32
  81. data/gemfiles/rails_3.2_stable.gemfile +0 -15
  82. data/gemfiles/rails_4.0_mongo_mapper.gemfile +0 -17
  83. data/gemfiles/rails_4.2_mongo_mapper.gemfile +0 -18
  84. data/lib/aasm/persistence/mongo_mapper_persistence.rb +0 -163
  85. data/spec/models/mongo_mapper/complex_mongo_mapper_example.rb +0 -37
  86. data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +0 -21
  87. data/spec/models/mongo_mapper/simple_mongo_mapper.rb +0 -23
  88. data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +0 -25
  89. data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +0 -146
  90. data/spec/unit/persistence/mongo_mapper_persistence_spec.rb +0 -93
  91. /data/spec/models/{worker.rb → active_record/worker.rb} +0 -0
@@ -1,688 +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
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)
46
33
  end
47
- end
48
- end
49
34
 
50
- describe "aasm_guess_enum_method" do
51
- subject { lambda{ gate.send(:aasm_guess_enum_method) } }
35
+ context "when AASM column has integer type" do
36
+ let(:column) { double(Object, type: :integer) }
52
37
 
53
- before :each do
54
- allow(gate.class.aasm).to receive(:attribute_name).and_return(:value)
55
- end
56
-
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 }
84
-
85
- it "returns nil" do
86
- expect(with_false_enum.send(:aasm_enum)).to be_nil
87
- end
88
- end
64
+ describe "aasm_enum" do
65
+ context "when AASM enum setting contains an explicit enum method name" do
66
+ let(:with_enum) { WithEnum.new }
89
67
 
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
-
211
- describe "aasm_write_attribute helper method" do
212
- let(:sym) { :sym }
213
- let(:value) { 42 }
214
242
 
215
- before :each do
216
- allow(gate).to receive(:write_attribute)
217
- allow(gate).to receive(:aasm_raw_attribute_value).and_return(value)
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
218
246
 
219
- gate.send(:aasm_write_attribute, sym)
247
+ it "writes attribute to the model" do
248
+ expect(gate).to have_received(:write_attribute).with(:aasm_state, value)
249
+ end
220
250
  end
221
251
 
222
- it "generates attribute value using a helper method" do
223
- expect(gate).to have_received(:aasm_raw_attribute_value).with(sym, :default)
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)
224
254
  end
225
255
 
226
- it "writes attribute to the model" do
227
- expect(gate).to have_received(:write_attribute).with(:aasm_state, value)
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)
228
259
  end
229
- end
230
260
 
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
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
234
266
 
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
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
239
272
 
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
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
245
278
 
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
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!
251
283
 
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
301
+ end
267
302
 
268
- 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
269
307
 
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
- end
279
- end
280
- 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
281
311
 
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)
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
285
316
  end
286
317
 
287
- it "should have the same events as its parent class" do
288
- expect(DerivateNewDsl.aasm.events).to eq(SimpleNewDsl.aasm.events)
289
- end
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)
290
323
 
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)
294
- end
295
- end
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
296
328
 
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" do
300
- expect(SimpleNewDsl).to respond_to(:unknown_scope)
301
- expect(SimpleNewDsl.unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
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
302
334
  end
303
- end
304
335
 
305
- context "Already respond_to? the scope name" do
306
- it "should not add a scope" do
307
- expect(SimpleNewDsl).to respond_to(:new)
308
- expect(SimpleNewDsl.new.class).to eq(SimpleNewDsl)
336
+ it "does not create scopes if requested" do
337
+ expect(NoScope).not_to respond_to(:pending)
309
338
  end
310
- end
311
339
 
312
- it "does not create scopes if requested" do
313
- expect(NoScope).not_to respond_to(:pending)
314
- end
340
+ context "result of scope" do
341
+ let!(:dsl1) { SimpleNewDsl.create!(status: :new) }
342
+ let!(:dsl2) { SimpleNewDsl.create!(status: :unknown_scope) }
315
343
 
316
- context "result of scope" do
317
- let!(:dsl1) { SimpleNewDsl.create!(status: :new) }
318
- let!(:dsl2) { SimpleNewDsl.create!(status: :unknown_scope) }
344
+ after do
345
+ SimpleNewDsl.destroy_all
346
+ end
319
347
 
320
- after do
321
- SimpleNewDsl.destroy_all
348
+ it "created scope works as where(name: :scope_name)" do
349
+ expect(SimpleNewDsl.unknown_scope).to contain_exactly(dsl2)
350
+ end
322
351
  end
352
+ end # scopes
323
353
 
324
- it "created scope works as where(name: :scope_name)" do
325
- expect(SimpleNewDsl.unknown_scope).to contain_exactly(dsl2)
354
+ describe "direct assignment" do
355
+ it "is allowed by default" do
356
+ obj = NoScope.create
357
+ expect(obj.aasm_state.to_sym).to eql :pending
358
+
359
+ obj.aasm_state = :running
360
+ expect(obj.aasm_state.to_sym).to eql :running
326
361
  end
327
- end
328
- end # scopes
329
362
 
330
- describe "direct assignment" do
331
- it "is allowed by default" do
332
- obj = NoScope.create
333
- 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
334
366
 
335
- obj.aasm_state = :running
336
- expect(obj.aasm_state.to_sym).to eql :running
337
- end
367
+ expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
368
+ expect(obj.aasm_state.to_sym).to eql :pending
369
+ end
338
370
 
339
- it "is forbidden if configured" do
340
- obj = NoDirectAssignment.create
341
- 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
342
374
 
343
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
344
- expect(obj.aasm_state.to_sym).to eql :pending
345
- end
375
+ expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
376
+ expect(obj.aasm_state.to_sym).to eql :pending
346
377
 
347
- it 'can be turned off and on again' do
348
- obj = NoDirectAssignment.create
349
- 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
350
382
 
351
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
352
- 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
353
389
 
354
- # allow it temporarily
355
- NoDirectAssignment.aasm.state_machine.config.no_direct_assignment = false
356
- obj.aasm_state = :pending
357
- expect(obj.aasm_state.to_sym).to eql :pending
390
+ describe 'initial states' do
358
391
 
359
- # and forbid it again
360
- NoDirectAssignment.aasm.state_machine.config.no_direct_assignment = true
361
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
362
- 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
363
396
  end
364
- end # direct assignment
365
397
 
366
- describe 'initial states' do
398
+ describe 'transitions with persistence' do
367
399
 
368
- it 'should support conditions' do
369
- expect(Thief.new(:skilled => true).aasm.current_state).to eq(:rich)
370
- expect(Thief.new(:skilled => false).aasm.current_state).to eq(:jailed)
371
- end
372
- 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
373
406
 
374
- 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
375
411
 
376
- it "should work for valid models" do
377
- valid_object = Validator.create(:name => 'name')
378
- expect(valid_object).to be_sleeping
379
- valid_object.status = :running
380
- expect(valid_object).to be_running
381
- 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
382
416
 
383
- it 'should not store states for invalid models' do
384
- validator = Validator.create(:name => 'name')
385
- expect(validator).to be_valid
386
- expect(validator).to be_sleeping
417
+ validator.reload
418
+ expect(validator).not_to be_running
419
+ expect(validator).to be_sleeping
387
420
 
388
- validator.name = nil
389
- expect(validator).not_to be_valid
390
- expect { validator.run! }.to raise_error(ActiveRecord::RecordInvalid)
391
- 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
392
425
 
393
- validator.reload
394
- expect(validator).not_to be_running
395
- expect(validator).to be_sleeping
426
+ validator.reload
427
+ expect(validator).to be_running
428
+ expect(validator).not_to be_sleeping
429
+ end
396
430
 
397
- validator.name = 'another name'
398
- expect(validator).to be_valid
399
- expect(validator.run!).to be_truthy
400
- 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
401
435
 
402
- validator.reload
403
- expect(validator).to be_running
404
- expect(validator).not_to be_sleeping
405
- 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
406
440
 
407
- it 'should not store states for invalid models silently if configured' do
408
- validator = SilentPersistor.create(:name => 'name')
409
- expect(validator).to be_valid
410
- expect(validator).to be_sleeping
441
+ validator.reload
442
+ expect(validator).not_to be_running
443
+ expect(validator).to be_sleeping
411
444
 
412
- validator.name = nil
413
- expect(validator).not_to be_valid
414
- expect(validator.run!).to be_falsey
415
- 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
416
449
 
417
- validator.reload
418
- expect(validator).not_to be_running
419
- expect(validator).to be_sleeping
450
+ validator.reload
451
+ expect(validator).to be_running
452
+ expect(validator).not_to be_sleeping
453
+ end
420
454
 
421
- validator.name = 'another name'
422
- expect(validator).to be_valid
423
- expect(validator.run!).to be_truthy
424
- 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
425
459
 
426
- validator.reload
427
- expect(validator).to be_running
428
- expect(validator).not_to be_sleeping
429
- 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
430
464
 
431
- it 'should store states for invalid models if configured' do
432
- persistor = InvalidPersistor.create(:name => 'name')
433
- expect(persistor).to be_valid
434
- expect(persistor).to be_sleeping
435
-
436
- persistor.name = nil
437
- expect(persistor).not_to be_valid
438
- expect(persistor.run!).to be_truthy
439
- expect(persistor).to be_running
440
-
441
- persistor = InvalidPersistor.find(persistor.id)
442
- persistor.valid?
443
- expect(persistor).to be_valid
444
- expect(persistor).to be_running
445
- expect(persistor).not_to be_sleeping
446
-
447
- persistor.reload
448
- expect(persistor).to be_running
449
- expect(persistor).not_to be_sleeping
450
- 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
470
+
471
+ persistor.reload
472
+ expect(persistor).to be_running
473
+ expect(persistor).not_to be_sleeping
474
+ end
451
475
 
452
- describe 'pessimistic locking' do
453
- let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
476
+ describe 'pessimistic locking' do
477
+ let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
454
478
 
455
- subject { transactor.run! }
479
+ subject { transactor.run! }
456
480
 
457
- context 'no lock' do
458
- let(:transactor) { NoLockTransactor.create!(:name => 'no_lock_transactor', :worker => worker) }
481
+ context 'no lock' do
482
+ let(:transactor) { NoLockTransactor.create!(:name => 'no_lock_transactor', :worker => worker) }
459
483
 
460
- it 'should not invoke lock!' do
461
- expect(transactor).to_not receive(:lock!)
462
- subject
484
+ it 'should not invoke lock!' do
485
+ expect(transactor).to_not receive(:lock!)
486
+ subject
487
+ end
463
488
  end
464
- end
465
489
 
466
- context 'a default lock' do
467
- 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) }
468
492
 
469
- it 'should invoke lock! with true' do
470
- expect(transactor).to receive(:lock!).with(true).and_call_original
471
- subject
493
+ it 'should invoke lock! with true' do
494
+ expect(transactor).to receive(:lock!).with(true).and_call_original
495
+ subject
496
+ end
472
497
  end
473
- end
474
498
 
475
- context 'a FOR UPDATE NOWAIT lock' do
476
- 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) }
477
501
 
478
- it 'should invoke lock! with FOR UPDATE NOWAIT' do
479
- expect(transactor).to receive(:lock!).with('FOR UPDATE NOWAIT').and_call_original
480
- 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
481
506
  end
482
507
  end
483
- end
484
-
485
- describe 'transactions' do
486
- let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
487
- let(:transactor) { Transactor.create!(:name => 'transactor', :worker => worker) }
488
508
 
489
- it 'should rollback all changes' do
490
- expect(transactor).to be_sleeping
491
- expect(worker.status).to eq('sleeping')
509
+ describe 'transactions' do
510
+ let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
511
+ let(:transactor) { Transactor.create!(:name => 'transactor', :worker => worker) }
492
512
 
493
- expect {transactor.run!}.to raise_error(StandardError, 'failed on purpose')
494
- expect(transactor).to be_running
495
- expect(worker.reload.status).to eq('sleeping')
496
- end
497
-
498
- context "nested transactions" do
499
- it "should rollback all changes in nested transaction" do
513
+ it 'should rollback all changes' do
500
514
  expect(transactor).to be_sleeping
501
515
  expect(worker.status).to eq('sleeping')
502
516
 
503
- Worker.transaction do
504
- expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
505
- end
506
-
517
+ expect {transactor.run!}.to raise_error(StandardError, 'failed on purpose')
507
518
  expect(transactor).to be_running
508
519
  expect(worker.reload.status).to eq('sleeping')
509
520
  end
510
521
 
511
- it "should only rollback changes in the main transaction not the nested one" do
512
- # change configuration to not require new transaction
513
- 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')
514
526
 
515
- expect(transactor).to be_sleeping
516
- expect(worker.status).to eq('sleeping')
527
+ Worker.transaction do
528
+ expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
529
+ end
517
530
 
518
- Worker.transaction do
519
- expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
531
+ expect(transactor).to be_running
532
+ expect(worker.reload.status).to eq('sleeping')
520
533
  end
521
534
 
522
- expect(transactor).to be_running
523
- expect(worker.reload.status).to eq('running')
524
- end
525
- 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
526
538
 
527
- describe "after_commit callback" do
528
- it "should fire :after_commit if transaction was successful" do
529
- validator = Validator.create(:name => 'name')
530
- expect(validator).to be_sleeping
539
+ expect(transactor).to be_sleeping
540
+ expect(worker.status).to eq('sleeping')
531
541
 
532
- validator.run!
533
- expect(validator).to be_running
534
- expect(validator.name).to eq("name changed")
542
+ Worker.transaction do
543
+ expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
544
+ end
535
545
 
536
- validator.sleep!("sleeper")
537
- expect(validator).to be_sleeping
538
- expect(validator.name).to eq("sleeper")
546
+ expect(transactor).to be_running
547
+ expect(worker.reload.status).to eq('running')
548
+ end
539
549
  end
540
550
 
541
- it "should not fire :after_commit if transaction failed" do
542
- validator = Validator.create(:name => 'name')
543
- expect { validator.fail! }.to raise_error(StandardError, 'failed on purpose')
544
- expect(validator.name).to eq("name")
545
- 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
546
555
 
547
- it "should not fire if not saving" do
548
- validator = Validator.create(:name => 'name')
549
- expect(validator).to be_sleeping
550
- validator.run
551
- expect(validator).to be_running
552
- expect(validator.name).to eq("name")
553
- end
554
- end
556
+ validator.run!
557
+ expect(validator).to be_running
558
+ expect(validator.name).to eq("name changed")
555
559
 
556
- describe 'before and after transaction callbacks' do
557
- [:after, :before].each do |event_type|
558
- describe "#{event_type}_transaction callback" do
559
- it "should fire :#{event_type}_transaction if transaction was successful" do
560
- validator = Validator.create(:name => 'name')
561
- expect(validator).to be_sleeping
560
+ validator.sleep!("sleeper")
561
+ expect(validator).to be_sleeping
562
+ expect(validator.name).to eq("sleeper")
563
+ end
562
564
 
563
- expect { validator.run! }.to change { validator.send("#{event_type}_transaction_performed_on_run") }.from(nil).to(true)
564
- expect(validator).to be_running
565
- 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
566
570
 
567
- it "should fire :#{event_type}_transaction if transaction failed" do
568
- validator = Validator.create(:name => 'name')
569
- expect do
570
- begin
571
- validator.fail!
572
- rescue => ignored
573
- end
574
- end.to change { validator.send("#{event_type}_transaction_performed_on_fail") }.from(nil).to(true)
575
- expect(validator).to_not be_running
576
- 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
577
578
 
578
- it "should not fire :#{event_type}_transaction if not saving" do
579
- validator = Validator.create(:name => 'name')
580
- expect(validator).to be_sleeping
581
- expect { validator.run }.to_not change { validator.send("#{event_type}_transaction_performed_on_run") }
582
- expect(validator).to be_running
583
- expect(validator.name).to eq("name")
584
- 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")
585
585
  end
586
586
  end
587
- end
588
587
 
589
- describe 'before and after all transactions callbacks' do
590
- [:after, :before].each do |event_type|
591
- describe "#{event_type}_all_transactions callback" do
592
- it "should fire :#{event_type}_all_transactions if transaction was successful" do
593
- validator = Validator.create(:name => 'name')
594
- expect(validator).to be_sleeping
595
-
596
- expect { validator.run! }.to change { validator.send("#{event_type}_all_transactions_performed") }.from(nil).to(true)
597
- expect(validator).to be_running
598
- end
599
-
600
- it "should fire :#{event_type}_all_transactions if transaction failed" do
601
- validator = Validator.create(:name => 'name')
602
- expect do
603
- begin
604
- validator.fail!
605
- rescue => ignored
606
- end
607
- end.to change { validator.send("#{event_type}_all_transactions_performed") }.from(nil).to(true)
608
- 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
609
617
  end
618
+ end
619
+ end
610
620
 
611
- it "should not fire :#{event_type}_all_transactions if not saving" do
612
- validator = Validator.create(:name => 'name')
613
- expect(validator).to be_sleeping
614
- expect { validator.run }.to_not change { validator.send("#{event_type}_all_transactions_performed") }
615
- expect(validator).to be_running
616
- 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
617
650
  end
618
651
  end
619
652
  end
620
- end
621
653
 
622
- context "when not persisting" do
623
- it 'should not rollback all changes' do
624
- expect(transactor).to be_sleeping
625
- 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')
626
658
 
627
- # Notice here we're calling "run" and not "run!" with a bang.
628
- expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
629
- expect(transactor).to be_running
630
- expect(worker.reload.status).to eq('running')
631
- 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
632
664
 
633
- it 'should not create a database transaction' do
634
- expect(transactor.class).not_to receive(:transaction)
635
- 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
636
669
  end
637
670
  end
638
671
  end
639
- end
640
672
 
641
- describe "invalid states with persistence" do
673
+ describe "invalid states with persistence" do
642
674
 
643
- it "should not store states" do
644
- validator = Validator.create(:name => 'name')
645
- validator.status = 'invalid_state'
646
- expect(validator.save).to be_falsey
647
- 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)
648
680
 
649
- validator.reload
650
- expect(validator).to be_sleeping
651
- end
681
+ validator.reload
682
+ expect(validator).to be_sleeping
683
+ end
652
684
 
653
- it "should store invalid states if configured" do
654
- persistor = InvalidPersistor.create(:name => 'name')
655
- persistor.status = 'invalid_state'
656
- 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
657
689
 
658
- persistor.reload
659
- expect(persistor.status).to eq('invalid_state')
660
- end
690
+ persistor.reload
691
+ expect(persistor.status).to eq('invalid_state')
692
+ end
661
693
 
662
- end
694
+ end
663
695
 
664
- describe 'basic example with two state machines' do
665
- let(:example) { BasicActiveRecordTwoStateMachinesExample.new }
696
+ describe 'basic example with two state machines' do
697
+ let(:example) { BasicActiveRecordTwoStateMachinesExample.new }
666
698
 
667
- it 'should initialise properly' do
668
- expect(example.aasm(:search).current_state).to eql :initialised
669
- 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
670
703
  end
671
- end
672
704
 
673
- describe 'testing the README examples' do
674
- it 'Usage' do
675
- job = ReadmeJob.new
705
+ describe 'testing the README examples' do
706
+ it 'Usage' do
707
+ job = ReadmeJob.new
676
708
 
677
- expect(job.sleeping?).to eql true
678
- expect(job.may_run?).to eql true
709
+ expect(job.sleeping?).to eql true
710
+ expect(job.may_run?).to eql true
679
711
 
680
- job.run
712
+ job.run
681
713
 
682
- expect(job.running?).to eql true
683
- expect(job.sleeping?).to eql false
684
- 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
685
717
 
686
- expect { job.run }.to raise_error(AASM::InvalidTransition)
718
+ expect { job.run }.to raise_error(AASM::InvalidTransition)
719
+ end
687
720
  end
688
721
  end