aasm 3.0.13 → 3.0.14
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 +10 -6
- data/README.md +217 -109
- data/aasm.gemspec +1 -0
- data/lib/aasm/persistence.rb +2 -0
- data/lib/aasm/persistence/active_record_persistence.rb +2 -71
- data/lib/aasm/persistence/base.rb +46 -0
- data/lib/aasm/persistence/mongoid_persistence.rb +3 -92
- data/lib/aasm/persistence/read_state.rb +40 -0
- data/lib/aasm/supporting_classes/event.rb +6 -2
- data/lib/aasm/supporting_classes/localizer.rb +15 -13
- data/lib/aasm/supporting_classes/state.rb +8 -0
- data/lib/aasm/version.rb +1 -1
- data/spec/models/auth_machine.rb +84 -0
- data/spec/models/callback_new_dsl.rb +38 -0
- data/spec/models/callback_old_dsl.rb +36 -0
- data/spec/models/persistence.rb +71 -0
- data/spec/spec_helpers/models_spec_helper.rb +0 -85
- data/spec/unit/aasm_spec.rb +1 -1
- data/spec/unit/callbacks_new_dsl_spec.rb +33 -0
- data/spec/unit/callbacks_old_dsl_spec.rb +33 -0
- data/spec/unit/complex_example_spec.rb +75 -0
- data/spec/unit/event_spec.rb +31 -12
- data/spec/unit/inspection_spec.rb +7 -0
- data/spec/unit/persistence/active_record_persistence_spec.rb +228 -0
- metadata +41 -29
- data/spec/unit/active_record_persistence_spec.rb +0 -334
- data/spec/unit/auth_machine_spec.rb +0 -83
- data/spec/unit/before_after_callbacks_spec.rb +0 -79
- data/spec/unit/conversation_spec.rb +0 -7
@@ -0,0 +1,71 @@
|
|
1
|
+
class Gate < ActiveRecord::Base
|
2
|
+
include AASM
|
3
|
+
|
4
|
+
# Fake this column for testing purposes
|
5
|
+
attr_accessor :aasm_state
|
6
|
+
|
7
|
+
aasm do
|
8
|
+
state :opened
|
9
|
+
state :closed
|
10
|
+
|
11
|
+
event :view do
|
12
|
+
transitions :to => :read, :from => [:needs_attention]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Reader < ActiveRecord::Base
|
18
|
+
def aasm_read_state
|
19
|
+
"fi"
|
20
|
+
end
|
21
|
+
include AASM
|
22
|
+
end
|
23
|
+
|
24
|
+
class Writer < ActiveRecord::Base
|
25
|
+
def aasm_write_state(state)
|
26
|
+
"fo"
|
27
|
+
end
|
28
|
+
include AASM
|
29
|
+
end
|
30
|
+
|
31
|
+
class Transient < ActiveRecord::Base
|
32
|
+
def aasm_write_state_without_persistence(state)
|
33
|
+
"fum"
|
34
|
+
end
|
35
|
+
include AASM
|
36
|
+
end
|
37
|
+
|
38
|
+
class Simple < ActiveRecord::Base
|
39
|
+
include AASM
|
40
|
+
aasm_column :status
|
41
|
+
aasm_state :unknown_scope
|
42
|
+
aasm_state :new
|
43
|
+
end
|
44
|
+
|
45
|
+
class SimpleNewDsl < ActiveRecord::Base
|
46
|
+
include AASM
|
47
|
+
aasm :column => :status
|
48
|
+
aasm do
|
49
|
+
state :unknown_scope
|
50
|
+
state :new
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Derivate < Simple
|
55
|
+
end
|
56
|
+
|
57
|
+
class DerivateNewDsl < SimpleNewDsl
|
58
|
+
end
|
59
|
+
|
60
|
+
class Thief < ActiveRecord::Base
|
61
|
+
if ActiveRecord::VERSION::MAJOR >= 3
|
62
|
+
self.table_name = 'thieves'
|
63
|
+
else
|
64
|
+
set_table_name "thieves"
|
65
|
+
end
|
66
|
+
include AASM
|
67
|
+
aasm_initial_state Proc.new { |thief| thief.skilled ? :rich : :jailed }
|
68
|
+
aasm_state :rich
|
69
|
+
aasm_state :jailed
|
70
|
+
attr_accessor :skilled, :aasm_state
|
71
|
+
end
|
@@ -76,91 +76,6 @@ class Argument
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
-
class AuthMachine
|
80
|
-
include AASM
|
81
|
-
|
82
|
-
attr_accessor :activation_code, :activated_at, :deleted_at
|
83
|
-
|
84
|
-
aasm do
|
85
|
-
state :passive
|
86
|
-
state :pending, :initial => true, :enter => :make_activation_code
|
87
|
-
state :active, :enter => :do_activate
|
88
|
-
state :suspended
|
89
|
-
state :deleted, :enter => :do_delete, :exit => :do_undelete
|
90
|
-
state :waiting
|
91
|
-
|
92
|
-
event :register do
|
93
|
-
transitions :from => :passive, :to => :pending, :guard => Proc.new {|u| u.can_register? }
|
94
|
-
end
|
95
|
-
|
96
|
-
event :activate do
|
97
|
-
transitions :from => :pending, :to => :active
|
98
|
-
end
|
99
|
-
|
100
|
-
event :suspend do
|
101
|
-
transitions :from => [:passive, :pending, :active], :to => :suspended
|
102
|
-
end
|
103
|
-
|
104
|
-
event :delete do
|
105
|
-
transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
|
106
|
-
end
|
107
|
-
|
108
|
-
# a dummy event that can never happen
|
109
|
-
event :unpassify do
|
110
|
-
transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false }
|
111
|
-
end
|
112
|
-
|
113
|
-
event :unsuspend do
|
114
|
-
transitions :from => :suspended, :to => :active, :guard => Proc.new {|u| u.has_activated? }
|
115
|
-
transitions :from => :suspended, :to => :pending, :guard => Proc.new {|u| u.has_activation_code? }
|
116
|
-
transitions :from => :suspended, :to => :passive
|
117
|
-
end
|
118
|
-
|
119
|
-
event :wait do
|
120
|
-
transitions :from => :suspended, :to => :waiting, :guard => :if_polite?
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def initialize
|
125
|
-
# the AR backend uses a before_validate_on_create :aasm_ensure_initial_state
|
126
|
-
# lets do something similar here for testing purposes.
|
127
|
-
aasm_enter_initial_state
|
128
|
-
end
|
129
|
-
|
130
|
-
def make_activation_code
|
131
|
-
@activation_code = 'moo'
|
132
|
-
end
|
133
|
-
|
134
|
-
def do_activate
|
135
|
-
@activated_at = Time.now
|
136
|
-
@activation_code = nil
|
137
|
-
end
|
138
|
-
|
139
|
-
def do_delete
|
140
|
-
@deleted_at = Time.now
|
141
|
-
end
|
142
|
-
|
143
|
-
def do_undelete
|
144
|
-
@deleted_at = false
|
145
|
-
end
|
146
|
-
|
147
|
-
def can_register?
|
148
|
-
true
|
149
|
-
end
|
150
|
-
|
151
|
-
def has_activated?
|
152
|
-
!!@activated_at
|
153
|
-
end
|
154
|
-
|
155
|
-
def has_activation_code?
|
156
|
-
!!@activation_code
|
157
|
-
end
|
158
|
-
|
159
|
-
def if_polite?(phrase = nil)
|
160
|
-
phrase == :please
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
79
|
class ThisNameBetterNotBeInUse
|
165
80
|
include AASM
|
166
81
|
|
data/spec/unit/aasm_spec.rb
CHANGED
@@ -41,7 +41,7 @@ end
|
|
41
41
|
|
42
42
|
|
43
43
|
describe AASM, '- aasm_states_for_select' do
|
44
|
-
it "should return a select friendly array of states
|
44
|
+
it "should return a select friendly array of states" do
|
45
45
|
Foo.aasm_states_for_select.should == [['Open', 'open'], ['Closed', 'closed']]
|
46
46
|
end
|
47
47
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'callbacks for the new DSL' do
|
4
|
+
before(:each) do
|
5
|
+
@callback = CallbackNewDsl.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should get close callbacks" do
|
9
|
+
@callback.should_receive(:before).once.ordered
|
10
|
+
@callback.should_receive(:before_exit_open).once.ordered # these should be before the state changes
|
11
|
+
@callback.should_receive(:before_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
|
+
|
20
|
+
it "should get open callbacks" do
|
21
|
+
@callback.close!
|
22
|
+
|
23
|
+
@callback.should_receive(:before).once.ordered
|
24
|
+
@callback.should_receive(:before_exit_closed).once.ordered # these should be before the state changes
|
25
|
+
@callback.should_receive(:before_enter_open).once.ordered
|
26
|
+
@callback.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
|
27
|
+
@callback.should_receive(:after_exit_closed).once.ordered # these should be after the state changes
|
28
|
+
@callback.should_receive(:after_enter_open).once.ordered
|
29
|
+
@callback.should_receive(:after).once.ordered
|
30
|
+
|
31
|
+
@callback.open!
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'callbacks for the old DSL' do
|
4
|
+
before(:each) do
|
5
|
+
@callback = CallbackOldDsl.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should get close callbacks" do
|
9
|
+
@callback.should_receive(:before).once.ordered
|
10
|
+
@callback.should_receive(:before_exit_open).once.ordered # these should be before the state changes
|
11
|
+
@callback.should_receive(:before_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
|
+
|
20
|
+
it "should get open callbacks" do
|
21
|
+
@callback.close!
|
22
|
+
|
23
|
+
@callback.should_receive(:before).once.ordered
|
24
|
+
@callback.should_receive(:before_exit_closed).once.ordered # these should be before the state changes
|
25
|
+
@callback.should_receive(:before_enter_open).once.ordered
|
26
|
+
@callback.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
|
27
|
+
@callback.should_receive(:after_exit_closed).once.ordered # these should be after the state changes
|
28
|
+
@callback.should_receive(:after_enter_open).once.ordered
|
29
|
+
@callback.should_receive(:after).once.ordered
|
30
|
+
|
31
|
+
@callback.open!
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'AuthMachine on initialization' do
|
4
|
+
let(:auth) {AuthMachine.new}
|
5
|
+
|
6
|
+
it 'should be in the pending state' do
|
7
|
+
auth.aasm_current_state.should == :pending
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should have an activation code' do
|
11
|
+
auth.has_activation_code?.should be_true
|
12
|
+
auth.activation_code.should_not be_nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'AuthMachine when being unsuspended' do
|
17
|
+
let(:auth) {AuthMachine.new}
|
18
|
+
|
19
|
+
it 'should be able to be unsuspended' do
|
20
|
+
auth.activate!
|
21
|
+
auth.suspend!
|
22
|
+
auth.may_unsuspend?.should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should not be able to be unsuspended into active' do
|
26
|
+
auth.suspend!
|
27
|
+
auth.may_unsuspend?(:active).should_not be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should be able to be unsuspended into active if polite' do
|
31
|
+
auth.suspend!
|
32
|
+
auth.may_wait?(:waiting, :please).should be_true
|
33
|
+
auth.wait!(nil, :please)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should not be able to be unsuspended into active if not polite' do
|
37
|
+
auth.suspend!
|
38
|
+
auth.may_wait?(:waiting).should_not be_true
|
39
|
+
auth.may_wait?(:waiting, :rude).should_not be_true
|
40
|
+
lambda {auth.wait!(nil, :rude)}.should raise_error(AASM::InvalidTransition)
|
41
|
+
lambda {auth.wait!}.should raise_error(AASM::InvalidTransition)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should not be able to be unpassified' do
|
45
|
+
auth.activate!
|
46
|
+
auth.suspend!
|
47
|
+
auth.unsuspend!
|
48
|
+
|
49
|
+
auth.may_unpassify?.should_not be_true
|
50
|
+
lambda {auth.unpassify!}.should raise_error(AASM::InvalidTransition)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should be active if previously activated' do
|
54
|
+
auth.activate!
|
55
|
+
auth.suspend!
|
56
|
+
auth.unsuspend!
|
57
|
+
|
58
|
+
auth.aasm_current_state.should == :active
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should be pending if not previously activated, but an activation code is present' do
|
62
|
+
auth.suspend!
|
63
|
+
auth.unsuspend!
|
64
|
+
|
65
|
+
auth.aasm_current_state.should == :pending
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should be passive if not previously activated and there is no activation code' do
|
69
|
+
auth.activation_code = nil
|
70
|
+
auth.suspend!
|
71
|
+
auth.unsuspend!
|
72
|
+
|
73
|
+
auth.aasm_current_state.should == :passive
|
74
|
+
end
|
75
|
+
end
|
data/spec/unit/event_spec.rb
CHANGED
@@ -1,25 +1,21 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
before(:each) do
|
5
|
-
@name = :close_order
|
6
|
-
@success = :success_callback
|
7
|
-
end
|
3
|
+
describe 'adding an event' do
|
8
4
|
|
9
5
|
def new_event
|
10
|
-
@event = AASM::SupportingClasses::Event.new(
|
6
|
+
@event = AASM::SupportingClasses::Event.new(:close_order, {:success => :success_callback}) do
|
11
7
|
transitions :to => :closed, :from => [:open, :received]
|
12
8
|
end
|
13
9
|
end
|
14
10
|
|
15
11
|
it 'should set the name' do
|
16
12
|
new_event
|
17
|
-
@event.name.should ==
|
13
|
+
@event.name.should == :close_order
|
18
14
|
end
|
19
15
|
|
20
16
|
it 'should set the success option' do
|
21
17
|
new_event
|
22
|
-
@event.success.should ==
|
18
|
+
@event.success.should == :success_callback
|
23
19
|
end
|
24
20
|
|
25
21
|
it 'should create StateTransitions' do
|
@@ -29,7 +25,31 @@ describe AASM::SupportingClasses::Event do
|
|
29
25
|
end
|
30
26
|
end
|
31
27
|
|
32
|
-
describe
|
28
|
+
describe 'transition inspection' do
|
29
|
+
before do
|
30
|
+
@event = AASM::SupportingClasses::Event.new(:run) do
|
31
|
+
transitions :to => :running, :from => :sleeping
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should support inspecting transitions from states' do
|
36
|
+
@event.transitions_from_state(:sleeping).map(&:to).should == [:running]
|
37
|
+
@event.transitions_from_state?(:sleeping).should be_true
|
38
|
+
|
39
|
+
@event.transitions_from_state(:cleaning).map(&:to).should == []
|
40
|
+
@event.transitions_from_state?(:cleaning).should be_false
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should support inspecting transitions to states' do
|
44
|
+
@event.transitions_to_state(:running).map(&:from).should == [:sleeping]
|
45
|
+
@event.transitions_to_state?(:running).should be_true
|
46
|
+
|
47
|
+
@event.transitions_to_state(:cleaning).map(&:to).should == []
|
48
|
+
@event.transitions_to_state?(:cleaning).should be_false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'firing an event' do
|
33
53
|
it 'should return nil if the transitions are empty' do
|
34
54
|
obj = mock('object')
|
35
55
|
obj.stub!(:aasm_current_state)
|
@@ -49,7 +69,6 @@ describe AASM::SupportingClasses::Event, 'when firing an event' do
|
|
49
69
|
event.fire(obj).should == :closed
|
50
70
|
end
|
51
71
|
|
52
|
-
|
53
72
|
it 'should call the guard with the params passed in' do
|
54
73
|
event = AASM::SupportingClasses::Event.new(:event) do
|
55
74
|
transitions :to => :closed, :from => [:open, :received], :guard => :guard_fn
|
@@ -64,7 +83,7 @@ describe AASM::SupportingClasses::Event, 'when firing an event' do
|
|
64
83
|
|
65
84
|
end
|
66
85
|
|
67
|
-
describe
|
86
|
+
describe 'executing the success callback' do
|
68
87
|
|
69
88
|
it "should send the success callback if it's a symbol" do
|
70
89
|
ThisNameBetterNotBeInUse.instance_eval {
|
@@ -0,0 +1,228 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
require 'logger'
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
load_schema
|
7
|
+
|
8
|
+
# if you want to see the statements while running the spec enable the following line
|
9
|
+
# ActiveRecord::Base.logger = Logger.new(STDERR)
|
10
|
+
|
11
|
+
shared_examples_for "aasm model" do
|
12
|
+
it "should include persistence mixins" do
|
13
|
+
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence)
|
14
|
+
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "class methods for classes without own read or write state" do
|
19
|
+
let(:klass) {Gate}
|
20
|
+
it_should_behave_like "aasm model"
|
21
|
+
it "should include all persistence mixins" do
|
22
|
+
klass.included_modules.should be_include(AASM::Persistence::ReadState)
|
23
|
+
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
|
24
|
+
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "class methods for classes with own read state" do
|
29
|
+
let(:klass) {Reader}
|
30
|
+
it_should_behave_like "aasm model"
|
31
|
+
it "should include all persistence mixins but read state" do
|
32
|
+
klass.included_modules.should_not be_include(AASM::Persistence::ReadState)
|
33
|
+
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
|
34
|
+
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "class methods for classes with own write state" do
|
39
|
+
let(:klass) {Writer}
|
40
|
+
it_should_behave_like "aasm model"
|
41
|
+
it "should include include all persistence mixins but write state" do
|
42
|
+
klass.included_modules.should be_include(AASM::Persistence::ReadState)
|
43
|
+
klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
|
44
|
+
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "class methods for classes without persistence" do
|
49
|
+
let(:klass) {Transient}
|
50
|
+
it_should_behave_like "aasm model"
|
51
|
+
it "should include all mixins but persistence" do
|
52
|
+
klass.included_modules.should be_include(AASM::Persistence::ReadState)
|
53
|
+
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
|
54
|
+
klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "instance methods" do
|
59
|
+
let(:gate) {Gate.new}
|
60
|
+
|
61
|
+
it "should respond to aasm states" do
|
62
|
+
gate.should respond_to(:aasm_read_state)
|
63
|
+
gate.should respond_to(:aasm_write_state)
|
64
|
+
gate.should respond_to(:aasm_write_state_without_persistence)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return the initial state when new and the aasm field is nil" do
|
68
|
+
gate.aasm_current_state.should == :opened
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should return the aasm column when new and the aasm field is not nil" do
|
72
|
+
gate.aasm_state = "closed"
|
73
|
+
gate.aasm_current_state.should == :closed
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should return the aasm column when not new and the aasm_column is not nil" do
|
77
|
+
gate.stub!(:new_record?).and_return(false)
|
78
|
+
gate.aasm_state = "state"
|
79
|
+
gate.aasm_current_state.should == :state
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should allow a nil state" do
|
83
|
+
gate.stub!(:new_record?).and_return(false)
|
84
|
+
gate.aasm_state = nil
|
85
|
+
gate.aasm_current_state.should be_nil
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should have aasm_ensure_initial_state" do
|
89
|
+
gate.send :aasm_ensure_initial_state
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should call aasm_ensure_initial_state on validation before create" do
|
93
|
+
gate.should_receive(:aasm_ensure_initial_state).and_return(true)
|
94
|
+
gate.valid?
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should call aasm_ensure_initial_state on validation before create" do
|
98
|
+
gate.stub!(:new_record?).and_return(false)
|
99
|
+
gate.should_not_receive(:aasm_ensure_initial_state)
|
100
|
+
gate.valid?
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'subclasses' do
|
106
|
+
it "should have the same states as its parent class" do
|
107
|
+
Derivate.aasm_states.should == Simple.aasm_states
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should have the same events as its parent class" do
|
111
|
+
Derivate.aasm_events.should == Simple.aasm_events
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should have the same column as its parent class" do
|
115
|
+
Derivate.aasm_column.should == :status
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should have the same column as its parent even for the new dsl" do
|
119
|
+
SimpleNewDsl.aasm_column.should == :status
|
120
|
+
DerivateNewDsl.aasm_column.should == :status
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "named scopes with the old DSL" do
|
125
|
+
|
126
|
+
context "Does not already respond_to? the scope name" do
|
127
|
+
it "should add a scope" do
|
128
|
+
Simple.should respond_to(:unknown_scope)
|
129
|
+
Simple.unknown_scope.class.should == ActiveRecord::Relation
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "Already respond_to? the scope name" do
|
134
|
+
it "should not add a scope" do
|
135
|
+
Simple.should respond_to(:new)
|
136
|
+
Simple.new.class.should == Simple
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "named scopes with the new DSL" do
|
143
|
+
|
144
|
+
context "Does not already respond_to? the scope name" do
|
145
|
+
it "should add a scope" do
|
146
|
+
SimpleNewDsl.should respond_to(:unknown_scope)
|
147
|
+
SimpleNewDsl.unknown_scope.class.should == ActiveRecord::Relation
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context "Already respond_to? the scope name" do
|
152
|
+
it "should not add a scope" do
|
153
|
+
SimpleNewDsl.should respond_to(:new)
|
154
|
+
SimpleNewDsl.new.class.should == SimpleNewDsl
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
describe 'initial states' do
|
161
|
+
|
162
|
+
it 'should support conditions' do
|
163
|
+
Thief.new(:skilled => true).aasm_current_state.should == :rich
|
164
|
+
Thief.new(:skilled => false).aasm_current_state.should == :jailed
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe 'transitions with persistence' do
|
169
|
+
|
170
|
+
it 'should not store states for invalid models' do
|
171
|
+
validator = Validator.create(:name => 'name')
|
172
|
+
validator.should be_valid
|
173
|
+
validator.should be_sleeping
|
174
|
+
|
175
|
+
validator.name = nil
|
176
|
+
validator.should_not be_valid
|
177
|
+
validator.run!.should be_false
|
178
|
+
validator.should be_sleeping
|
179
|
+
|
180
|
+
validator.reload
|
181
|
+
validator.should_not be_running
|
182
|
+
validator.should be_sleeping
|
183
|
+
|
184
|
+
validator.name = 'another name'
|
185
|
+
validator.should be_valid
|
186
|
+
validator.run!.should be_true
|
187
|
+
validator.should be_running
|
188
|
+
|
189
|
+
validator.reload
|
190
|
+
validator.should be_running
|
191
|
+
validator.should_not be_sleeping
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'should store states for invalid models if configured' do
|
195
|
+
persistor = InvalidPersistor.create(:name => 'name')
|
196
|
+
persistor.should be_valid
|
197
|
+
persistor.should be_sleeping
|
198
|
+
|
199
|
+
persistor.name = nil
|
200
|
+
persistor.should_not be_valid
|
201
|
+
persistor.run!.should be_true
|
202
|
+
persistor.should be_running
|
203
|
+
|
204
|
+
persistor = InvalidPersistor.find(persistor.id)
|
205
|
+
persistor.valid?
|
206
|
+
persistor.should be_valid
|
207
|
+
persistor.should be_running
|
208
|
+
persistor.should_not be_sleeping
|
209
|
+
|
210
|
+
persistor.reload
|
211
|
+
persistor.should be_running
|
212
|
+
persistor.should_not be_sleeping
|
213
|
+
end
|
214
|
+
|
215
|
+
describe 'transactions' do
|
216
|
+
it 'should rollback all changes' do
|
217
|
+
worker = Worker.create!(:name => 'worker', :status => 'sleeping')
|
218
|
+
transactor = Transactor.create!(:name => 'transactor', :worker => worker)
|
219
|
+
transactor.should be_sleeping
|
220
|
+
worker.status.should == 'sleeping'
|
221
|
+
|
222
|
+
lambda {transactor.run!}.should raise_error(StandardError, 'failed on purpose')
|
223
|
+
transactor.should be_running
|
224
|
+
worker.reload.status.should == 'sleeping'
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|