aasm 3.0.24 → 3.0.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +21 -3
- data/CHANGELOG.md +8 -0
- data/Gemfile +9 -1
- data/LICENSE +1 -1
- data/README.md +9 -8
- data/aasm.gemspec +4 -5
- data/gemfiles/rails_3.2.gemfile +11 -0
- data/gemfiles/rails_4.0.gemfile +10 -0
- data/lib/aasm.rb +0 -3
- data/lib/aasm/aasm.rb +31 -27
- data/lib/aasm/base.rb +14 -5
- data/lib/aasm/event.rb +16 -16
- data/lib/aasm/instance_base.rb +1 -1
- data/lib/aasm/persistence/active_record_persistence.rb +10 -8
- data/lib/aasm/persistence/base.rb +1 -1
- data/lib/aasm/persistence/mongoid_persistence.rb +10 -8
- data/lib/aasm/version.rb +1 -1
- data/spec/models/mongoid/no_scope_mongoid.rb +1 -1
- data/spec/models/mongoid/simple_mongoid.rb +5 -4
- data/spec/models/mongoid/simple_new_dsl_mongoid.rb +1 -1
- data/spec/models/not_auto_loaded/process.rb +10 -8
- data/spec/models/persistence.rb +5 -13
- data/spec/unit/callbacks_spec.rb +4 -20
- data/spec/unit/complex_example_spec.rb +4 -4
- data/spec/unit/event_spec.rb +49 -36
- data/spec/unit/initial_state_spec.rb +4 -5
- data/spec/unit/inspection_spec.rb +11 -24
- data/spec/unit/localizer_spec.rb +12 -12
- data/spec/unit/persistence/active_record_persistence_spec.rb +13 -31
- data/spec/unit/persistence/mongoid_persistance_spec.rb +102 -81
- data/spec/unit/simple_example_spec.rb +1 -2
- data/spec/unit/subclassing_spec.rb +7 -7
- data/spec/unit/transition_spec.rb +5 -5
- metadata +4 -75
- data/lib/aasm/deprecated/aasm.rb +0 -15
- data/spec/models/callback_old_dsl.rb +0 -41
@@ -35,7 +35,7 @@ module AASM
|
|
35
35
|
def aasm_read_state
|
36
36
|
state = send(self.class.aasm_column)
|
37
37
|
if new_record?
|
38
|
-
state.blank? ? aasm.determine_state_name(self.class.
|
38
|
+
state.blank? ? aasm.determine_state_name(self.class.aasm.initial_state) : state.to_sym
|
39
39
|
else
|
40
40
|
state.nil? ? nil : state.to_sym
|
41
41
|
end
|
@@ -36,6 +36,8 @@ module AASM
|
|
36
36
|
# Mongoid's Validatable gem dependency goes not have a before_validation_on_xxx hook yet.
|
37
37
|
# base.before_validation_on_create :aasm_ensure_initial_state
|
38
38
|
base.before_validation :aasm_ensure_initial_state
|
39
|
+
# ensure initial aasm state even when validations are skipped
|
40
|
+
base.before_create :aasm_ensure_initial_state
|
39
41
|
end
|
40
42
|
|
41
43
|
module ClassMethods
|
@@ -66,10 +68,10 @@ module AASM
|
|
66
68
|
# using update_attribute (which bypasses validation)
|
67
69
|
#
|
68
70
|
# foo = Foo.find(1)
|
69
|
-
# foo.
|
71
|
+
# foo.aasm.current_state # => :opened
|
70
72
|
# foo.close!
|
71
|
-
# foo.
|
72
|
-
# Foo.find(1).
|
73
|
+
# foo.aasm.current_state # => :closed
|
74
|
+
# Foo.find(1).aasm.current_state # => :closed
|
73
75
|
#
|
74
76
|
# NOTE: intended to be called from an event
|
75
77
|
def aasm_write_state(state)
|
@@ -87,13 +89,13 @@ module AASM
|
|
87
89
|
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
88
90
|
#
|
89
91
|
# foo = Foo.find(1)
|
90
|
-
# foo.
|
92
|
+
# foo.aasm.current_state # => :opened
|
91
93
|
# foo.close
|
92
|
-
# foo.
|
93
|
-
# Foo.find(1).
|
94
|
+
# foo.aasm.current_state # => :closed
|
95
|
+
# Foo.find(1).aasm.current_state # => :opened
|
94
96
|
# foo.save
|
95
|
-
# foo.
|
96
|
-
# Foo.find(1).
|
97
|
+
# foo.aasm.current_state # => :closed
|
98
|
+
# Foo.find(1).aasm.current_state # => :closed
|
97
99
|
#
|
98
100
|
# NOTE: intended to be called from an event
|
99
101
|
def aasm_write_state_without_persistence(state)
|
data/lib/aasm/version.rb
CHANGED
@@ -2,9 +2,10 @@ class SimpleMongoid
|
|
2
2
|
include Mongoid::Document
|
3
3
|
include AASM
|
4
4
|
|
5
|
-
field :status, type
|
5
|
+
field :status, :type => String
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
aasm column: :status do
|
8
|
+
state :unknown_scope
|
9
|
+
state :new
|
10
|
+
end
|
10
11
|
end
|
@@ -2,16 +2,18 @@ module Models
|
|
2
2
|
class Process
|
3
3
|
include AASM
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
aasm do
|
6
|
+
state :sleeping
|
7
|
+
state :running
|
8
|
+
state :suspended
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
event :start do
|
11
|
+
transitions :from => :sleeping, :to => :running
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
event :stop do
|
15
|
+
transitions :from => :running, :to => :suspended
|
16
|
+
end
|
15
17
|
end
|
16
18
|
|
17
19
|
end
|
data/spec/models/persistence.rb
CHANGED
@@ -36,13 +36,6 @@ class Transient < ActiveRecord::Base
|
|
36
36
|
include AASM
|
37
37
|
end
|
38
38
|
|
39
|
-
class Simple < ActiveRecord::Base
|
40
|
-
include AASM
|
41
|
-
aasm_column :status
|
42
|
-
aasm_state :unknown_scope
|
43
|
-
aasm_state :new
|
44
|
-
end
|
45
|
-
|
46
39
|
class SimpleNewDsl < ActiveRecord::Base
|
47
40
|
include AASM
|
48
41
|
aasm :column => :status
|
@@ -59,9 +52,6 @@ class NoScope < ActiveRecord::Base
|
|
59
52
|
end
|
60
53
|
end
|
61
54
|
|
62
|
-
class Derivate < Simple
|
63
|
-
end
|
64
|
-
|
65
55
|
class DerivateNewDsl < SimpleNewDsl
|
66
56
|
end
|
67
57
|
|
@@ -72,8 +62,10 @@ class Thief < ActiveRecord::Base
|
|
72
62
|
set_table_name "thieves"
|
73
63
|
end
|
74
64
|
include AASM
|
75
|
-
|
76
|
-
|
77
|
-
|
65
|
+
aasm do
|
66
|
+
state :rich
|
67
|
+
state :jailed
|
68
|
+
initial_state Proc.new {|thief| thief.skilled ? :rich : :jailed }
|
69
|
+
end
|
78
70
|
attr_accessor :skilled, :aasm_state
|
79
71
|
end
|
data/spec/unit/callbacks_spec.rb
CHANGED
@@ -1,23 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe 'callbacks for the old DSL' do
|
4
|
-
let(:callback) {CallbackOldDsl.new}
|
5
|
-
|
6
|
-
it "should get close callbacks" do
|
7
|
-
callback.should_receive(:exit_open).once.ordered
|
8
|
-
callback.should_receive(:before).once.ordered
|
9
|
-
callback.should_receive(:before_exit_open).once.ordered # these should be before the state changes
|
10
|
-
callback.should_receive(:before_enter_closed).once.ordered
|
11
|
-
callback.should_receive(:enter_closed).once.ordered
|
12
|
-
callback.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
|
13
|
-
callback.should_receive(:after_exit_open).once.ordered # these should be after the state changes
|
14
|
-
callback.should_receive(:after_enter_closed).once.ordered
|
15
|
-
callback.should_receive(:after).once.ordered
|
16
|
-
|
17
|
-
callback.close!
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
3
|
describe 'callbacks for the new DSL' do
|
22
4
|
let(:callback) {CallbackNewDsl.new}
|
23
5
|
|
@@ -40,8 +22,10 @@ describe 'event callbacks' do
|
|
40
22
|
describe "with an error callback defined" do
|
41
23
|
before do
|
42
24
|
class Foo
|
43
|
-
|
44
|
-
|
25
|
+
aasm do
|
26
|
+
event :safe_close, :success => :success_callback, :error => :error_callback do
|
27
|
+
transitions :to => :closed, :from => [:open]
|
28
|
+
end
|
45
29
|
end
|
46
30
|
end
|
47
31
|
|
@@ -4,7 +4,7 @@ describe 'on initialization' do
|
|
4
4
|
let(:auth) {AuthMachine.new}
|
5
5
|
|
6
6
|
it 'should be in the pending state' do
|
7
|
-
auth.
|
7
|
+
auth.aasm.current_state.should == :pending
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'should have an activation code' do
|
@@ -55,14 +55,14 @@ describe 'when being unsuspended' do
|
|
55
55
|
auth.suspend!
|
56
56
|
auth.unsuspend!
|
57
57
|
|
58
|
-
auth.
|
58
|
+
auth.aasm.current_state.should == :active
|
59
59
|
end
|
60
60
|
|
61
61
|
it 'should be pending if not previously activated, but an activation code is present' do
|
62
62
|
auth.suspend!
|
63
63
|
auth.unsuspend!
|
64
64
|
|
65
|
-
auth.
|
65
|
+
auth.aasm.current_state.should == :pending
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'should be passive if not previously activated and there is no activation code' do
|
@@ -70,6 +70,6 @@ describe 'when being unsuspended' do
|
|
70
70
|
auth.suspend!
|
71
71
|
auth.unsuspend!
|
72
72
|
|
73
|
-
auth.
|
73
|
+
auth.aasm.current_state.should == :passive
|
74
74
|
end
|
75
75
|
end
|
data/spec/unit/event_spec.rb
CHANGED
@@ -26,7 +26,7 @@ describe 'adding an event' do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'should create transitions' do
|
29
|
-
transitions = event.
|
29
|
+
transitions = event.transitions
|
30
30
|
transitions[0].from.should == :open
|
31
31
|
transitions[0].to.should == :closed
|
32
32
|
transitions[1].from.should == :received
|
@@ -60,8 +60,7 @@ end
|
|
60
60
|
|
61
61
|
describe 'firing an event' do
|
62
62
|
it 'should return nil if the transitions are empty' do
|
63
|
-
obj = double('object')
|
64
|
-
obj.stub(:aasm_current_state)
|
63
|
+
obj = double('object', :aasm => double('aasm', :current_state => 'open'))
|
65
64
|
|
66
65
|
event = AASM::Event.new(:event)
|
67
66
|
event.fire(obj).should be_nil
|
@@ -72,8 +71,7 @@ describe 'firing an event' do
|
|
72
71
|
transitions :to => :closed, :from => [:open, :received]
|
73
72
|
end
|
74
73
|
|
75
|
-
obj = double('object')
|
76
|
-
obj.stub(:aasm_current_state).and_return(:open)
|
74
|
+
obj = double('object', :aasm => double('aasm', :current_state => :open))
|
77
75
|
|
78
76
|
event.fire(obj).should == :closed
|
79
77
|
end
|
@@ -83,8 +81,7 @@ describe 'firing an event' do
|
|
83
81
|
transitions :to => :closed, :from => [:open, :received], :guard => :guard_fn
|
84
82
|
end
|
85
83
|
|
86
|
-
obj = double('object')
|
87
|
-
obj.stub(:aasm_current_state).and_return(:open)
|
84
|
+
obj = double('object', :aasm => double('aasm', :current_state => :open))
|
88
85
|
obj.should_receive(:guard_fn).with('arg1', 'arg2').and_return(true)
|
89
86
|
|
90
87
|
event.fire(obj, nil, 'arg1', 'arg2').should == :closed
|
@@ -96,8 +93,10 @@ describe 'should fire callbacks' do
|
|
96
93
|
describe 'success' do
|
97
94
|
it "if it's a symbol" do
|
98
95
|
ThisNameBetterNotBeInUse.instance_eval {
|
99
|
-
|
100
|
-
|
96
|
+
aasm do
|
97
|
+
event :with_symbol, :success => :symbol_success_callback do
|
98
|
+
transitions :to => :symbol, :from => [:initial]
|
99
|
+
end
|
101
100
|
end
|
102
101
|
}
|
103
102
|
|
@@ -108,8 +107,10 @@ describe 'should fire callbacks' do
|
|
108
107
|
|
109
108
|
it "if it's a string" do
|
110
109
|
ThisNameBetterNotBeInUse.instance_eval {
|
111
|
-
|
112
|
-
|
110
|
+
aasm do
|
111
|
+
event :with_string, :success => 'string_success_callback' do
|
112
|
+
transitions :to => :string, :from => [:initial]
|
113
|
+
end
|
113
114
|
end
|
114
115
|
}
|
115
116
|
|
@@ -120,8 +121,10 @@ describe 'should fire callbacks' do
|
|
120
121
|
|
121
122
|
it "if passed an array of strings and/or symbols" do
|
122
123
|
ThisNameBetterNotBeInUse.instance_eval {
|
123
|
-
|
124
|
-
|
124
|
+
aasm do
|
125
|
+
event :with_array, :success => [:success_callback1, 'success_callback2'] do
|
126
|
+
transitions :to => :array, :from => [:initial]
|
127
|
+
end
|
125
128
|
end
|
126
129
|
}
|
127
130
|
|
@@ -133,8 +136,10 @@ describe 'should fire callbacks' do
|
|
133
136
|
|
134
137
|
it "if passed an array of strings and/or symbols and/or procs" do
|
135
138
|
ThisNameBetterNotBeInUse.instance_eval {
|
136
|
-
|
137
|
-
|
139
|
+
aasm do
|
140
|
+
event :with_array_including_procs, :success => [:success_callback1, 'success_callback2', lambda { proc_success_callback }] do
|
141
|
+
transitions :to => :array, :from => [:initial]
|
142
|
+
end
|
138
143
|
end
|
139
144
|
}
|
140
145
|
|
@@ -147,8 +152,10 @@ describe 'should fire callbacks' do
|
|
147
152
|
|
148
153
|
it "if it's a proc" do
|
149
154
|
ThisNameBetterNotBeInUse.instance_eval {
|
150
|
-
|
151
|
-
|
155
|
+
aasm do
|
156
|
+
event :with_proc, :success => lambda { proc_success_callback } do
|
157
|
+
transitions :to => :proc, :from => [:initial]
|
158
|
+
end
|
152
159
|
end
|
153
160
|
}
|
154
161
|
|
@@ -161,14 +168,16 @@ describe 'should fire callbacks' do
|
|
161
168
|
describe 'after' do
|
162
169
|
it "if they set different ways" do
|
163
170
|
ThisNameBetterNotBeInUse.instance_eval do
|
164
|
-
|
165
|
-
after do
|
166
|
-
|
171
|
+
aasm do
|
172
|
+
event :with_afters, :after => :do_one_thing_after do
|
173
|
+
after do
|
174
|
+
do_another_thing_after_too
|
175
|
+
end
|
176
|
+
after do
|
177
|
+
do_third_thing_at_last
|
178
|
+
end
|
179
|
+
transitions :to => :proc, :from => [:initial]
|
167
180
|
end
|
168
|
-
after do
|
169
|
-
do_third_thing_at_last
|
170
|
-
end
|
171
|
-
transitions :to => :proc, :from => [:initial]
|
172
181
|
end
|
173
182
|
end
|
174
183
|
|
@@ -183,11 +192,13 @@ describe 'should fire callbacks' do
|
|
183
192
|
describe 'before' do
|
184
193
|
it "if it's a proc" do
|
185
194
|
ThisNameBetterNotBeInUse.instance_eval do
|
186
|
-
|
187
|
-
|
188
|
-
|
195
|
+
aasm do
|
196
|
+
event :before_as_proc do
|
197
|
+
before do
|
198
|
+
do_something_before
|
199
|
+
end
|
200
|
+
transitions :to => :proc, :from => [:initial]
|
189
201
|
end
|
190
|
-
transitions :to => :proc, :from => [:initial]
|
191
202
|
end
|
192
203
|
end
|
193
204
|
|
@@ -199,11 +210,13 @@ describe 'should fire callbacks' do
|
|
199
210
|
|
200
211
|
it 'in right order' do
|
201
212
|
ThisNameBetterNotBeInUse.instance_eval do
|
202
|
-
|
203
|
-
|
204
|
-
|
213
|
+
aasm do
|
214
|
+
event :in_right_order, :after => :do_something_after do
|
215
|
+
before do
|
216
|
+
do_something_before
|
217
|
+
end
|
218
|
+
transitions :to => :proc, :from => [:initial]
|
205
219
|
end
|
206
|
-
transitions :to => :proc, :from => [:initial]
|
207
220
|
end
|
208
221
|
end
|
209
222
|
|
@@ -219,22 +232,22 @@ describe 'parametrised events' do
|
|
219
232
|
|
220
233
|
it 'should transition to specified next state (sleeping to showering)' do
|
221
234
|
pe.wakeup!(:showering)
|
222
|
-
pe.
|
235
|
+
pe.aasm.current_state.should == :showering
|
223
236
|
end
|
224
237
|
|
225
238
|
it 'should transition to specified next state (sleeping to working)' do
|
226
239
|
pe.wakeup!(:working)
|
227
|
-
pe.
|
240
|
+
pe.aasm.current_state.should == :working
|
228
241
|
end
|
229
242
|
|
230
243
|
it 'should transition to default (first or showering) state' do
|
231
244
|
pe.wakeup!
|
232
|
-
pe.
|
245
|
+
pe.aasm.current_state.should == :showering
|
233
246
|
end
|
234
247
|
|
235
248
|
it 'should transition to default state when on_transition invoked' do
|
236
249
|
pe.dress!(nil, 'purple', 'dressy')
|
237
|
-
pe.
|
250
|
+
pe.aasm.current_state.should == :working
|
238
251
|
end
|
239
252
|
|
240
253
|
it 'should call on_transition method with args' do
|
@@ -5,8 +5,8 @@ class Banker
|
|
5
5
|
aasm do
|
6
6
|
state :retired
|
7
7
|
state :selling_bad_mortgages
|
8
|
+
initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
|
8
9
|
end
|
9
|
-
aasm_initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
|
10
10
|
RICH = 1_000_000
|
11
11
|
attr_accessor :balance
|
12
12
|
def initialize(balance = 0); self.balance = balance; end
|
@@ -17,12 +17,11 @@ describe 'initial states' do
|
|
17
17
|
let(:bar) {Bar.new}
|
18
18
|
|
19
19
|
it 'should use the first state defined if no initial state is given' do
|
20
|
-
bar.
|
21
|
-
# bar.aasm.current_state.should == :read # not yet supported
|
20
|
+
bar.aasm.current_state.should == :read
|
22
21
|
end
|
23
22
|
|
24
23
|
it 'should determine initial state from the Proc results' do
|
25
|
-
Banker.new(Banker::RICH - 1).
|
26
|
-
Banker.new(Banker::RICH + 1).
|
24
|
+
Banker.new(Banker::RICH - 1).aasm.current_state.should == :selling_bad_mortgages
|
25
|
+
Banker.new(Banker::RICH + 1).aasm.current_state.should == :retired
|
27
26
|
end
|
28
27
|
end
|
@@ -1,19 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'inspection for common cases' do
|
4
|
-
it 'should support the old DSL' do
|
5
|
-
Foo.should respond_to(:aasm_states)
|
6
|
-
Foo.aasm_states.should include(:open)
|
7
|
-
Foo.aasm_states.should include(:closed)
|
8
|
-
|
9
|
-
Foo.should respond_to(:aasm_initial_state)
|
10
|
-
Foo.aasm_initial_state.should == :open
|
11
|
-
|
12
|
-
Foo.should respond_to(:aasm_events)
|
13
|
-
Foo.aasm_events.should include(:close)
|
14
|
-
Foo.aasm_events.should include(:null)
|
15
|
-
end
|
16
|
-
|
17
4
|
it 'should support the new DSL' do
|
18
5
|
Foo.aasm.should respond_to(:states)
|
19
6
|
Foo.aasm.states.should include(:open)
|
@@ -74,35 +61,35 @@ end
|
|
74
61
|
|
75
62
|
describe "special cases" do
|
76
63
|
it "should support valid a state name" do
|
77
|
-
Argument.
|
78
|
-
Argument.
|
64
|
+
Argument.aasm.states.should include(:invalid)
|
65
|
+
Argument.aasm.states.should include(:valid)
|
79
66
|
|
80
67
|
argument = Argument.new
|
81
68
|
argument.invalid?.should be_true
|
82
|
-
argument.
|
69
|
+
argument.aasm.current_state.should == :invalid
|
83
70
|
|
84
71
|
argument.valid!
|
85
72
|
argument.valid?.should be_true
|
86
|
-
argument.
|
73
|
+
argument.aasm.current_state.should == :valid
|
87
74
|
end
|
88
75
|
end
|
89
76
|
|
90
|
-
describe
|
77
|
+
describe 'aasm.states_for_select' do
|
91
78
|
it "should return a select friendly array of states" do
|
92
|
-
Foo.should respond_to(:
|
93
|
-
Foo.
|
79
|
+
Foo.aasm.should respond_to(:states_for_select)
|
80
|
+
Foo.aasm.states_for_select.should == [['Open', 'open'], ['Closed', 'closed']]
|
94
81
|
end
|
95
82
|
end
|
96
83
|
|
97
|
-
describe
|
84
|
+
describe 'aasm.from_states_for_state' do
|
98
85
|
it "should return all from states for a state" do
|
99
|
-
AuthMachine.should respond_to(:
|
100
|
-
froms = AuthMachine.
|
86
|
+
AuthMachine.aasm.should respond_to(:from_states_for_state)
|
87
|
+
froms = AuthMachine.aasm.from_states_for_state(:active)
|
101
88
|
[:pending, :passive, :suspended].each {|from| froms.should include(from)}
|
102
89
|
end
|
103
90
|
|
104
91
|
it "should return from states for a state for a particular transition only" do
|
105
|
-
froms = AuthMachine.
|
92
|
+
froms = AuthMachine.aasm.from_states_for_state(:active, :transition => :unsuspend)
|
106
93
|
[:suspended].each {|from| froms.should include(from)}
|
107
94
|
end
|
108
95
|
end
|