aasm 3.2.1 → 3.3.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/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
|