aasm 3.2.1 → 3.3.2
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 +15 -0
- data/README.md +38 -2
- data/lib/aasm/aasm.rb +4 -4
- data/lib/aasm/base.rb +2 -0
- data/lib/aasm/instance_base.rb +1 -1
- data/lib/aasm/persistence/active_record_persistence.rb +39 -8
- data/lib/aasm/persistence/base.rb +1 -5
- data/lib/aasm/persistence/sequel_persistence.rb +1 -1
- data/lib/aasm/version.rb +1 -1
- data/spec/models/foo.rb +2 -1
- data/spec/unit/event_naming_spec.rb +24 -0
- data/spec/unit/inspection_spec.rb +3 -1
- data/spec/unit/persistence/active_record_persistence_spec.rb +246 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 83a1f3168fccb10e8b1514ced2d81ec931c5c53a
|
|
4
|
+
data.tar.gz: 216b3cdd8404f5b2cd963c99a975946848a06e69
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ea1641220521468b48b11ce9e8fb868a85d1e34d44ddc8256cb2a26ccc055f2cddcf3b557358a651239d2d6cc5d3bedf6f53e9baaf9122b6329c5d3cdd2ed25e
|
|
7
|
+
data.tar.gz: 2f4e51a87d973d04a16cd64692d0fbcf48df87ab7ee8d412411ca7cb742005b68f7a7ee2ae3d953b0ab01bd8f7956ffd98dd95ba6eda0e3e9b7a6b3533eaa0ea
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
* deprecated old aasm_* class methods (old-style DSL), in preparation for AASM v4.0.0
|
|
6
6
|
|
|
7
|
+
## 3.3.2
|
|
8
|
+
|
|
9
|
+
* bugfix: avoid conflicts with `failed` and `fired` event names (see [issue #157](https://github.com/aasm/aasm/issues/157)), thanks to [@MichaelXavier](https://github.com/MichaelXavier)
|
|
10
|
+
* bugfix: not using transactions unless saving to the database (see [issue #162](https://github.com/aasm/aasm/issues/162) and [issue #164](https://github.com/aasm/aasm/issues/164)), thanks to [@roberthoner](https://github.com/roberthoner)
|
|
11
|
+
* bugfix: `after_commit` should only run if saving to the database (see [issue #151](https://github.com/aasm/aasm/issues/151)), thanks to [@ivantsepp](https://github.com/ivantsepp)
|
|
12
|
+
|
|
13
|
+
## 3.3.1
|
|
14
|
+
|
|
15
|
+
* bugfix: permissible events will respect given `guards` (see [issue #150](https://github.com/aasm/aasm/issues/150))
|
|
16
|
+
|
|
17
|
+
## 3.3.0
|
|
18
|
+
|
|
19
|
+
* support for Rails 4.1 enum fields (see [issue #124](https://github.com/aasm/aasm/issues/124), thanks to [@bkon](https://github.com/bkon))
|
|
20
|
+
* 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))
|
|
21
|
+
|
|
7
22
|
## 3.2.1
|
|
8
23
|
|
|
9
24
|
* 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
|
@@ -147,7 +147,9 @@ Also, you can pass parameters to events:
|
|
|
147
147
|
job.run(:running, :defragmentation)
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
In this case the `set_process` would be called with `:
|
|
150
|
+
In this case the `set_process` would be called with `:defragmentation` argument.
|
|
151
|
+
|
|
152
|
+
Note that when passing arguments to a state transition, the first argument must be the desired end state. In the above example, we wish to transition to `:running` state and run the callback with `:defragmentation` argument. You can also pass in `nil` as the desired end state, and AASM will try to transition to the first end state defined for that event.
|
|
151
153
|
|
|
152
154
|
In case of an error during the event processing the error is rescued and passed to `:error`
|
|
153
155
|
callback, which can handle it or re-raise it for further propagation.
|
|
@@ -212,7 +214,7 @@ You can even provide a number of guards, which all have to succeed to proceed
|
|
|
212
214
|
end
|
|
213
215
|
```
|
|
214
216
|
|
|
215
|
-
If you want to provide guards for all transitions
|
|
217
|
+
If you want to provide guards for all transitions within an event, you can use event guards
|
|
216
218
|
|
|
217
219
|
```ruby
|
|
218
220
|
event :sleep, :guards => [:walked_the_dog?] do
|
|
@@ -278,6 +280,40 @@ class Job < ActiveRecord::Base
|
|
|
278
280
|
end
|
|
279
281
|
```
|
|
280
282
|
|
|
283
|
+
#### ActiveRecord enums
|
|
284
|
+
|
|
285
|
+
You can use
|
|
286
|
+
[enumerations](http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html)
|
|
287
|
+
in Rails 4.1+ for your state column:
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
class Job < ActiveRecord::Base
|
|
291
|
+
include AASM
|
|
292
|
+
|
|
293
|
+
enum state: {
|
|
294
|
+
sleeping: 5,
|
|
295
|
+
running: 99
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
aasm :column => :state, :enum => true do
|
|
299
|
+
state :sleeping, :initial => true
|
|
300
|
+
state :running
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
You can explicitly pass the name of the method which provides access
|
|
306
|
+
to the enumeration mapping as a value of ```enum```, or you can simply
|
|
307
|
+
set it to ```true```. In the latter case AASM will try to use
|
|
308
|
+
pluralized column name to access possible enum states.
|
|
309
|
+
|
|
310
|
+
Furthermore, if your column has integer type (which is normally the
|
|
311
|
+
case when you're working with Rails enums), you can omit ```:enum```
|
|
312
|
+
setting --- AASM auto-detects this situation and enabled enum
|
|
313
|
+
support. If anything goes wrong, you can disable enum functionality
|
|
314
|
+
and fall back to the default behavior by setting ```:enum```
|
|
315
|
+
to ```false```.
|
|
316
|
+
|
|
281
317
|
### Sequel
|
|
282
318
|
|
|
283
319
|
AASM also supports [Sequel](http://sequel.jeremyevans.net/) besides _ActiveRecord_ and _Mongoid_.
|
data/lib/aasm/aasm.rb
CHANGED
|
@@ -155,16 +155,16 @@ private
|
|
|
155
155
|
event.fire_callbacks(:before, self)
|
|
156
156
|
|
|
157
157
|
if new_state_name = event.fire(self, *args)
|
|
158
|
-
|
|
158
|
+
aasm_fired(event, old_state, new_state_name, options, &block)
|
|
159
159
|
else
|
|
160
|
-
|
|
160
|
+
aasm_failed(event_name, old_state)
|
|
161
161
|
end
|
|
162
162
|
rescue StandardError => e
|
|
163
163
|
event.fire_callbacks(:error, self, e) || raise(e)
|
|
164
164
|
end
|
|
165
165
|
end
|
|
166
166
|
|
|
167
|
-
def
|
|
167
|
+
def aasm_fired(event, old_state, new_state_name, options)
|
|
168
168
|
persist = options[:persist]
|
|
169
169
|
|
|
170
170
|
new_state = aasm.state_object_for_name(new_state_name)
|
|
@@ -200,7 +200,7 @@ private
|
|
|
200
200
|
persist_successful
|
|
201
201
|
end
|
|
202
202
|
|
|
203
|
-
def
|
|
203
|
+
def aasm_failed(event_name, old_state)
|
|
204
204
|
if self.respond_to?(:aasm_event_failed)
|
|
205
205
|
self.aasm_event_failed(event_name, old_state.name)
|
|
206
206
|
end
|
data/lib/aasm/base.rb
CHANGED
data/lib/aasm/instance_base.rb
CHANGED
|
@@ -35,7 +35,7 @@ module AASM
|
|
|
35
35
|
def states(options={})
|
|
36
36
|
if options[:permissible]
|
|
37
37
|
# ugliness level 1000
|
|
38
|
-
transitions = @instance.class.aasm.events.
|
|
38
|
+
transitions = @instance.class.aasm.events.values_at(*permissible_events).compact.map {|e| e.transitions_from_state(current_state) }
|
|
39
39
|
tos = transitions.map {|t| t[0] ? t[0].to : nil}.flatten.compact.map(&:to_sym).uniq
|
|
40
40
|
@instance.class.aasm.states.select {|s| tos.include?(s.name.to_sym)}
|
|
41
41
|
else
|
|
@@ -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
|
|
@@ -138,11 +171,9 @@ module AASM
|
|
|
138
171
|
end
|
|
139
172
|
|
|
140
173
|
def aasm_fire_event(name, options, *args, &block)
|
|
141
|
-
success = self.class.transaction(:requires_new => requires_new?)
|
|
142
|
-
super
|
|
143
|
-
end
|
|
174
|
+
success = options[:persist] ? self.class.transaction(:requires_new => requires_new?) { super } : super
|
|
144
175
|
|
|
145
|
-
if success
|
|
176
|
+
if success && options[:persist]
|
|
146
177
|
new_state = aasm.state_object_for_name(aasm.current_state)
|
|
147
178
|
new_state.fire_callbacks(:after_commit, self)
|
|
148
179
|
end
|
|
@@ -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
|
|
@@ -84,7 +84,7 @@ module AASM
|
|
|
84
84
|
# NOTE: intended to be called from an event
|
|
85
85
|
def aasm_write_state state
|
|
86
86
|
aasm_column = self.class.aasm_column
|
|
87
|
-
|
|
87
|
+
update_only({aasm_column => state.to_s}, aasm_column)
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
data/lib/aasm/version.rb
CHANGED
data/spec/models/foo.rb
CHANGED
|
@@ -3,13 +3,14 @@ class Foo
|
|
|
3
3
|
aasm do
|
|
4
4
|
state :open, :initial => true, :exit => :exit
|
|
5
5
|
state :closed, :enter => :enter
|
|
6
|
+
state :final
|
|
6
7
|
|
|
7
8
|
event :close, :success => :success_callback do
|
|
8
9
|
transitions :from => [:open], :to => [:closed]
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
event :null do
|
|
12
|
-
transitions :from => [:open], :to => :closed, :guard => :always_false
|
|
13
|
+
transitions :from => [:open], :to => [:closed, :final], :guard => :always_false
|
|
13
14
|
end
|
|
14
15
|
end
|
|
15
16
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class SimpleStateMachine
|
|
4
|
+
include AASM
|
|
5
|
+
|
|
6
|
+
aasm do
|
|
7
|
+
state :init, :initial => true
|
|
8
|
+
state :failed
|
|
9
|
+
|
|
10
|
+
event :failed do
|
|
11
|
+
transitions :from => :init, :to => :failed
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "event naming" do
|
|
17
|
+
let(:state_machine) { SimpleStateMachine.new }
|
|
18
|
+
|
|
19
|
+
it "allows an event of failed without blowing the stack" do
|
|
20
|
+
state_machine.failed
|
|
21
|
+
|
|
22
|
+
expect { state_machine.failed }.to raise_error(AASM::InvalidTransition)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -22,10 +22,12 @@ describe 'inspection for common cases' do
|
|
|
22
22
|
states = foo.aasm.states
|
|
23
23
|
expect(states).to include(:open)
|
|
24
24
|
expect(states).to include(:closed)
|
|
25
|
+
expect(states).to include(:final)
|
|
25
26
|
|
|
26
27
|
states = foo.aasm.states(:permissible => true)
|
|
27
28
|
expect(states).to include(:closed)
|
|
28
29
|
expect(states).not_to include(:open)
|
|
30
|
+
expect(states).not_to include(:final)
|
|
29
31
|
|
|
30
32
|
foo.close
|
|
31
33
|
expect(foo.aasm.states(:permissible => true)).to be_empty
|
|
@@ -77,7 +79,7 @@ end
|
|
|
77
79
|
describe 'aasm.states_for_select' do
|
|
78
80
|
it "should return a select friendly array of states" do
|
|
79
81
|
expect(Foo.aasm).to respond_to(:states_for_select)
|
|
80
|
-
expect(Foo.aasm.states_for_select).to eq([['Open', 'open'], ['Closed', 'closed']])
|
|
82
|
+
expect(Foo.aasm.states_for_select).to eq([['Open', 'open'], ['Closed', 'closed'], ['Final', 'final']])
|
|
81
83
|
end
|
|
82
84
|
end
|
|
83
85
|
|
|
@@ -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
|
|
@@ -217,6 +438,31 @@ describe 'transitions with persistence' do
|
|
|
217
438
|
expect(validator.name).to eq("name")
|
|
218
439
|
end
|
|
219
440
|
|
|
441
|
+
it "should not fire if not saving" do
|
|
442
|
+
validator = Validator.create(:name => 'name')
|
|
443
|
+
expect(validator).to be_sleeping
|
|
444
|
+
validator.run
|
|
445
|
+
expect(validator).to be_running
|
|
446
|
+
expect(validator.name).to eq("name")
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
context "when not persisting" do
|
|
452
|
+
it 'should not rollback all changes' do
|
|
453
|
+
expect(transactor).to be_sleeping
|
|
454
|
+
expect(worker.status).to eq('sleeping')
|
|
455
|
+
|
|
456
|
+
# Notice here we're calling "run" and not "run!" with a bang.
|
|
457
|
+
expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
|
|
458
|
+
expect(transactor).to be_running
|
|
459
|
+
expect(worker.reload.status).to eq('running')
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
it 'should not create a database transaction' do
|
|
463
|
+
expect(transactor.class).not_to receive(:transaction)
|
|
464
|
+
expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
|
|
465
|
+
end
|
|
220
466
|
end
|
|
221
467
|
end
|
|
222
468
|
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.2
|
|
4
|
+
version: 3.3.2
|
|
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-
|
|
14
|
+
date: 2014-08-16 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: rake
|
|
@@ -166,6 +166,7 @@ files:
|
|
|
166
166
|
- spec/unit/api_spec.rb
|
|
167
167
|
- spec/unit/callbacks_spec.rb
|
|
168
168
|
- spec/unit/complex_example_spec.rb
|
|
169
|
+
- spec/unit/event_naming_spec.rb
|
|
169
170
|
- spec/unit/event_spec.rb
|
|
170
171
|
- spec/unit/guard_spec.rb
|
|
171
172
|
- spec/unit/initial_state_spec.rb
|
|
@@ -237,6 +238,7 @@ test_files:
|
|
|
237
238
|
- spec/unit/api_spec.rb
|
|
238
239
|
- spec/unit/callbacks_spec.rb
|
|
239
240
|
- spec/unit/complex_example_spec.rb
|
|
241
|
+
- spec/unit/event_naming_spec.rb
|
|
240
242
|
- spec/unit/event_spec.rb
|
|
241
243
|
- spec/unit/guard_spec.rb
|
|
242
244
|
- spec/unit/initial_state_spec.rb
|