aasm 4.2.0 → 4.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 +4 -1
- data/Gemfile +2 -2
- data/PLANNED_CHANGES.md +24 -4
- data/README.md +75 -5
- data/lib/aasm/aasm.rb +50 -36
- data/lib/aasm/base.rb +36 -18
- data/lib/aasm/core/event.rb +6 -5
- data/lib/aasm/core/state.rb +3 -2
- data/lib/aasm/core/transition.rb +5 -4
- data/lib/aasm/errors.rb +7 -4
- data/lib/aasm/instance_base.rb +14 -13
- data/lib/aasm/localizer.rb +1 -1
- data/lib/aasm/persistence/active_record_persistence.rb +41 -66
- data/lib/aasm/persistence/base.rb +7 -7
- data/lib/aasm/persistence/mongo_mapper_persistence.rb +34 -51
- data/lib/aasm/persistence/mongoid_persistence.rb +15 -36
- data/lib/aasm/persistence/plain_persistence.rb +8 -7
- data/lib/aasm/persistence/sequel_persistence.rb +12 -10
- data/lib/aasm/state_machine.rb +11 -6
- data/lib/aasm/version.rb +1 -1
- data/spec/database.rb +27 -1
- data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
- data/spec/models/active_record/complex_active_record_example.rb +33 -0
- data/spec/models/active_record/derivate_new_dsl.rb +4 -0
- data/spec/models/active_record/false_state.rb +18 -0
- data/spec/models/active_record/gate.rb +20 -0
- data/spec/models/active_record/no_direct_assignment.rb +11 -0
- data/spec/models/active_record/no_scope.rb +11 -0
- data/spec/models/active_record/provided_and_persisted_state.rb +3 -3
- data/spec/models/active_record/simple_new_dsl.rb +9 -0
- data/spec/models/active_record/thief.rb +15 -0
- data/spec/models/active_record/with_enum.rb +20 -0
- data/spec/models/active_record/with_false_enum.rb +16 -0
- data/spec/models/active_record/with_true_enum.rb +20 -0
- data/spec/models/basic_two_state_machines_example.rb +25 -0
- data/spec/models/callbacks/basic_multiple.rb +75 -0
- data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
- data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
- data/spec/models/callbacks/private_method_multiple.rb +44 -0
- data/spec/models/callbacks/with_args_multiple.rb +61 -0
- data/spec/models/callbacks/{with_state_args.rb → with_state_arg.rb} +0 -0
- data/spec/models/callbacks/with_state_arg_multiple.rb +26 -0
- data/spec/models/complex_example.rb +134 -0
- data/spec/models/conversation.rb +47 -1
- data/spec/models/foo.rb +57 -0
- data/spec/models/foo_callback_multiple.rb +45 -0
- data/spec/models/guardian_multiple.rb +48 -0
- data/spec/models/initial_state_proc.rb +16 -0
- data/spec/models/invalid_persistor.rb +15 -0
- data/spec/models/mongo_mapper/complex_mongo_mapper_example.rb +37 -0
- data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +11 -0
- data/spec/models/mongo_mapper/simple_mongo_mapper.rb +12 -0
- data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +13 -0
- data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
- data/spec/models/mongoid/no_scope_mongoid.rb +11 -0
- data/spec/models/mongoid/simple_mongoid.rb +12 -0
- data/spec/models/mongoid/simple_new_dsl_mongoid.rb +13 -0
- data/spec/models/no_initial_state.rb +13 -0
- data/spec/models/parametrised_event.rb +1 -1
- data/spec/models/parametrised_event_multiple.rb +29 -0
- data/spec/models/provided_state.rb +3 -3
- data/spec/models/sequel/complex_sequel_example.rb +45 -0
- data/spec/models/sequel/sequel_multiple.rb +25 -0
- data/spec/models/sequel/sequel_simple.rb +25 -0
- data/spec/models/simple_multiple_example.rb +30 -0
- data/spec/models/sub_class.rb +4 -0
- data/spec/models/sub_class_with_more_states.rb +11 -0
- data/spec/models/super_class.rb +28 -0
- data/spec/models/transactor.rb +27 -0
- data/spec/models/valid_state_name.rb +12 -0
- data/spec/models/validator.rb +39 -0
- data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
- data/spec/unit/callback_multiple_spec.rb +295 -0
- data/spec/unit/callbacks_spec.rb +1 -1
- data/spec/unit/complex_multiple_example_spec.rb +99 -0
- data/spec/unit/edge_cases_spec.rb +16 -0
- data/spec/unit/event_multiple_spec.rb +73 -0
- data/spec/unit/event_spec.rb +11 -6
- data/spec/unit/guard_multiple_spec.rb +60 -0
- data/spec/unit/initial_state_multiple_spec.rb +15 -0
- data/spec/unit/inspection_multiple_spec.rb +201 -0
- data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +560 -0
- data/spec/unit/persistence/active_record_persistence_spec.rb +17 -12
- data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +146 -0
- data/spec/unit/persistence/{mongo_mapper_persistance_spec.rb → mongo_mapper_persistence_spec.rb} +7 -49
- data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +127 -0
- data/spec/unit/persistence/mongoid_persistence_spec.rb +79 -0
- data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +153 -0
- data/spec/unit/persistence/sequel_persistence_spec.rb +7 -24
- data/spec/unit/reloading_spec.rb +1 -1
- data/spec/unit/simple_multiple_example_spec.rb +63 -0
- data/spec/unit/state_spec.rb +3 -1
- data/spec/unit/subclassing_multiple_spec.rb +39 -0
- data/spec/unit/transition_spec.rb +31 -22
- metadata +73 -9
- data/spec/unit/persistence/mongoid_persistance_spec.rb +0 -146
@@ -86,3 +86,137 @@ class ComplexExample
|
|
86
86
|
phrase == :please
|
87
87
|
end
|
88
88
|
end
|
89
|
+
|
90
|
+
class ComplexExampleMultiple
|
91
|
+
include AASM
|
92
|
+
|
93
|
+
attr_accessor :activation_code, :activated_at, :deleted_at
|
94
|
+
|
95
|
+
aasm(:left) do
|
96
|
+
state :passive
|
97
|
+
state :pending, :initial => true, :before_enter => :make_activation_code
|
98
|
+
state :active, :before_enter => :do_activate
|
99
|
+
state :suspended
|
100
|
+
state :deleted, :before_enter => :do_delete#, :exit => :do_undelete
|
101
|
+
state :waiting
|
102
|
+
|
103
|
+
event :left_register do
|
104
|
+
transitions :from => :passive, :to => :pending do
|
105
|
+
guard do
|
106
|
+
can_register?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
event :left_activate do
|
112
|
+
transitions :from => :pending, :to => :active
|
113
|
+
end
|
114
|
+
|
115
|
+
event :left_suspend do
|
116
|
+
transitions :from => [:passive, :pending, :active], :to => :suspended
|
117
|
+
end
|
118
|
+
|
119
|
+
event :left_delete do
|
120
|
+
transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
|
121
|
+
end
|
122
|
+
|
123
|
+
# a dummy event that can never happen
|
124
|
+
event :left_unpassify do
|
125
|
+
transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false }
|
126
|
+
end
|
127
|
+
|
128
|
+
event :left_unsuspend do
|
129
|
+
transitions :from => :suspended, :to => :active, :guard => Proc.new { has_activated? }
|
130
|
+
transitions :from => :suspended, :to => :pending, :guard => :has_activation_code?
|
131
|
+
transitions :from => :suspended, :to => :passive
|
132
|
+
end
|
133
|
+
|
134
|
+
event :left_wait do
|
135
|
+
transitions :from => :suspended, :to => :waiting, :guard => :if_polite?
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
aasm(:right) do
|
140
|
+
state :passive
|
141
|
+
state :pending, :initial => true, :before_enter => :make_activation_code
|
142
|
+
state :active, :before_enter => :do_activate
|
143
|
+
state :suspended
|
144
|
+
state :deleted, :before_enter => :do_delete#, :exit => :do_undelete
|
145
|
+
state :waiting
|
146
|
+
|
147
|
+
event :right_register do
|
148
|
+
transitions :from => :passive, :to => :pending do
|
149
|
+
guard do
|
150
|
+
can_register?
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
event :right_activate do
|
156
|
+
transitions :from => :pending, :to => :active
|
157
|
+
end
|
158
|
+
|
159
|
+
event :right_suspend do
|
160
|
+
transitions :from => [:passive, :pending, :active], :to => :suspended
|
161
|
+
end
|
162
|
+
|
163
|
+
event :right_delete do
|
164
|
+
transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
|
165
|
+
end
|
166
|
+
|
167
|
+
# a dummy event that can never happen
|
168
|
+
event :right_unpassify do
|
169
|
+
transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false }
|
170
|
+
end
|
171
|
+
|
172
|
+
event :right_unsuspend do
|
173
|
+
transitions :from => :suspended, :to => :active, :guard => Proc.new { has_activated? }
|
174
|
+
transitions :from => :suspended, :to => :pending, :guard => :has_activation_code?
|
175
|
+
transitions :from => :suspended, :to => :passive
|
176
|
+
end
|
177
|
+
|
178
|
+
event :right_wait do
|
179
|
+
transitions :from => :suspended, :to => :waiting, :guard => :if_polite?
|
180
|
+
end
|
181
|
+
end # right
|
182
|
+
|
183
|
+
def initialize
|
184
|
+
# the AR backend uses a before_validate_on_create :aasm_ensure_initial_state
|
185
|
+
# lets do something similar here for testing purposes.
|
186
|
+
aasm(:left).enter_initial_state
|
187
|
+
aasm(:right).enter_initial_state
|
188
|
+
end
|
189
|
+
|
190
|
+
def make_activation_code
|
191
|
+
@activation_code = @activation_code ? @activation_code + '2' : '1'
|
192
|
+
end
|
193
|
+
|
194
|
+
def do_activate
|
195
|
+
@activated_at = Time.now
|
196
|
+
@activation_code = nil
|
197
|
+
end
|
198
|
+
|
199
|
+
def do_delete
|
200
|
+
@deleted_at = Time.now
|
201
|
+
end
|
202
|
+
|
203
|
+
def do_undelete
|
204
|
+
@deleted_at = false
|
205
|
+
end
|
206
|
+
|
207
|
+
def can_register?
|
208
|
+
true
|
209
|
+
end
|
210
|
+
|
211
|
+
def has_activated?
|
212
|
+
!!@activated_at
|
213
|
+
end
|
214
|
+
|
215
|
+
def has_activation_code?
|
216
|
+
!!@activation_code
|
217
|
+
end
|
218
|
+
|
219
|
+
def if_polite?(phrase = nil)
|
220
|
+
phrase == :please
|
221
|
+
end
|
222
|
+
end
|
data/spec/models/conversation.rb
CHANGED
@@ -34,8 +34,8 @@ class Conversation
|
|
34
34
|
@persister = persister
|
35
35
|
end
|
36
36
|
|
37
|
-
|
38
37
|
private
|
38
|
+
|
39
39
|
def aasm_read_state
|
40
40
|
@persister.read_state
|
41
41
|
end
|
@@ -43,5 +43,51 @@ class Conversation
|
|
43
43
|
def aasm_write_state(state)
|
44
44
|
@persister.write_state(state)
|
45
45
|
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class ConversationMultiple
|
49
|
+
include AASM
|
50
|
+
|
51
|
+
aasm(:left) do
|
52
|
+
state :needs_attention, :initial => true
|
53
|
+
state :read
|
54
|
+
state :closed
|
55
|
+
state :awaiting_response
|
56
|
+
state :junk
|
57
|
+
|
58
|
+
event :new_message do
|
59
|
+
end
|
60
|
+
|
61
|
+
event :view do
|
62
|
+
transitions :to => :read, :from => [:needs_attention]
|
63
|
+
end
|
64
|
+
|
65
|
+
event :reply do
|
66
|
+
end
|
67
|
+
|
68
|
+
event :close do
|
69
|
+
transitions :to => :closed, :from => [:read, :awaiting_response]
|
70
|
+
end
|
71
|
+
|
72
|
+
event :junk do
|
73
|
+
transitions :to => :junk, :from => [:read]
|
74
|
+
end
|
75
|
+
|
76
|
+
event :unjunk do
|
77
|
+
end
|
78
|
+
end
|
46
79
|
|
80
|
+
def initialize(persister)
|
81
|
+
@persister = persister
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def aasm_read_state
|
87
|
+
@persister.read_state
|
88
|
+
end
|
89
|
+
|
90
|
+
def aasm_write_state(state)
|
91
|
+
@persister.write_state(state)
|
92
|
+
end
|
47
93
|
end
|
data/spec/models/foo.rb
CHANGED
@@ -33,3 +33,60 @@ class FooTwo < Foo
|
|
33
33
|
state :foo
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
class FooMultiple
|
38
|
+
include AASM
|
39
|
+
|
40
|
+
aasm(:left) do
|
41
|
+
state :open, :initial => true, :before_exit => :before_exit
|
42
|
+
state :closed, :before_enter => :before_enter
|
43
|
+
state :final
|
44
|
+
|
45
|
+
event :close, :success => :success_callback do
|
46
|
+
transitions :from => [:open], :to => [:closed]
|
47
|
+
end
|
48
|
+
|
49
|
+
event :null do
|
50
|
+
transitions :from => [:open], :to => [:closed, :final], :guard => :always_false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
aasm(:right, :column => :right) do
|
55
|
+
state :green, :initial => true
|
56
|
+
state :yellow
|
57
|
+
state :red
|
58
|
+
|
59
|
+
event :green do
|
60
|
+
transitions :from => [:yellow], :to => :green
|
61
|
+
end
|
62
|
+
event :yellow do
|
63
|
+
transitions :from => [:green, :red], :to => :yellow
|
64
|
+
end
|
65
|
+
event :red do
|
66
|
+
transitions :from => [:yellow], :to => :red
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def always_false
|
71
|
+
false
|
72
|
+
end
|
73
|
+
|
74
|
+
def success_callback
|
75
|
+
end
|
76
|
+
|
77
|
+
def before_enter
|
78
|
+
end
|
79
|
+
def before_exit
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class FooTwoMultiple < FooMultiple
|
84
|
+
include AASM
|
85
|
+
aasm(:left) do
|
86
|
+
state :foo
|
87
|
+
end
|
88
|
+
|
89
|
+
aasm(:right) do
|
90
|
+
state :bar
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class FooCallbackMultiple
|
2
|
+
include AASM
|
3
|
+
|
4
|
+
aasm(:left) do
|
5
|
+
state :open, :initial => true, :before_exit => :before_exit
|
6
|
+
state :closed, :before_enter => :before_enter
|
7
|
+
state :final
|
8
|
+
|
9
|
+
event :close, :success => :success_callback do
|
10
|
+
transitions :from => [:open], :to => [:closed]
|
11
|
+
end
|
12
|
+
|
13
|
+
event :null do
|
14
|
+
transitions :from => [:open], :to => [:closed, :final], :guard => :always_false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
aasm(:right, :column => :right) do
|
19
|
+
state :green, :initial => true
|
20
|
+
state :yellow
|
21
|
+
state :red
|
22
|
+
|
23
|
+
event :green do
|
24
|
+
transitions :from => [:yellow], :to => :green
|
25
|
+
end
|
26
|
+
event :yellow do
|
27
|
+
transitions :from => [:green, :red], :to => :yellow
|
28
|
+
end
|
29
|
+
event :red do
|
30
|
+
transitions :from => [:yellow], :to => :red
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def always_false
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
def success_callback
|
39
|
+
end
|
40
|
+
|
41
|
+
def before_enter
|
42
|
+
end
|
43
|
+
def before_exit
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class GuardianMultiple
|
2
|
+
include AASM
|
3
|
+
|
4
|
+
aasm(:left) do
|
5
|
+
state :alpha, :initial => true
|
6
|
+
state :beta
|
7
|
+
|
8
|
+
event :use_one_guard_that_succeeds do
|
9
|
+
transitions :from => :alpha, :to => :beta, :guard => :succeed
|
10
|
+
end
|
11
|
+
event :use_one_guard_that_fails do
|
12
|
+
transitions :from => :alpha, :to => :beta, :guard => :fail
|
13
|
+
end
|
14
|
+
|
15
|
+
event :use_guards_that_succeed do
|
16
|
+
transitions :from => :alpha, :to => :beta, :guards => [:succeed, :another_succeed]
|
17
|
+
end
|
18
|
+
event :use_guards_where_the_first_fails do
|
19
|
+
transitions :from => :alpha, :to => :beta, :guards => [:succeed, :fail]
|
20
|
+
end
|
21
|
+
event :use_guards_where_the_second_fails do
|
22
|
+
transitions :from => :alpha, :to => :beta, :guards => [:fail, :succeed]
|
23
|
+
end
|
24
|
+
|
25
|
+
event :use_event_guards_that_succeed, :guards => [:succeed, :another_succeed] do
|
26
|
+
transitions :from => :alpha, :to => :beta
|
27
|
+
end
|
28
|
+
event :use_event_and_transition_guards_that_succeed, :guards => [:succeed, :another_succeed] do
|
29
|
+
transitions :from => :alpha, :to => :beta, :guards => [:more_succeed]
|
30
|
+
end
|
31
|
+
event :use_event_guards_where_the_first_fails, :guards => [:succeed, :fail] do
|
32
|
+
transitions :from => :alpha, :to => :beta
|
33
|
+
end
|
34
|
+
event :use_event_guards_where_the_second_fails, :guards => [:fail, :succeed] do
|
35
|
+
transitions :from => :alpha, :to => :beta, :guard => :another_succeed
|
36
|
+
end
|
37
|
+
event :use_event_and_transition_guards_where_third_fails, :guards => [:succeed, :another_succeed] do
|
38
|
+
transitions :from => :alpha, :to => :beta, :guards => [:fail]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def fail; false; end
|
43
|
+
|
44
|
+
def succeed; true; end
|
45
|
+
def another_succeed; true; end
|
46
|
+
def more_succeed; true; end
|
47
|
+
|
48
|
+
end
|
@@ -13,3 +13,19 @@ class InitialStateProc
|
|
13
13
|
def initialize(balance = 0); self.balance = balance; end
|
14
14
|
def rich?; self.balance >= RICH; end
|
15
15
|
end
|
16
|
+
|
17
|
+
class InitialStateProcMultiple
|
18
|
+
RICH = 1_000_000
|
19
|
+
|
20
|
+
attr_accessor :balance
|
21
|
+
|
22
|
+
include AASM
|
23
|
+
aasm(:left) do
|
24
|
+
state :retired
|
25
|
+
state :selling_bad_mortgages
|
26
|
+
initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(balance = 0); self.balance = balance; end
|
30
|
+
def rich?; self.balance >= RICH; end
|
31
|
+
end
|
@@ -14,3 +14,18 @@ class InvalidPersistor < ActiveRecord::Base
|
|
14
14
|
end
|
15
15
|
validates_presence_of :name
|
16
16
|
end
|
17
|
+
|
18
|
+
class MultipleInvalidPersistor < ActiveRecord::Base
|
19
|
+
include AASM
|
20
|
+
aasm :left, :column => :status, :skip_validation_on_save => true do
|
21
|
+
state :sleeping, :initial => true
|
22
|
+
state :running
|
23
|
+
event :run do
|
24
|
+
transitions :to => :running, :from => :sleeping
|
25
|
+
end
|
26
|
+
event :sleep do
|
27
|
+
transitions :to => :sleeping, :from => :running
|
28
|
+
end
|
29
|
+
end
|
30
|
+
validates_presence_of :name
|
31
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class ComplexMongoMapperExample
|
2
|
+
include MongoMapper::Document
|
3
|
+
include AASM
|
4
|
+
|
5
|
+
key :left, String
|
6
|
+
key :right, String
|
7
|
+
|
8
|
+
aasm :left, :column => 'left' do
|
9
|
+
state :one, :initial => true
|
10
|
+
state :two
|
11
|
+
state :three
|
12
|
+
|
13
|
+
event :increment do
|
14
|
+
transitions :from => :one, :to => :two
|
15
|
+
transitions :from => :two, :to => :three
|
16
|
+
end
|
17
|
+
event :reset do
|
18
|
+
transitions :from => :three, :to => :one
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
aasm :right, :column => 'right' do
|
23
|
+
state :alpha, :initial => true
|
24
|
+
state :beta
|
25
|
+
state :gamma
|
26
|
+
|
27
|
+
event :level_up do
|
28
|
+
transitions :from => :alpha, :to => :beta
|
29
|
+
transitions :from => :beta, :to => :gamma
|
30
|
+
end
|
31
|
+
event :level_down do
|
32
|
+
transitions :from => :gamma, :to => :beta
|
33
|
+
transitions :from => :beta, :to => :alpha
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -8,3 +8,14 @@ class NoScopeMongoMapper
|
|
8
8
|
state :ignored_scope
|
9
9
|
end
|
10
10
|
end
|
11
|
+
|
12
|
+
class NoScopeMongoMapperMultiple
|
13
|
+
include MongoMapper::Document
|
14
|
+
include AASM
|
15
|
+
|
16
|
+
key :status, String
|
17
|
+
|
18
|
+
aasm :left, :create_scopes => false, :column => :status do
|
19
|
+
state :ignored_scope
|
20
|
+
end
|
21
|
+
end
|