aasm 3.0.14 → 3.0.15
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.
- data/CHANGELOG.md +4 -0
- data/lib/aasm/aasm.rb +9 -8
- data/lib/aasm/base.rb +6 -1
- data/lib/aasm/state_machine.rb +8 -3
- data/lib/aasm/supporting_classes/localizer.rb +6 -7
- data/lib/aasm/supporting_classes/state.rb +17 -2
- data/lib/aasm/version.rb +1 -1
- data/spec/en.yml +1 -1
- data/spec/en_deprecated_style.yml +1 -1
- data/spec/models/argument.rb +11 -0
- data/spec/models/callback_new_dsl.rb +5 -0
- data/spec/models/callback_old_dsl.rb +11 -6
- data/spec/models/parametrised_event.rb +29 -0
- data/spec/spec_helpers/models_spec_helper.rb +0 -55
- data/spec/unit/callbacks_spec.rb +116 -0
- data/spec/unit/complex_example_spec.rb +2 -2
- data/spec/unit/initial_state_spec.rb +28 -0
- data/spec/unit/inspection_spec.rb +75 -3
- data/spec/unit/memory_leak_spec.rb +32 -28
- data/spec/unit/new_dsl_spec.rb +2 -18
- data/spec/unit/persistence/active_record_persistence_spec.rb +2 -7
- data/spec/unit/simple_example_spec.rb +53 -0
- data/spec/unit/subclassing_spec.rb +19 -0
- data/spec/unit/{event_spec.rb → supporting_classes/event_spec.rb} +77 -24
- data/spec/unit/{localizer_spec.rb → supporting_classes/localizer_spec.rb} +25 -3
- data/spec/unit/{state_spec.rb → supporting_classes/state_spec.rb} +2 -2
- data/spec/unit/{state_transition_spec.rb → supporting_classes/state_transition_spec.rb} +2 -2
- metadata +40 -34
- data/spec/unit/aasm_spec.rb +0 -301
- data/spec/unit/callbacks_new_dsl_spec.rb +0 -33
- data/spec/unit/callbacks_old_dsl_spec.rb +0 -33
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe '
|
3
|
+
describe 'on initialization' do
|
4
4
|
let(:auth) {AuthMachine.new}
|
5
5
|
|
6
6
|
it 'should be in the pending state' do
|
@@ -13,7 +13,7 @@ describe 'AuthMachine on initialization' do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe '
|
16
|
+
describe 'when being unsuspended' do
|
17
17
|
let(:auth) {AuthMachine.new}
|
18
18
|
|
19
19
|
it 'should be able to be unsuspended' do
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Banker
|
4
|
+
include AASM
|
5
|
+
aasm do
|
6
|
+
state :retired
|
7
|
+
state :selling_bad_mortgages
|
8
|
+
end
|
9
|
+
aasm_initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
|
10
|
+
RICH = 1_000_000
|
11
|
+
attr_accessor :balance
|
12
|
+
def initialize(balance = 0); self.balance = balance; end
|
13
|
+
def rich?; self.balance >= RICH; end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'initial states' do
|
17
|
+
let(:bar) {Bar.new}
|
18
|
+
|
19
|
+
it 'should use the first state defined if no initial state is given' do
|
20
|
+
bar.aasm_current_state.should == :read
|
21
|
+
# bar.aasm.current_state.should == :read # not yet supported
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should determine initial state from the Proc results' do
|
25
|
+
Banker.new(Banker::RICH - 1).aasm_current_state.should == :selling_bad_mortgages
|
26
|
+
Banker.new(Banker::RICH + 1).aasm_current_state.should == :retired
|
27
|
+
end
|
28
|
+
end
|
@@ -1,7 +1,79 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe '
|
4
|
-
it 'should support
|
5
|
-
|
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
|
+
it 'should support the new DSL' do
|
18
|
+
Foo.aasm.should respond_to(:states)
|
19
|
+
Foo.aasm.states.should include(:open)
|
20
|
+
Foo.aasm.states.should include(:closed)
|
21
|
+
|
22
|
+
Foo.aasm.should respond_to(:initial_state)
|
23
|
+
Foo.aasm.initial_state.should == :open
|
24
|
+
|
25
|
+
Foo.aasm.should respond_to(:events)
|
26
|
+
Foo.aasm.events.should include(:close)
|
27
|
+
Foo.aasm.events.should include(:null)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should list states in the order they have been defined' do
|
31
|
+
Conversation.aasm.states.should == [:needs_attention, :read, :closed, :awaiting_response, :junk]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "special cases" do
|
36
|
+
it "should support valid a state name" do
|
37
|
+
Argument.aasm_states.should include(:invalid)
|
38
|
+
Argument.aasm_states.should include(:valid)
|
39
|
+
|
40
|
+
argument = Argument.new
|
41
|
+
argument.invalid?.should be_true
|
42
|
+
argument.aasm_current_state.should == :invalid
|
43
|
+
|
44
|
+
argument.valid!
|
45
|
+
argument.valid?.should be_true
|
46
|
+
argument.aasm_current_state.should == :valid
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe :aasm_states_for_select do
|
51
|
+
it "should return a select friendly array of states" do
|
52
|
+
Foo.should respond_to(:aasm_states_for_select)
|
53
|
+
Foo.aasm_states_for_select.should == [['Open', 'open'], ['Closed', 'closed']]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe :aasm_from_states_for_state do
|
58
|
+
it "should return all from states for a state" do
|
59
|
+
AuthMachine.should respond_to(:aasm_from_states_for_state)
|
60
|
+
froms = AuthMachine.aasm_from_states_for_state(:active)
|
61
|
+
[:pending, :passive, :suspended].each {|from| froms.should include(from)}
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return from states for a state for a particular transition only" do
|
65
|
+
froms = AuthMachine.aasm_from_states_for_state(:active, :transition => :unsuspend)
|
66
|
+
[:suspended].each {|from| froms.should include(from)}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe :aasm_events_for_current_state do
|
71
|
+
let(:foo) {Foo.new}
|
72
|
+
|
73
|
+
it 'work' do
|
74
|
+
foo.aasm_events_for_current_state.should include(:close)
|
75
|
+
foo.aasm_events_for_current_state.should include(:null)
|
76
|
+
foo.close
|
77
|
+
foo.aasm_events_for_current_state.should be_empty
|
6
78
|
end
|
7
79
|
end
|
@@ -1,34 +1,38 @@
|
|
1
|
-
require
|
1
|
+
# require 'spec_helper'
|
2
2
|
|
3
|
-
describe "state machines" do
|
3
|
+
# describe "state machines" do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def machines
|
10
|
-
AASM::StateMachine.instance_variable_get("@machines")
|
11
|
-
end
|
5
|
+
# def number_of_objects(clazz)
|
6
|
+
# ObjectSpace.each_object(clazz) {}
|
7
|
+
# end
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
event_count = number_of_objects(AASM::SupportingClasses::Event)
|
17
|
-
transition_count = number_of_objects(AASM::SupportingClasses::StateTransition)
|
9
|
+
# def machines
|
10
|
+
# AASM::StateMachine.instance_variable_get("@machines")
|
11
|
+
# end
|
18
12
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
13
|
+
# it "should be created without memory leak" do
|
14
|
+
# machines_count = machines.size
|
15
|
+
# state_count = number_of_objects(AASM::SupportingClasses::State)
|
16
|
+
# event_count = number_of_objects(AASM::SupportingClasses::Event)
|
17
|
+
# puts "event_count = #{event_count}"
|
18
|
+
# transition_count = number_of_objects(AASM::SupportingClasses::StateTransition)
|
25
19
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
20
|
+
# load File.expand_path(File.dirname(__FILE__) + '/../models/not_auto_loaded/process.rb')
|
21
|
+
# machines.size.should == machines_count + 1 # + Process
|
22
|
+
# number_of_objects(Models::Process).should == 0
|
23
|
+
# number_of_objects(AASM::SupportingClasses::State).should == state_count + 3 # + Process
|
24
|
+
# puts "event_count = #{number_of_objects(AASM::SupportingClasses::Event)}"
|
25
|
+
# number_of_objects(AASM::SupportingClasses::Event).should == event_count + 2 # + Process
|
26
|
+
# number_of_objects(AASM::SupportingClasses::StateTransition).should == transition_count + 2 # + Process
|
33
27
|
|
34
|
-
|
28
|
+
# Models.send(:remove_const, "Process") if Models.const_defined?("Process")
|
29
|
+
# load File.expand_path(File.dirname(__FILE__) + '/../models/not_auto_loaded/process.rb')
|
30
|
+
# machines.size.should == machines_count + 1 # + Process
|
31
|
+
# number_of_objects(AASM::SupportingClasses::State).should == state_count + 3 # + Process
|
32
|
+
# # ObjectSpace.each_object(AASM::SupportingClasses::Event) {|o| puts o.inspect}
|
33
|
+
# puts "event_count = #{number_of_objects(AASM::SupportingClasses::Event)}"
|
34
|
+
# number_of_objects(AASM::SupportingClasses::Event).should == event_count + 2 # + Process
|
35
|
+
# number_of_objects(AASM::SupportingClasses::StateTransition).should == transition_count + 2 # + Process
|
36
|
+
# end
|
37
|
+
|
38
|
+
# end
|
data/spec/unit/new_dsl_spec.rb
CHANGED
@@ -1,24 +1,8 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "the new dsl" do
|
4
4
|
|
5
|
-
|
6
|
-
@process = ProcessWithNewDsl.new
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'should use an initial event' do
|
10
|
-
@process.aasm_current_state.should == :sleeping
|
11
|
-
@process.should be_sleeping
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'should have states and transitions' do
|
15
|
-
@process.flagged.should be_nil
|
16
|
-
@process.start!
|
17
|
-
@process.should be_running
|
18
|
-
@process.flagged.should be_true
|
19
|
-
@process.stop!
|
20
|
-
@process.should be_suspended
|
21
|
-
end
|
5
|
+
let(:process) {ProcessWithNewDsl.new}
|
22
6
|
|
23
7
|
it 'should not conflict with other event or state methods' do
|
24
8
|
lambda {ProcessWithNewDsl.state}.should raise_error(RuntimeError, "wrong state method")
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'active_record'
|
3
2
|
require 'logger'
|
4
3
|
require 'spec_helper'
|
@@ -58,7 +57,7 @@ end
|
|
58
57
|
describe "instance methods" do
|
59
58
|
let(:gate) {Gate.new}
|
60
59
|
|
61
|
-
it "should respond to aasm
|
60
|
+
it "should respond to aasm persistence methods" do
|
62
61
|
gate.should respond_to(:aasm_read_state)
|
63
62
|
gate.should respond_to(:aasm_write_state)
|
64
63
|
gate.should respond_to(:aasm_write_state_without_persistence)
|
@@ -85,16 +84,12 @@ describe "instance methods" do
|
|
85
84
|
gate.aasm_current_state.should be_nil
|
86
85
|
end
|
87
86
|
|
88
|
-
it "should have aasm_ensure_initial_state" do
|
89
|
-
gate.send :aasm_ensure_initial_state
|
90
|
-
end
|
91
|
-
|
92
87
|
it "should call aasm_ensure_initial_state on validation before create" do
|
93
88
|
gate.should_receive(:aasm_ensure_initial_state).and_return(true)
|
94
89
|
gate.valid?
|
95
90
|
end
|
96
91
|
|
97
|
-
it "should call aasm_ensure_initial_state on validation before
|
92
|
+
it "should not call aasm_ensure_initial_state on validation before update" do
|
98
93
|
gate.stub!(:new_record?).and_return(false)
|
99
94
|
gate.should_not_receive(:aasm_ensure_initial_state)
|
100
95
|
gate.valid?
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Payment
|
4
|
+
include AASM
|
5
|
+
aasm do
|
6
|
+
state :initialised, :initial => true
|
7
|
+
state :filled_out
|
8
|
+
state :authorised
|
9
|
+
|
10
|
+
event :fill_out do
|
11
|
+
transitions :from => :initialised, :to => :filled_out
|
12
|
+
end
|
13
|
+
event :authorise do
|
14
|
+
transitions :from => :filled_out, :to => :authorised
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'state machine' do
|
20
|
+
let(:payment) {Payment.new}
|
21
|
+
|
22
|
+
it 'starts with an initial state' do
|
23
|
+
payment.aasm_current_state.should == :initialised
|
24
|
+
# payment.aasm.current_state.should == :initialised # not yet supported
|
25
|
+
payment.should respond_to(:initialised?)
|
26
|
+
payment.should be_initialised
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'allows transitions to other states' do
|
30
|
+
payment.should respond_to(:fill_out)
|
31
|
+
payment.should respond_to(:fill_out!)
|
32
|
+
payment.fill_out!
|
33
|
+
payment.should respond_to(:filled_out?)
|
34
|
+
payment.should be_filled_out
|
35
|
+
|
36
|
+
payment.should respond_to(:authorise)
|
37
|
+
payment.should respond_to(:authorise!)
|
38
|
+
payment.authorise
|
39
|
+
payment.should respond_to(:authorised?)
|
40
|
+
payment.should be_authorised
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'denies transitions to other states' do
|
44
|
+
lambda {payment.authorise}.should raise_error(AASM::InvalidTransition)
|
45
|
+
lambda {payment.authorise!}.should raise_error(AASM::InvalidTransition)
|
46
|
+
payment.fill_out
|
47
|
+
lambda {payment.fill_out}.should raise_error(AASM::InvalidTransition)
|
48
|
+
lambda {payment.fill_out!}.should raise_error(AASM::InvalidTransition)
|
49
|
+
payment.authorise
|
50
|
+
lambda {payment.fill_out}.should raise_error(AASM::InvalidTransition)
|
51
|
+
lambda {payment.fill_out!}.should raise_error(AASM::InvalidTransition)
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'subclassing' do
|
4
|
+
it 'should have the parent states' do
|
5
|
+
Foo.aasm_states.each do |state|
|
6
|
+
FooTwo.aasm_states.should include(state)
|
7
|
+
end
|
8
|
+
Baz.aasm_states.should == Bar.aasm_states
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should not add the child states to the parent machine' do
|
12
|
+
Foo.aasm_states.should_not include(:foo)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have the same events as its parent" do
|
16
|
+
Baz.aasm_events.should == Bar.aasm_events
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -1,51 +1,50 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'adding an event' do
|
4
|
-
|
5
|
-
|
6
|
-
@event = AASM::SupportingClasses::Event.new(:close_order, {:success => :success_callback}) do
|
4
|
+
let(:event) do
|
5
|
+
AASM::SupportingClasses::Event.new(:close_order, {:success => :success_callback}) do
|
7
6
|
transitions :to => :closed, :from => [:open, :received]
|
8
7
|
end
|
9
8
|
end
|
10
9
|
|
11
10
|
it 'should set the name' do
|
12
|
-
|
13
|
-
@event.name.should == :close_order
|
11
|
+
event.name.should == :close_order
|
14
12
|
end
|
15
13
|
|
16
|
-
it 'should set the success
|
17
|
-
|
18
|
-
@event.success.should == :success_callback
|
14
|
+
it 'should set the success callback' do
|
15
|
+
event.success.should == :success_callback
|
19
16
|
end
|
20
17
|
|
21
|
-
it 'should create
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
it 'should create transitions' do
|
19
|
+
transitions = event.all_transitions
|
20
|
+
transitions[0].from.should == :open
|
21
|
+
transitions[0].to.should == :closed
|
22
|
+
transitions[1].from.should == :received
|
23
|
+
transitions[1].to.should == :closed
|
25
24
|
end
|
26
25
|
end
|
27
26
|
|
28
27
|
describe 'transition inspection' do
|
29
|
-
|
30
|
-
|
28
|
+
let(:event) do
|
29
|
+
AASM::SupportingClasses::Event.new(:run) do
|
31
30
|
transitions :to => :running, :from => :sleeping
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
|
-
it 'should support inspecting transitions from states' do
|
36
|
-
|
37
|
-
|
34
|
+
it 'should support inspecting transitions from other states' do
|
35
|
+
event.transitions_from_state(:sleeping).map(&:to).should == [:running]
|
36
|
+
event.transitions_from_state?(:sleeping).should be_true
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
event.transitions_from_state(:cleaning).map(&:to).should == []
|
39
|
+
event.transitions_from_state?(:cleaning).should be_false
|
41
40
|
end
|
42
41
|
|
43
|
-
it 'should support inspecting transitions to states' do
|
44
|
-
|
45
|
-
|
42
|
+
it 'should support inspecting transitions to other states' do
|
43
|
+
event.transitions_to_state(:running).map(&:from).should == [:sleeping]
|
44
|
+
event.transitions_to_state?(:running).should be_true
|
46
45
|
|
47
|
-
|
48
|
-
|
46
|
+
event.transitions_to_state(:cleaning).map(&:to).should == []
|
47
|
+
event.transitions_to_state?(:cleaning).should be_false
|
49
48
|
end
|
50
49
|
end
|
51
50
|
|
@@ -148,3 +147,57 @@ describe 'executing the success callback' do
|
|
148
147
|
model.with_proc!
|
149
148
|
end
|
150
149
|
end
|
150
|
+
|
151
|
+
describe 'parametrised events' do
|
152
|
+
let(:pe) {ParametrisedEvent.new}
|
153
|
+
|
154
|
+
it 'should transition to specified next state (sleeping to showering)' do
|
155
|
+
pe.wakeup!(:showering)
|
156
|
+
pe.aasm_current_state.should == :showering
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should transition to specified next state (sleeping to working)' do
|
160
|
+
pe.wakeup!(:working)
|
161
|
+
pe.aasm_current_state.should == :working
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'should transition to default (first or showering) state' do
|
165
|
+
pe.wakeup!
|
166
|
+
pe.aasm_current_state.should == :showering
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'should transition to default state when on_transition invoked' do
|
170
|
+
pe.dress!(nil, 'purple', 'dressy')
|
171
|
+
pe.aasm_current_state.should == :working
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should call on_transition method with args' do
|
175
|
+
pe.wakeup!(:showering)
|
176
|
+
pe.should_receive(:wear_clothes).with('blue', 'jeans')
|
177
|
+
pe.dress!(:working, 'blue', 'jeans')
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should call on_transition proc' do
|
181
|
+
pe.wakeup!(:showering)
|
182
|
+
pe.should_receive(:wear_clothes).with('purple', 'slacks')
|
183
|
+
pe.dress!(:dating, 'purple', 'slacks')
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'should call on_transition with an array of methods' do
|
187
|
+
pe.wakeup!(:showering)
|
188
|
+
pe.should_receive(:condition_hair)
|
189
|
+
pe.should_receive(:fix_hair)
|
190
|
+
pe.dress!(:prettying_up)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe 'event firing without persistence' do
|
195
|
+
it 'should attempt to persist if aasm_write_state is defined' do
|
196
|
+
foo = Foo.new
|
197
|
+
def foo.aasm_write_state; end
|
198
|
+
foo.should be_open
|
199
|
+
|
200
|
+
foo.should_receive(:aasm_write_state_without_persistence)
|
201
|
+
foo.close
|
202
|
+
end
|
203
|
+
end
|