aasm 4.2.0 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -1
  3. data/Gemfile +2 -2
  4. data/PLANNED_CHANGES.md +24 -4
  5. data/README.md +75 -5
  6. data/lib/aasm/aasm.rb +50 -36
  7. data/lib/aasm/base.rb +36 -18
  8. data/lib/aasm/core/event.rb +6 -5
  9. data/lib/aasm/core/state.rb +3 -2
  10. data/lib/aasm/core/transition.rb +5 -4
  11. data/lib/aasm/errors.rb +7 -4
  12. data/lib/aasm/instance_base.rb +14 -13
  13. data/lib/aasm/localizer.rb +1 -1
  14. data/lib/aasm/persistence/active_record_persistence.rb +41 -66
  15. data/lib/aasm/persistence/base.rb +7 -7
  16. data/lib/aasm/persistence/mongo_mapper_persistence.rb +34 -51
  17. data/lib/aasm/persistence/mongoid_persistence.rb +15 -36
  18. data/lib/aasm/persistence/plain_persistence.rb +8 -7
  19. data/lib/aasm/persistence/sequel_persistence.rb +12 -10
  20. data/lib/aasm/state_machine.rb +11 -6
  21. data/lib/aasm/version.rb +1 -1
  22. data/spec/database.rb +27 -1
  23. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
  24. data/spec/models/active_record/complex_active_record_example.rb +33 -0
  25. data/spec/models/active_record/derivate_new_dsl.rb +4 -0
  26. data/spec/models/active_record/false_state.rb +18 -0
  27. data/spec/models/active_record/gate.rb +20 -0
  28. data/spec/models/active_record/no_direct_assignment.rb +11 -0
  29. data/spec/models/active_record/no_scope.rb +11 -0
  30. data/spec/models/active_record/provided_and_persisted_state.rb +3 -3
  31. data/spec/models/active_record/simple_new_dsl.rb +9 -0
  32. data/spec/models/active_record/thief.rb +15 -0
  33. data/spec/models/active_record/with_enum.rb +20 -0
  34. data/spec/models/active_record/with_false_enum.rb +16 -0
  35. data/spec/models/active_record/with_true_enum.rb +20 -0
  36. data/spec/models/basic_two_state_machines_example.rb +25 -0
  37. data/spec/models/callbacks/basic_multiple.rb +75 -0
  38. data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
  39. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
  40. data/spec/models/callbacks/private_method_multiple.rb +44 -0
  41. data/spec/models/callbacks/with_args_multiple.rb +61 -0
  42. data/spec/models/callbacks/{with_state_args.rb → with_state_arg.rb} +0 -0
  43. data/spec/models/callbacks/with_state_arg_multiple.rb +26 -0
  44. data/spec/models/complex_example.rb +134 -0
  45. data/spec/models/conversation.rb +47 -1
  46. data/spec/models/foo.rb +57 -0
  47. data/spec/models/foo_callback_multiple.rb +45 -0
  48. data/spec/models/guardian_multiple.rb +48 -0
  49. data/spec/models/initial_state_proc.rb +16 -0
  50. data/spec/models/invalid_persistor.rb +15 -0
  51. data/spec/models/mongo_mapper/complex_mongo_mapper_example.rb +37 -0
  52. data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +11 -0
  53. data/spec/models/mongo_mapper/simple_mongo_mapper.rb +12 -0
  54. data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +13 -0
  55. data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
  56. data/spec/models/mongoid/no_scope_mongoid.rb +11 -0
  57. data/spec/models/mongoid/simple_mongoid.rb +12 -0
  58. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +13 -0
  59. data/spec/models/no_initial_state.rb +13 -0
  60. data/spec/models/parametrised_event.rb +1 -1
  61. data/spec/models/parametrised_event_multiple.rb +29 -0
  62. data/spec/models/provided_state.rb +3 -3
  63. data/spec/models/sequel/complex_sequel_example.rb +45 -0
  64. data/spec/models/sequel/sequel_multiple.rb +25 -0
  65. data/spec/models/sequel/sequel_simple.rb +25 -0
  66. data/spec/models/simple_multiple_example.rb +30 -0
  67. data/spec/models/sub_class.rb +4 -0
  68. data/spec/models/sub_class_with_more_states.rb +11 -0
  69. data/spec/models/super_class.rb +28 -0
  70. data/spec/models/transactor.rb +27 -0
  71. data/spec/models/valid_state_name.rb +12 -0
  72. data/spec/models/validator.rb +39 -0
  73. data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
  74. data/spec/unit/callback_multiple_spec.rb +295 -0
  75. data/spec/unit/callbacks_spec.rb +1 -1
  76. data/spec/unit/complex_multiple_example_spec.rb +99 -0
  77. data/spec/unit/edge_cases_spec.rb +16 -0
  78. data/spec/unit/event_multiple_spec.rb +73 -0
  79. data/spec/unit/event_spec.rb +11 -6
  80. data/spec/unit/guard_multiple_spec.rb +60 -0
  81. data/spec/unit/initial_state_multiple_spec.rb +15 -0
  82. data/spec/unit/inspection_multiple_spec.rb +201 -0
  83. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +560 -0
  84. data/spec/unit/persistence/active_record_persistence_spec.rb +17 -12
  85. data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +146 -0
  86. data/spec/unit/persistence/{mongo_mapper_persistance_spec.rb → mongo_mapper_persistence_spec.rb} +7 -49
  87. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +127 -0
  88. data/spec/unit/persistence/mongoid_persistence_spec.rb +79 -0
  89. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +153 -0
  90. data/spec/unit/persistence/sequel_persistence_spec.rb +7 -24
  91. data/spec/unit/reloading_spec.rb +1 -1
  92. data/spec/unit/simple_multiple_example_spec.rb +63 -0
  93. data/spec/unit/state_spec.rb +3 -1
  94. data/spec/unit/subclassing_multiple_spec.rb +39 -0
  95. data/spec/unit/transition_spec.rb +31 -22
  96. metadata +73 -9
  97. 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
@@ -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
@@ -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