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