aasm 3.2.1 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +34 -0
- data/lib/aasm/base.rb +2 -0
- data/lib/aasm/persistence/active_record_persistence.rb +37 -4
- data/lib/aasm/persistence/base.rb +1 -5
- data/lib/aasm/version.rb +1 -1
- data/spec/unit/persistence/active_record_persistence_spec.rb +221 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 402286c5cd8a9288380d837b7faeb96429a5d5e0
|
4
|
+
data.tar.gz: 45868b7761fa2ed0ffc42d7ab0c7ef637e52a668
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5d7c42efeb5438ba6693008b2f92c9cffdcdced9982f550091e2c12b8f756d233a0d6ddb9f6517c9754bf8204c8e7ecdd96da4e9a6209b7bc3df1fd1e35c109
|
7
|
+
data.tar.gz: dd23c1b785e7e917334ce577cd56412c1e1f6a6a30105edf827ab89296c9e1e77394a3762aeff67996401a8fbc887240a7a21ecd86ab178157fefd792accb670
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,11 @@
|
|
4
4
|
|
5
5
|
* deprecated old aasm_* class methods (old-style DSL), in preparation for AASM v4.0.0
|
6
6
|
|
7
|
+
## 3.3.0 (not yet released)
|
8
|
+
|
9
|
+
* support for Rails 4.1 enum fields (see [issue #124](https://github.com/aasm/aasm/issues/124), thanks to [@bkon](https://github.com/bkon))
|
10
|
+
* bugfix: allow lazy-evaluation for Rails 3 scopes (see [issue #144](https://github.com/aasm/aasm/issues/144), thanks to [@laurens](https://github.com/laurens))
|
11
|
+
|
7
12
|
## 3.2.1
|
8
13
|
|
9
14
|
* bugfix: permissible_events and events did not contain events with an empty "from" transition (see [issue #140](https://github.com/aasm/aasm/issues/140) and [issue #141](https://github.com/aasm/aasm/issues/141), thanks to [@daniel-rikowski](https://github.com/daniel-rikowski))
|
data/README.md
CHANGED
@@ -278,6 +278,40 @@ class Job < ActiveRecord::Base
|
|
278
278
|
end
|
279
279
|
```
|
280
280
|
|
281
|
+
#### ActiveRecord enums
|
282
|
+
|
283
|
+
You can use
|
284
|
+
[enumerations](http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html)
|
285
|
+
in Rails 4.1+ for your state column:
|
286
|
+
|
287
|
+
```ruby
|
288
|
+
class Job < ActiveRecord::Base
|
289
|
+
include AASM
|
290
|
+
|
291
|
+
enum state {
|
292
|
+
sleeping: 5,
|
293
|
+
running: 99
|
294
|
+
}
|
295
|
+
|
296
|
+
aasm :column => :state, :enum => true do
|
297
|
+
state :sleeping, :initial => true
|
298
|
+
state :running
|
299
|
+
end
|
300
|
+
end
|
301
|
+
```
|
302
|
+
|
303
|
+
You can explicitly pass the name of the method which provides access
|
304
|
+
to the enumeration mapping as a value of ```enum```, or you can simply
|
305
|
+
set it to ```true```. In the latter case AASM will try to use
|
306
|
+
pluralized column name to access possible enum states.
|
307
|
+
|
308
|
+
Furthermore, if your column has integer type (which is normally the
|
309
|
+
case when you're working with Rails enums), you can omit ```:enum```
|
310
|
+
setting --- AASM auto-detects this situation and enabled enum
|
311
|
+
support. If anything goes wrong, you can disable enum functionality
|
312
|
+
and fall back to the default behavior by setting ```:enum```
|
313
|
+
to ```false```.
|
314
|
+
|
281
315
|
### Sequel
|
282
316
|
|
283
317
|
AASM also supports [Sequel](http://sequel.jeremyevans.net/) besides _ActiveRecord_ and _Mongoid_.
|
data/lib/aasm/base.rb
CHANGED
@@ -85,10 +85,11 @@ module AASM
|
|
85
85
|
# NOTE: intended to be called from an event
|
86
86
|
def aasm_write_state(state)
|
87
87
|
old_value = read_attribute(self.class.aasm_column)
|
88
|
-
|
88
|
+
aasm_write_attribute state
|
89
89
|
|
90
|
-
success = if
|
91
|
-
|
90
|
+
success = if aasm_skipping_validations
|
91
|
+
value = aasm_raw_attribute_value state
|
92
|
+
self.class.where(self.class.primary_key => self.id).update_all(self.class.aasm_column => value) == 1
|
92
93
|
else
|
93
94
|
self.save
|
94
95
|
end
|
@@ -113,10 +114,42 @@ module AASM
|
|
113
114
|
#
|
114
115
|
# NOTE: intended to be called from an event
|
115
116
|
def aasm_write_state_without_persistence(state)
|
116
|
-
|
117
|
+
aasm_write_attribute state
|
117
118
|
end
|
118
119
|
|
119
120
|
private
|
121
|
+
def aasm_enum
|
122
|
+
case AASM::StateMachine[self.class].config.enum
|
123
|
+
when false then nil
|
124
|
+
when true then aasm_guess_enum_method
|
125
|
+
when nil then aasm_guess_enum_method if aasm_column_looks_like_enum
|
126
|
+
else AASM::StateMachine[self.class].config.enum
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def aasm_column_looks_like_enum
|
131
|
+
self.class.columns_hash[self.class.aasm_column.to_s].type == :integer
|
132
|
+
end
|
133
|
+
|
134
|
+
def aasm_guess_enum_method
|
135
|
+
self.class.aasm_column.to_s.pluralize.to_sym
|
136
|
+
end
|
137
|
+
|
138
|
+
def aasm_skipping_validations
|
139
|
+
AASM::StateMachine[self.class].config.skip_validation_on_save
|
140
|
+
end
|
141
|
+
|
142
|
+
def aasm_write_attribute(state)
|
143
|
+
write_attribute self.class.aasm_column, aasm_raw_attribute_value(state)
|
144
|
+
end
|
145
|
+
|
146
|
+
def aasm_raw_attribute_value(state)
|
147
|
+
if aasm_enum
|
148
|
+
value = self.class.send(aasm_enum)[state]
|
149
|
+
else
|
150
|
+
value = state.to_s
|
151
|
+
end
|
152
|
+
end
|
120
153
|
|
121
154
|
# Ensures that if the aasm_state column is nil and the record is new
|
122
155
|
# that the initial state gets populated before validation on create
|
@@ -91,14 +91,10 @@ module AASM
|
|
91
91
|
if @klass.ancestors.map {|klass| klass.to_s}.include?("ActiveRecord::Base")
|
92
92
|
|
93
93
|
conditions = {"#{@klass.table_name}.#{@klass.aasm_column}" => name.to_s}
|
94
|
-
if ActiveRecord::VERSION::MAJOR >=
|
94
|
+
if ActiveRecord::VERSION::MAJOR >= 3
|
95
95
|
@klass.class_eval do
|
96
96
|
scope name, lambda { where(conditions) }
|
97
97
|
end
|
98
|
-
elsif ActiveRecord::VERSION::MAJOR >= 3
|
99
|
-
@klass.class_eval do
|
100
|
-
scope name, where(conditions)
|
101
|
-
end
|
102
98
|
else
|
103
99
|
@klass.class_eval do
|
104
100
|
named_scope name, :conditions => conditions
|
data/lib/aasm/version.rb
CHANGED
@@ -23,6 +23,227 @@ describe "instance methods" do
|
|
23
23
|
expect(gate).to respond_to(:aasm_write_state_without_persistence)
|
24
24
|
end
|
25
25
|
|
26
|
+
describe "aasm_column_looks_like_enum" do
|
27
|
+
subject { lambda{ gate.send(:aasm_column_looks_like_enum) } }
|
28
|
+
|
29
|
+
let(:column_name) { "value" }
|
30
|
+
let(:columns_hash) { Hash[column_name, column] }
|
31
|
+
|
32
|
+
before :each do
|
33
|
+
gate.class.stub(:aasm_column).and_return(column_name.to_sym)
|
34
|
+
gate.class.stub(:columns_hash).and_return(columns_hash)
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when AASM column has integer type" do
|
38
|
+
let(:column) { double(Object, type: :integer) }
|
39
|
+
|
40
|
+
it "returns true" do
|
41
|
+
expect(subject.call).to be_true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when AASM column has string type" do
|
46
|
+
let(:column) { double(Object, type: :string) }
|
47
|
+
|
48
|
+
it "returns false" do
|
49
|
+
expect(subject.call).to be_false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "aasm_guess_enum_method" do
|
55
|
+
subject { lambda{ gate.send(:aasm_guess_enum_method) } }
|
56
|
+
|
57
|
+
before :each do
|
58
|
+
gate.class.stub(:aasm_column).and_return(:value)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "pluralizes AASM column name" do
|
62
|
+
expect(subject.call).to eq :values
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "aasm_enum" do
|
67
|
+
subject { lambda{ gate.send(:aasm_enum) } }
|
68
|
+
|
69
|
+
context "when AASM enum setting contains an explicit enum method name" do
|
70
|
+
let(:enum) { :test }
|
71
|
+
|
72
|
+
before :each do
|
73
|
+
AASM::StateMachine[Gate].config.stub(:enum).and_return(enum)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returns whatever value was set in AASM config" do
|
77
|
+
expect(subject.call).to eq enum
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "when AASM enum setting is simply set to true" do
|
82
|
+
before :each do
|
83
|
+
AASM::StateMachine[Gate].config.stub(:enum).and_return(true)
|
84
|
+
Gate.stub(:aasm_column).and_return(:value)
|
85
|
+
gate.stub(:aasm_guess_enum_method).and_return(:values)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "infers enum method name from pluralized column name" do
|
89
|
+
expect(subject.call).to eq :values
|
90
|
+
expect(gate).to have_received :aasm_guess_enum_method
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "when AASM enum setting is explicitly disabled" do
|
95
|
+
before :each do
|
96
|
+
AASM::StateMachine[Gate].config.stub(:enum).and_return(false)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "returns nil" do
|
100
|
+
expect(subject.call).to be_nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "when AASM enum setting is not enabled" do
|
105
|
+
before :each do
|
106
|
+
AASM::StateMachine[Gate].config.stub(:enum).and_return(nil)
|
107
|
+
Gate.stub(:aasm_column).and_return(:value)
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when AASM column looks like enum" do
|
111
|
+
before :each do
|
112
|
+
gate.stub(:aasm_column_looks_like_enum).and_return(true)
|
113
|
+
gate.stub(:aasm_guess_enum_method).and_return(:values)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "infers enum method name from pluralized column name" do
|
117
|
+
expect(subject.call).to eq :values
|
118
|
+
expect(gate).to have_received :aasm_guess_enum_method
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "when AASM column doesn't look like enum'" do
|
123
|
+
before :each do
|
124
|
+
gate.stub(:aasm_column_looks_like_enum)
|
125
|
+
.and_return(false)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "returns nil, as we're not using enum" do
|
129
|
+
expect(subject.call).to be_nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "when AASM is configured to use enum" do
|
136
|
+
let(:state_sym) { :running }
|
137
|
+
let(:state_code) { 2 }
|
138
|
+
let(:enum_name) { :states }
|
139
|
+
let(:enum) { Hash[state_sym, state_code] }
|
140
|
+
|
141
|
+
before :each do
|
142
|
+
gate
|
143
|
+
.stub(:aasm_enum)
|
144
|
+
.and_return(enum_name)
|
145
|
+
gate.stub(:aasm_write_attribute)
|
146
|
+
gate.stub(:write_attribute)
|
147
|
+
|
148
|
+
gate
|
149
|
+
.class
|
150
|
+
.stub(enum_name)
|
151
|
+
.and_return(enum)
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "aasm_write_state" do
|
155
|
+
context "when AASM is configured to skip validations on save" do
|
156
|
+
before :each do
|
157
|
+
gate
|
158
|
+
.stub(:aasm_skipping_validations)
|
159
|
+
.and_return(true)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "passes state code instead of state symbol to update_all" do
|
163
|
+
# stub_chain does not allow us to give expectations on call
|
164
|
+
# parameters in the middle of the chain, so we need to use
|
165
|
+
# intermediate object instead.
|
166
|
+
obj = double(Object, update_all: 1)
|
167
|
+
gate
|
168
|
+
.class
|
169
|
+
.stub(:where)
|
170
|
+
.and_return(obj)
|
171
|
+
|
172
|
+
gate.aasm_write_state state_sym
|
173
|
+
|
174
|
+
expect(obj).to have_received(:update_all)
|
175
|
+
.with(Hash[gate.class.aasm_column, state_code])
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "when AASM is not skipping validations" do
|
180
|
+
it "delegates state update to the helper method" do
|
181
|
+
# Let's pretend that validation is passed
|
182
|
+
gate.stub(:save).and_return(true)
|
183
|
+
|
184
|
+
gate.aasm_write_state state_sym
|
185
|
+
|
186
|
+
expect(gate).to have_received(:aasm_write_attribute).with(state_sym)
|
187
|
+
expect(gate).to_not have_received :write_attribute
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "aasm_write_state_without_persistence" do
|
193
|
+
it "delegates state update to the helper method" do
|
194
|
+
gate.aasm_write_state_without_persistence state_sym
|
195
|
+
|
196
|
+
expect(gate).to have_received(:aasm_write_attribute).with(state_sym)
|
197
|
+
expect(gate).to_not have_received :write_attribute
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe "aasm_raw_attribute_value" do
|
202
|
+
it "converts state symbol to state code" do
|
203
|
+
expect(gate.send(:aasm_raw_attribute_value, state_sym))
|
204
|
+
.to eq state_code
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context "when AASM is configured to use string field" do
|
210
|
+
let(:state_sym) { :running }
|
211
|
+
|
212
|
+
before :each do
|
213
|
+
gate
|
214
|
+
.stub(:aasm_enum)
|
215
|
+
.and_return(nil)
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "aasm_raw_attribute_value" do
|
219
|
+
it "converts state symbol to string" do
|
220
|
+
expect(gate.send(:aasm_raw_attribute_value, state_sym))
|
221
|
+
.to eq state_sym.to_s
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "aasm_write_attribute helper method" do
|
227
|
+
let(:sym) { :sym }
|
228
|
+
let(:value) { 42 }
|
229
|
+
|
230
|
+
before :each do
|
231
|
+
gate.stub(:write_attribute)
|
232
|
+
gate.stub(:aasm_raw_attribute_value)
|
233
|
+
.and_return(value)
|
234
|
+
|
235
|
+
gate.send(:aasm_write_attribute, sym)
|
236
|
+
end
|
237
|
+
|
238
|
+
it "generates attribute value using a helper method" do
|
239
|
+
expect(gate).to have_received(:aasm_raw_attribute_value).with(sym)
|
240
|
+
end
|
241
|
+
|
242
|
+
it "writes attribute to the model" do
|
243
|
+
expect(gate).to have_received(:write_attribute).with(:aasm_state, value)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
26
247
|
it "should return the initial state when new and the aasm field is nil" do
|
27
248
|
expect(gate.aasm.current_state).to eq(:opened)
|
28
249
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aasm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Barron
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2014-06
|
14
|
+
date: 2014-07-06 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rake
|