state_machine 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (240) hide show
  1. data/.gitignore +7 -11
  2. data/.travis.yml +49 -7
  3. data/Appraisals +255 -87
  4. data/CHANGELOG.md +30 -0
  5. data/README.md +142 -21
  6. data/Rakefile +1 -11
  7. data/examples/Gemfile +5 -0
  8. data/examples/Gemfile.lock +14 -0
  9. data/examples/auto_shop.rb +2 -0
  10. data/examples/car.rb +2 -0
  11. data/examples/doc/AutoShop.html +2856 -0
  12. data/examples/doc/AutoShop_state.png +0 -0
  13. data/examples/doc/Car.html +919 -0
  14. data/examples/doc/Car_state.png +0 -0
  15. data/examples/doc/TrafficLight.html +2230 -0
  16. data/examples/doc/TrafficLight_state.png +0 -0
  17. data/examples/doc/Vehicle.html +7921 -0
  18. data/examples/doc/Vehicle_state.png +0 -0
  19. data/examples/doc/_index.html +136 -0
  20. data/examples/doc/class_list.html +47 -0
  21. data/examples/doc/css/common.css +1 -0
  22. data/examples/doc/css/full_list.css +55 -0
  23. data/examples/doc/css/style.css +322 -0
  24. data/examples/doc/file_list.html +46 -0
  25. data/examples/doc/frames.html +13 -0
  26. data/examples/doc/index.html +136 -0
  27. data/examples/doc/js/app.js +205 -0
  28. data/examples/doc/js/full_list.js +173 -0
  29. data/examples/doc/js/jquery.js +16 -0
  30. data/examples/doc/method_list.html +734 -0
  31. data/examples/doc/top-level-namespace.html +105 -0
  32. data/examples/rails-rest/migration.rb +1 -5
  33. data/examples/rails-rest/view__form.html.erb +34 -0
  34. data/examples/rails-rest/view_edit.html.erb +2 -21
  35. data/examples/rails-rest/view_index.html.erb +6 -4
  36. data/examples/rails-rest/view_new.html.erb +2 -11
  37. data/examples/rails-rest/view_show.html.erb +5 -3
  38. data/examples/traffic_light.rb +2 -0
  39. data/examples/vehicle.rb +2 -0
  40. data/gemfiles/active_model-3.0.0.gemfile.lock +9 -6
  41. data/gemfiles/active_model-3.0.5.gemfile.lock +10 -7
  42. data/gemfiles/active_model-3.1.1.gemfile.lock +12 -10
  43. data/gemfiles/{active_model-3.2.0.gemfile → active_model-3.2.1.gemfile} +1 -1
  44. data/gemfiles/{graphviz-0.9.0.gemfile → active_model-3.2.12.gemfile} +1 -1
  45. data/gemfiles/active_model-3.2.12.gemfile.lock +36 -0
  46. data/gemfiles/{active_record-3.2.0.gemfile → active_model-3.2.13.rc1.gemfile} +1 -2
  47. data/gemfiles/active_model-3.2.13.rc1.gemfile.lock +36 -0
  48. data/gemfiles/active_model-4.0.0.gemfile +9 -0
  49. data/gemfiles/active_model-4.0.0.gemfile.lock +78 -0
  50. data/gemfiles/active_record-2.0.0.gemfile +2 -1
  51. data/gemfiles/active_record-2.0.0.gemfile.lock +15 -6
  52. data/gemfiles/active_record-2.0.5.gemfile +2 -1
  53. data/gemfiles/active_record-2.0.5.gemfile.lock +15 -6
  54. data/gemfiles/active_record-2.1.0.gemfile +2 -1
  55. data/gemfiles/active_record-2.1.0.gemfile.lock +15 -6
  56. data/gemfiles/active_record-2.1.2.gemfile +2 -1
  57. data/gemfiles/active_record-2.1.2.gemfile.lock +15 -6
  58. data/gemfiles/active_record-2.2.3.gemfile +2 -1
  59. data/gemfiles/active_record-2.2.3.gemfile.lock +15 -6
  60. data/gemfiles/active_record-2.3.12.gemfile +2 -1
  61. data/gemfiles/active_record-2.3.12.gemfile.lock +15 -6
  62. data/gemfiles/active_record-2.3.5.gemfile +9 -0
  63. data/gemfiles/active_record-2.3.5.gemfile.lock +39 -0
  64. data/gemfiles/active_record-3.0.0.gemfile +2 -1
  65. data/gemfiles/active_record-3.0.0.gemfile.lock +18 -11
  66. data/gemfiles/active_record-3.0.5.gemfile +2 -1
  67. data/gemfiles/active_record-3.0.5.gemfile.lock +19 -12
  68. data/gemfiles/active_record-3.1.1.gemfile +2 -1
  69. data/gemfiles/active_record-3.1.1.gemfile.lock +22 -16
  70. data/gemfiles/active_record-3.2.12.gemfile +9 -0
  71. data/gemfiles/active_record-3.2.12.gemfile.lock +51 -0
  72. data/gemfiles/active_record-3.2.13.rc1.gemfile +9 -0
  73. data/gemfiles/active_record-3.2.13.rc1.gemfile.lock +51 -0
  74. data/gemfiles/active_record-4.0.0.gemfile +11 -0
  75. data/gemfiles/active_record-4.0.0.gemfile.lock +83 -0
  76. data/gemfiles/data_mapper-0.10.2.gemfile +1 -0
  77. data/gemfiles/data_mapper-0.10.2.gemfile.lock +13 -9
  78. data/gemfiles/data_mapper-0.9.11.gemfile +1 -0
  79. data/gemfiles/data_mapper-0.9.11.gemfile.lock +31 -7
  80. data/gemfiles/data_mapper-0.9.4.gemfile.lock +25 -14
  81. data/gemfiles/data_mapper-0.9.7.gemfile +1 -0
  82. data/gemfiles/data_mapper-0.9.7.gemfile.lock +27 -15
  83. data/gemfiles/data_mapper-1.0.0.gemfile.lock +20 -17
  84. data/gemfiles/data_mapper-1.0.1.gemfile.lock +20 -17
  85. data/gemfiles/data_mapper-1.0.2.gemfile.lock +20 -17
  86. data/gemfiles/data_mapper-1.1.0.gemfile.lock +19 -16
  87. data/gemfiles/data_mapper-1.2.0.gemfile.lock +19 -16
  88. data/gemfiles/default.gemfile.lock +8 -5
  89. data/gemfiles/graphviz-0.9.17.gemfile +7 -0
  90. data/gemfiles/graphviz-0.9.17.gemfile.lock +29 -0
  91. data/gemfiles/graphviz-0.9.21.gemfile.lock +7 -4
  92. data/gemfiles/graphviz-1.0.0.gemfile.lock +7 -4
  93. data/gemfiles/graphviz-1.0.3.gemfile +7 -0
  94. data/gemfiles/graphviz-1.0.3.gemfile.lock +29 -0
  95. data/gemfiles/graphviz-1.0.8.gemfile +7 -0
  96. data/gemfiles/graphviz-1.0.8.gemfile.lock +29 -0
  97. data/gemfiles/mongo_mapper-0.10.0.gemfile +1 -0
  98. data/gemfiles/mongo_mapper-0.10.0.gemfile.lock +14 -11
  99. data/gemfiles/mongo_mapper-0.11.1.gemfile +7 -0
  100. data/gemfiles/mongo_mapper-0.11.1.gemfile.lock +44 -0
  101. data/gemfiles/mongo_mapper-0.11.2.gemfile +9 -0
  102. data/gemfiles/mongo_mapper-0.11.2.gemfile.lock +48 -0
  103. data/gemfiles/mongo_mapper-0.12.0.gemfile +9 -0
  104. data/gemfiles/mongo_mapper-0.12.0.gemfile.lock +48 -0
  105. data/gemfiles/mongo_mapper-0.5.5.gemfile.lock +7 -4
  106. data/gemfiles/mongo_mapper-0.5.8.gemfile.lock +7 -4
  107. data/gemfiles/mongo_mapper-0.6.0.gemfile.lock +7 -4
  108. data/gemfiles/mongo_mapper-0.6.10.gemfile.lock +7 -4
  109. data/gemfiles/mongo_mapper-0.7.0.gemfile.lock +7 -4
  110. data/gemfiles/mongo_mapper-0.7.5.gemfile.lock +7 -4
  111. data/gemfiles/mongo_mapper-0.8.0.gemfile.lock +7 -4
  112. data/gemfiles/mongo_mapper-0.8.3.gemfile.lock +7 -4
  113. data/gemfiles/mongo_mapper-0.8.4.gemfile.lock +7 -4
  114. data/gemfiles/mongo_mapper-0.8.6.gemfile.lock +7 -4
  115. data/gemfiles/mongo_mapper-0.9.0.gemfile.lock +7 -4
  116. data/gemfiles/mongoid-2.0.0.gemfile +2 -0
  117. data/gemfiles/mongoid-2.0.0.gemfile.lock +22 -18
  118. data/gemfiles/mongoid-2.1.4.gemfile +2 -0
  119. data/gemfiles/mongoid-2.1.4.gemfile.lock +21 -17
  120. data/gemfiles/mongoid-2.2.4.gemfile +2 -0
  121. data/gemfiles/mongoid-2.2.4.gemfile.lock +21 -17
  122. data/gemfiles/mongoid-2.3.3.gemfile +2 -0
  123. data/gemfiles/mongoid-2.3.3.gemfile.lock +21 -17
  124. data/gemfiles/mongoid-2.4.0.gemfile +9 -0
  125. data/gemfiles/mongoid-2.4.0.gemfile.lock +47 -0
  126. data/gemfiles/mongoid-2.4.10.gemfile +9 -0
  127. data/gemfiles/mongoid-2.4.10.gemfile.lock +47 -0
  128. data/gemfiles/mongoid-2.5.2.gemfile +9 -0
  129. data/gemfiles/mongoid-2.5.2.gemfile.lock +47 -0
  130. data/gemfiles/mongoid-2.6.0.gemfile +9 -0
  131. data/gemfiles/mongoid-2.6.0.gemfile.lock +47 -0
  132. data/gemfiles/mongoid-3.0.0.gemfile +8 -0
  133. data/gemfiles/mongoid-3.0.0.gemfile.lock +45 -0
  134. data/gemfiles/mongoid-3.0.22.gemfile +8 -0
  135. data/gemfiles/mongoid-3.0.22.gemfile.lock +45 -0
  136. data/gemfiles/mongoid-3.1.0.gemfile +8 -0
  137. data/gemfiles/mongoid-3.1.0.gemfile.lock +45 -0
  138. data/gemfiles/sequel-2.11.0.gemfile +2 -1
  139. data/gemfiles/sequel-2.11.0.gemfile.lock +11 -6
  140. data/gemfiles/sequel-2.12.0.gemfile +2 -1
  141. data/gemfiles/sequel-2.12.0.gemfile.lock +11 -6
  142. data/gemfiles/sequel-2.8.0.gemfile +2 -1
  143. data/gemfiles/sequel-2.8.0.gemfile.lock +11 -6
  144. data/gemfiles/sequel-3.0.0.gemfile +2 -1
  145. data/gemfiles/sequel-3.0.0.gemfile.lock +11 -6
  146. data/gemfiles/sequel-3.10.0.gemfile +9 -0
  147. data/gemfiles/sequel-3.10.0.gemfile.lock +33 -0
  148. data/gemfiles/sequel-3.13.0.gemfile +2 -1
  149. data/gemfiles/sequel-3.13.0.gemfile.lock +11 -6
  150. data/gemfiles/sequel-3.14.0.gemfile +2 -1
  151. data/gemfiles/sequel-3.14.0.gemfile.lock +11 -6
  152. data/gemfiles/sequel-3.23.0.gemfile +2 -1
  153. data/gemfiles/sequel-3.23.0.gemfile.lock +11 -6
  154. data/gemfiles/sequel-3.24.0.gemfile +2 -1
  155. data/gemfiles/sequel-3.24.0.gemfile.lock +11 -6
  156. data/gemfiles/sequel-3.29.0.gemfile +2 -1
  157. data/gemfiles/sequel-3.29.0.gemfile.lock +11 -6
  158. data/gemfiles/sequel-3.34.0.gemfile +9 -0
  159. data/gemfiles/sequel-3.34.0.gemfile.lock +33 -0
  160. data/gemfiles/sequel-3.35.0.gemfile +9 -0
  161. data/gemfiles/sequel-3.35.0.gemfile.lock +33 -0
  162. data/gemfiles/sequel-3.4.0.gemfile +9 -0
  163. data/gemfiles/sequel-3.4.0.gemfile.lock +33 -0
  164. data/gemfiles/sequel-3.44.0.gemfile +9 -0
  165. data/gemfiles/sequel-3.44.0.gemfile.lock +33 -0
  166. data/lib/state_machine.rb +6 -0
  167. data/lib/state_machine/branch.rb +9 -8
  168. data/lib/state_machine/callback.rb +2 -2
  169. data/lib/state_machine/core.rb +10 -0
  170. data/lib/state_machine/core_ext.rb +1 -0
  171. data/lib/state_machine/eval_helpers.rb +5 -3
  172. data/lib/state_machine/event.rb +17 -6
  173. data/lib/state_machine/graph.rb +92 -0
  174. data/lib/state_machine/integrations.rb +13 -1
  175. data/lib/state_machine/integrations/active_model.rb +14 -20
  176. data/lib/state_machine/integrations/active_model/observer.rb +3 -3
  177. data/lib/state_machine/integrations/active_model/observer_update.rb +42 -0
  178. data/lib/state_machine/integrations/active_record.rb +52 -25
  179. data/lib/state_machine/integrations/active_record/locale.rb +1 -1
  180. data/lib/state_machine/integrations/active_record/versions.rb +1 -17
  181. data/lib/state_machine/integrations/base.rb +15 -6
  182. data/lib/state_machine/integrations/data_mapper.rb +98 -35
  183. data/lib/state_machine/integrations/data_mapper/versions.rb +46 -8
  184. data/lib/state_machine/integrations/mongo_mapper.rb +39 -12
  185. data/lib/state_machine/integrations/mongo_mapper/locale.rb +1 -1
  186. data/lib/state_machine/integrations/mongo_mapper/versions.rb +3 -20
  187. data/lib/state_machine/integrations/mongoid.rb +52 -14
  188. data/lib/state_machine/integrations/mongoid/locale.rb +1 -1
  189. data/lib/state_machine/integrations/mongoid/versions.rb +52 -26
  190. data/lib/state_machine/integrations/sequel.rb +82 -33
  191. data/lib/state_machine/integrations/sequel/versions.rb +19 -44
  192. data/lib/state_machine/machine.rb +99 -59
  193. data/lib/state_machine/machine_collection.rb +1 -2
  194. data/lib/state_machine/macro_methods.rb +29 -0
  195. data/lib/state_machine/node_collection.rb +1 -1
  196. data/lib/state_machine/state.rb +18 -10
  197. data/lib/state_machine/state_context.rb +2 -2
  198. data/lib/state_machine/transition.rb +8 -1
  199. data/lib/state_machine/transition_collection.rb +2 -1
  200. data/lib/state_machine/version.rb +1 -1
  201. data/lib/state_machine/yard.rb +8 -0
  202. data/lib/state_machine/yard/handlers.rb +12 -0
  203. data/lib/state_machine/yard/handlers/base.rb +32 -0
  204. data/lib/state_machine/yard/handlers/event.rb +25 -0
  205. data/lib/state_machine/yard/handlers/machine.rb +344 -0
  206. data/lib/state_machine/yard/handlers/state.rb +25 -0
  207. data/lib/state_machine/yard/handlers/transition.rb +47 -0
  208. data/lib/state_machine/yard/templates.rb +3 -0
  209. data/lib/state_machine/yard/templates/default/class/html/setup.rb +30 -0
  210. data/lib/state_machine/yard/templates/default/class/html/state_machines.erb +12 -0
  211. data/lib/tasks/state_machine.rb +2 -1
  212. data/lib/yard-state_machine.rb +2 -0
  213. data/state_machine.gemspec +4 -3
  214. data/test/files/switch.rb +4 -0
  215. data/test/test_helper.rb +5 -0
  216. data/test/unit/branch_test.rb +117 -36
  217. data/test/unit/callback_test.rb +5 -2
  218. data/test/unit/eval_helpers_test.rb +49 -1
  219. data/test/unit/event_collection_test.rb +3 -1
  220. data/test/unit/event_test.rb +182 -12
  221. data/test/unit/graph_test.rb +98 -0
  222. data/test/unit/integrations/active_model_test.rb +82 -12
  223. data/test/unit/integrations/active_record_test.rb +393 -37
  224. data/test/unit/integrations/base_test.rb +7 -2
  225. data/test/unit/integrations/data_mapper_test.rb +326 -72
  226. data/test/unit/integrations/mongo_mapper_test.rb +338 -44
  227. data/test/unit/integrations/mongoid_test.rb +606 -98
  228. data/test/unit/integrations/sequel_test.rb +429 -102
  229. data/test/unit/integrations_test.rb +28 -6
  230. data/test/unit/machine_collection_test.rb +6 -2
  231. data/test/unit/machine_test.rb +134 -82
  232. data/test/unit/node_collection_test.rb +2 -2
  233. data/test/unit/path_test.rb +1 -1
  234. data/test/unit/state_test.rb +65 -21
  235. data/test/unit/transition_collection_test.rb +43 -23
  236. data/test/unit/transition_test.rb +8 -2
  237. metadata +303 -221
  238. data/gemfiles/active_model-3.2.0.gemfile.lock +0 -32
  239. data/gemfiles/active_record-3.2.0.gemfile.lock +0 -43
  240. data/gemfiles/graphviz-0.9.0.gemfile.lock +0 -26
@@ -11,14 +11,23 @@ module MongoMapperTest
11
11
  def default_test
12
12
  end
13
13
 
14
+ def teardown
15
+ if @table_names
16
+ MongoMapper.database.collections.each {|c| c.drop if @table_names.include?(c.name)}
17
+ end
18
+ end
19
+
14
20
  protected
15
21
  # Creates a new MongoMapper model (and the associated table)
16
- def new_model(table_name = :foo, &block)
22
+ def new_model(name = :foo, &block)
23
+ table_name = "#{name}_#{rand(1000000)}"
24
+ @table_names ||= []
25
+ @table_names << table_name
17
26
 
18
27
  model = Class.new do
19
28
  (class << self; self; end).class_eval do
20
- define_method(:name) { "MongoMapperTest::#{table_name.to_s.capitalize}" }
21
- define_method(:to_s) { name }
29
+ define_method(:name) { "MongoMapperTest::#{name.to_s.capitalize}" }
30
+ define_method(:to_s) { self.name }
22
31
  end
23
32
  end
24
33
 
@@ -29,7 +38,6 @@ module MongoMapperTest
29
38
  key :state, String
30
39
  end
31
40
  model.class_eval(&block) if block_given?
32
- model.collection.remove
33
41
  model
34
42
  end
35
43
  end
@@ -52,7 +60,7 @@ module MongoMapperTest
52
60
  end
53
61
 
54
62
  def test_should_have_defaults
55
- assert_equal e = {:action => :save}, StateMachine::Integrations::MongoMapper.defaults
63
+ assert_equal({:action => :save}, StateMachine::Integrations::MongoMapper.defaults)
56
64
  end
57
65
 
58
66
  def test_should_have_a_locale_path
@@ -136,7 +144,7 @@ module MongoMapperTest
136
144
 
137
145
  class MachineWithStaticInitialStateTest < BaseTestCase
138
146
  def setup
139
- @model = new_model do
147
+ @model = new_model(:vehicle) do
140
148
  attr_accessor :value
141
149
  end
142
150
  @machine = StateMachine::Machine.new(@model, :initial => :parked)
@@ -159,7 +167,7 @@ module MongoMapperTest
159
167
 
160
168
  def test_should_not_allow_initialize_blocks
161
169
  block_args = nil
162
- record = @model.new do |*args|
170
+ @model.new do |*args|
163
171
  block_args = args
164
172
  end
165
173
 
@@ -170,6 +178,7 @@ module MongoMapperTest
170
178
  @model.class_eval do
171
179
  attr_accessor :state_during_setter
172
180
 
181
+ remove_method :value=
173
182
  define_method(:value=) do |value|
174
183
  self.state_during_setter = state
175
184
  end
@@ -188,6 +197,20 @@ module MongoMapperTest
188
197
  assert_equal 'idling', record.state
189
198
  end
190
199
 
200
+ def test_should_persist_initial_state
201
+ record = @model.new
202
+ record.save
203
+ record = @model.find(record.id)
204
+ assert_equal 'parked', record.state
205
+ end
206
+
207
+ def test_should_persist_initial_state_on_dup
208
+ record = @model.create.dup
209
+ record.save
210
+ record = @model.find(record.id)
211
+ assert_equal 'parked', record.state
212
+ end
213
+
191
214
  def test_should_use_stored_values_when_loading_from_database
192
215
  @machine.state :idling
193
216
 
@@ -201,6 +224,65 @@ module MongoMapperTest
201
224
  record = @model.find(@model.create(:state => nil).id)
202
225
  assert_nil record.state
203
226
  end
227
+
228
+ if defined?(MongoMapper::Version) && MongoMapper::Version !~ /^0\.[5-8]\./
229
+ def test_should_use_stored_values_when_loading_for_many_association
230
+ @machine.state :idling
231
+
232
+ @model.belongs_to :owner, :class_name => 'MongoMapperTest::Owner'
233
+ MongoMapperTest.const_set('Vehicle', @model)
234
+
235
+ owner_model = new_model(:owner) do
236
+ many :vehicles, :class_name => 'MongoMapperTest::Vehicle'
237
+ end
238
+ MongoMapperTest.const_set('Owner', owner_model)
239
+
240
+ owner = owner_model.create
241
+ record = @model.create(:state => 'idling', :owner_id => owner.id)
242
+ assert_equal 'idling', owner.vehicles[0].state
243
+ end
244
+
245
+ def test_should_use_stored_values_when_loading_for_one_association
246
+ @machine.state :idling
247
+
248
+ @model.belongs_to :owner, :class_name => 'MongoMapperTest::Owner'
249
+ MongoMapperTest.const_set('Vehicle', @model)
250
+
251
+ owner_model = new_model(:owner) do
252
+ one :vehicle, :class_name => 'MongoMapperTest::Vehicle'
253
+ end
254
+ MongoMapperTest.const_set('Owner', owner_model)
255
+
256
+ owner = owner_model.create
257
+ record = @model.create(:state => 'idling', :owner_id => owner.id)
258
+ owner.reload
259
+ assert_equal 'idling', owner.vehicle.state
260
+ end
261
+
262
+ def test_should_use_stored_values_when_loading_for_belongs_to_association
263
+ @machine.state :idling
264
+
265
+ MongoMapperTest.const_set('Vehicle', @model)
266
+
267
+ driver_model = new_model(:driver) do
268
+ belongs_to :vehicle, :class_name => 'MongoMapperTest::Vehicle'
269
+ end
270
+ MongoMapperTest.const_set('Driver', driver_model)
271
+
272
+ record = @model.create(:state => 'idling')
273
+ driver = driver_model.create(:vehicle_id => record.id)
274
+ assert_equal 'idling', driver.vehicle.state
275
+ end
276
+ end
277
+
278
+ def teardown
279
+ MongoMapperTest.class_eval do
280
+ remove_const('Vehicle') if defined?(MongoMapperTest::Vehicle)
281
+ remove_const('Owner') if defined?(MongoMapperTest::Owner)
282
+ remove_const('Driver') if defined?(MongoMapperTest::Driver)
283
+ end
284
+ super
285
+ end
204
286
  end
205
287
 
206
288
  class MachineWithDynamicInitialStateTest < BaseTestCase
@@ -224,7 +306,7 @@ module MongoMapperTest
224
306
 
225
307
  def test_should_not_allow_initialize_blocks
226
308
  block_args = nil
227
- record = @model.new do |*args|
309
+ @model.new do |*args|
228
310
  block_args = args
229
311
  end
230
312
 
@@ -235,6 +317,7 @@ module MongoMapperTest
235
317
  @model.class_eval do
236
318
  attr_accessor :state_during_setter
237
319
 
320
+ remove_method :value=
238
321
  define_method(:value=) do |value|
239
322
  self.state_during_setter = state || 'nil'
240
323
  end
@@ -253,6 +336,20 @@ module MongoMapperTest
253
336
  assert_equal 'idling', record.state
254
337
  end
255
338
 
339
+ def test_should_persist_initial_state
340
+ record = @model.new
341
+ record.save
342
+ record = @model.find(record.id)
343
+ assert_equal 'parked', record.state
344
+ end
345
+
346
+ def test_should_persist_initial_state_on_dup
347
+ record = @model.create.dup
348
+ record.save
349
+ record = @model.find(record.id)
350
+ assert_equal 'parked', record.state
351
+ end
352
+
256
353
  def test_should_use_stored_values_when_loading_from_database
257
354
  @machine.state :idling
258
355
 
@@ -280,8 +377,34 @@ module MongoMapperTest
280
377
  end
281
378
  end
282
379
 
283
- class MachineWithColumnDefaultTest < BaseTestCase
380
+ class MachineWithSameColumnDefaultTest < BaseTestCase
284
381
  def setup
382
+ @original_stderr, $stderr = $stderr, StringIO.new
383
+
384
+ @model = new_model do
385
+ key :status, String, :default => 'parked'
386
+ end
387
+ @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
388
+ @record = @model.new
389
+ end
390
+
391
+ def test_should_use_machine_default
392
+ assert_equal 'parked', @record.status
393
+ end
394
+
395
+ def test_should_not_generate_a_warning
396
+ assert_no_match(/have defined a different default/, $stderr.string)
397
+ end
398
+
399
+ def teardown
400
+ $stderr = @original_stderr
401
+ end
402
+ end
403
+
404
+ class MachineWithDifferentColumnDefaultTest < BaseTestCase
405
+ def setup
406
+ @original_stderr, $stderr = $stderr, StringIO.new
407
+
285
408
  @model = new_model do
286
409
  key :status, String, :default => 'idling'
287
410
  end
@@ -292,6 +415,39 @@ module MongoMapperTest
292
415
  def test_should_use_machine_default
293
416
  assert_equal 'parked', @record.status
294
417
  end
418
+
419
+ def test_should_generate_a_warning
420
+ assert_match(/Both MongoMapperTest::Foo and its :status machine have defined a different default for "status". Use only one or the other for defining defaults to avoid unexpected behaviors\./, $stderr.string)
421
+ end
422
+
423
+ def teardown
424
+ $stderr = @original_stderr
425
+ end
426
+ end
427
+
428
+ class MachineWithDifferentIntegerColumnDefaultTest < BaseTestCase
429
+ def setup
430
+ @original_stderr, $stderr = $stderr, StringIO.new
431
+
432
+ @model = new_model do
433
+ key :status, Integer, :default => 0
434
+ end
435
+ @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
436
+ @machine.state :parked, :value => 1
437
+ @record = @model.new
438
+ end
439
+
440
+ def test_should_use_machine_default
441
+ assert_equal 1, @record.status
442
+ end
443
+
444
+ def test_should_generate_a_warning
445
+ assert_match(/Both MongoMapperTest::Foo and its :status machine have defined a different default for "status". Use only one or the other for defining defaults to avoid unexpected behaviors\./, $stderr.string)
446
+ end
447
+
448
+ def teardown
449
+ $stderr = @original_stderr
450
+ end
295
451
  end
296
452
 
297
453
  class MachineWithConflictingPredicateTest < BaseTestCase
@@ -323,14 +479,14 @@ module MongoMapperTest
323
479
  @machine = StateMachine::Machine.new(@model)
324
480
  @machine.state :state
325
481
 
326
- assert_match /^Instance method "state\?" is already defined in .*, use generic helper instead.*\n$/, $stderr.string
482
+ assert_match(/^Instance method "state\?" is already defined in .*, use generic helper instead.*\n$/, $stderr.string)
327
483
  end
328
484
 
329
485
  def test_should_output_warning_with_same_machine_attribute
330
486
  @machine = StateMachine::Machine.new(@model, :public_state, :attribute => :state)
331
487
  @machine.state :state
332
488
 
333
- assert_match /^Instance method "state\?" is already defined in .*, use generic helper instead.*\n$/, $stderr.string
489
+ assert_match(/^Instance method "state\?" is already defined in .*, use generic helper instead.*\n$/, $stderr.string)
334
490
  end
335
491
 
336
492
  def teardown
@@ -441,24 +597,26 @@ module MongoMapperTest
441
597
  end
442
598
  end
443
599
 
444
- class MachineWithAliasedAttributeTest < BaseTestCase
445
- def setup
446
- @model = new_model do
447
- alias_attribute :vehicle_status, :state
600
+ if !defined?(MongoMapper::Version) || MongoMapper::Version =~ /^0\.[5-8]\./
601
+ class MachineWithAliasedAttributeTest < BaseTestCase
602
+ def setup
603
+ @model = new_model do
604
+ alias_attribute :vehicle_status, :state
605
+ end
606
+
607
+ @machine = StateMachine::Machine.new(@model, :status, :attribute => :vehicle_status)
608
+ @machine.state :parked
609
+
610
+ @record = @model.new
448
611
  end
449
612
 
450
- @machine = StateMachine::Machine.new(@model, :status, :attribute => :vehicle_status)
451
- @machine.state :parked
452
-
453
- @record = @model.new
454
- end
455
-
456
- def test_should_check_custom_attribute_for_predicate
457
- @record.vehicle_status = nil
458
- assert !@record.status?(:parked)
459
-
460
- @record.vehicle_status = 'parked'
461
- assert @record.status?(:parked)
613
+ def test_should_check_custom_attribute_for_predicate
614
+ @record.vehicle_status = nil
615
+ assert !@record.status?(:parked)
616
+
617
+ @record.vehicle_status = 'parked'
618
+ assert @record.status?(:parked)
619
+ end
462
620
  end
463
621
  end
464
622
 
@@ -529,7 +687,7 @@ module MongoMapperTest
529
687
  class MachineMultipleTest < BaseTestCase
530
688
  def setup
531
689
  @model = new_model do
532
- key :status, String, :default => 'idling'
690
+ key :status, String
533
691
  end
534
692
  @state_machine = StateMachine::Machine.new(@model, :initial => :parked)
535
693
  @status_machine = StateMachine::Machine.new(@model, :status, :initial => :idling)
@@ -625,7 +783,7 @@ module MongoMapperTest
625
783
  class MachineWithDirtyAttributesAndCustomAttributeTest < BaseTestCase
626
784
  def setup
627
785
  @model = new_model do
628
- key :status, String, :default => 'idling'
786
+ key :status, String
629
787
  end
630
788
  @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
631
789
  @machine.event :ignite
@@ -656,7 +814,7 @@ module MongoMapperTest
656
814
  class MachineWithDirtyAttributeAndCustomAttributesDuringLoopbackTest < BaseTestCase
657
815
  def setup
658
816
  @model = new_model do
659
- key :status, String, :default => 'idling'
817
+ key :status, String
660
818
  end
661
819
  @machine = StateMachine::Machine.new(@model, :status, :initial => :parked)
662
820
  @machine.event :park
@@ -789,11 +947,21 @@ module MongoMapperTest
789
947
  def test_should_run_around_callbacks
790
948
  before_called = false
791
949
  after_called = false
792
- @machine.around_transition {|block| before_called = true; block.call; after_called = true}
950
+ ensure_called = 0
951
+ @machine.around_transition do |block|
952
+ before_called = true
953
+ begin
954
+ block.call
955
+ ensure
956
+ ensure_called += 1
957
+ end
958
+ after_called = true
959
+ end
793
960
 
794
961
  @transition.perform
795
962
  assert before_called
796
963
  assert after_called
964
+ assert_equal ensure_called, 1
797
965
  end
798
966
 
799
967
  def test_should_include_transition_states_in_known_states
@@ -826,6 +994,29 @@ module MongoMapperTest
826
994
 
827
995
  assert_equal [1, 2, 3], @record.callback_result
828
996
  end
997
+
998
+ def test_should_run_in_expected_order
999
+ expected = [
1000
+ :before_transition, :before_validation, :after_validation,
1001
+ :before_save, :before_create, :after_create, :after_save,
1002
+ :after_transition
1003
+ ]
1004
+
1005
+ callbacks = []
1006
+ @model.before_validation { callbacks << :before_validation }
1007
+ @model.after_validation { callbacks << :after_validation }
1008
+ @model.before_save { callbacks << :before_save }
1009
+ @model.before_create { callbacks << :before_create }
1010
+ @model.after_create { callbacks << :after_create }
1011
+ @model.after_save { callbacks << :after_save }
1012
+
1013
+ @machine.before_transition { callbacks << :before_transition }
1014
+ @machine.after_transition { callbacks << :after_transition }
1015
+
1016
+ @transition.perform
1017
+
1018
+ assert_equal expected, callbacks
1019
+ end
829
1020
  end
830
1021
 
831
1022
  class MachineWithFailedBeforeCallbacksTest < BaseTestCase
@@ -881,6 +1072,42 @@ module MongoMapperTest
881
1072
  end
882
1073
  end
883
1074
 
1075
+ class MachineNestedActionTest < BaseTestCase
1076
+ def setup
1077
+ @callbacks = []
1078
+
1079
+ @model = new_model
1080
+ @machine = StateMachine::Machine.new(@model)
1081
+ @machine.event :ignite do
1082
+ transition :parked => :idling
1083
+ end
1084
+
1085
+ @record = @model.new(:state => 'parked')
1086
+ end
1087
+
1088
+ def test_should_allow_transition_prior_to_creation_if_skipping_action
1089
+ record = @record
1090
+ @model.before_create { record.ignite(false) }
1091
+ result = @record.save
1092
+
1093
+ assert_equal true, result
1094
+ assert_equal "idling", @record.state
1095
+ @record = @model.find(@record.id)
1096
+ assert_equal "idling", @record.state
1097
+ end
1098
+
1099
+ def test_should_allow_transition_after_creation
1100
+ record = @record
1101
+ @model.after_create { record.ignite }
1102
+ result = @record.save
1103
+
1104
+ assert_equal true, result
1105
+ assert_equal "idling", @record.state
1106
+ @record = @model.find(@record.id)
1107
+ assert_equal "idling", @record.state
1108
+ end
1109
+ end
1110
+
884
1111
  class MachineWithFailedActionTest < BaseTestCase
885
1112
  def setup
886
1113
  @model = new_model do
@@ -920,7 +1147,7 @@ module MongoMapperTest
920
1147
  end
921
1148
 
922
1149
  class MachineWithFailedAfterCallbacksTest < BaseTestCase
923
- def setup
1150
+ def setup
924
1151
  @callbacks = []
925
1152
 
926
1153
  @model = new_model
@@ -1006,10 +1233,7 @@ module MongoMapperTest
1006
1233
 
1007
1234
  class MachineWithValidationsAndCustomAttributeTest < BaseTestCase
1008
1235
  def setup
1009
- @model = new_model do
1010
- alias_attribute :status, :state
1011
- end
1012
-
1236
+ @model = new_model
1013
1237
  @machine = StateMachine::Machine.new(@model, :status, :attribute => :state)
1014
1238
  @machine.state :parked
1015
1239
 
@@ -1118,7 +1342,11 @@ module MongoMapperTest
1118
1342
  ran_callback = false
1119
1343
  @machine.around_transition {|block| ran_callback = true; block.call }
1120
1344
 
1121
- @record.valid?
1345
+ begin
1346
+ @record.valid?
1347
+ rescue ArgumentError
1348
+ raise if StateMachine::Transition.pause_supported?
1349
+ end
1122
1350
  assert ran_callback
1123
1351
  end
1124
1352
 
@@ -1152,7 +1380,11 @@ module MongoMapperTest
1152
1380
  ran_callback = false
1153
1381
  @machine.around_transition {|block| block.call; ran_callback = true }
1154
1382
 
1155
- @record.valid?
1383
+ begin
1384
+ @record.valid?
1385
+ rescue ArgumentError
1386
+ raise if StateMachine::Transition.pause_supported?
1387
+ end
1156
1388
  assert !ran_callback
1157
1389
  end
1158
1390
 
@@ -1298,6 +1530,73 @@ module MongoMapperTest
1298
1530
  @record.save
1299
1531
  assert ran_callback
1300
1532
  end
1533
+
1534
+ def test_should_allow_additional_transitions_to_new_state_in_after_transitions
1535
+ @machine.event :park do
1536
+ transition :idling => :parked
1537
+ end
1538
+
1539
+ @machine.after_transition(:on => :ignite) { @record.park }
1540
+
1541
+ @record.save
1542
+ assert_equal 'parked', @record.state
1543
+
1544
+ @record = @model.find(@record.id)
1545
+ assert_equal 'parked', @record.state
1546
+ end
1547
+
1548
+ def test_should_allow_additional_transitions_to_previous_state_in_after_transitions
1549
+ @machine.event :shift_up do
1550
+ transition :idling => :first_gear
1551
+ end
1552
+
1553
+ @machine.after_transition(:on => :ignite) { @record.shift_up }
1554
+
1555
+ @record.save
1556
+ assert_equal 'first_gear', @record.state
1557
+
1558
+ @record = @model.find(@record.id)
1559
+ assert_equal 'first_gear', @record.state
1560
+ end
1561
+ end
1562
+
1563
+ if defined?(MongoMapper::Version) && MongoMapper::Version !~ /^0\.[5-8]\./
1564
+ class MachineWithEventAttributesOnAutosaveTest < BaseTestCase
1565
+ def setup
1566
+ @vehicle_model = new_model(:vehicle) do
1567
+ belongs_to :owner, :class_name => 'MongoMapperTest::Owner'
1568
+ end
1569
+ MongoMapperTest.const_set('Vehicle', @vehicle_model)
1570
+
1571
+ @owner_model = new_model(:owner)
1572
+ MongoMapperTest.const_set('Owner', @owner_model)
1573
+
1574
+ machine = StateMachine::Machine.new(@vehicle_model)
1575
+ machine.event :ignite do
1576
+ transition :parked => :idling
1577
+ end
1578
+
1579
+ @owner = @owner_model.create
1580
+ @vehicle = @vehicle_model.create(:state => 'parked', :owner_id => @owner.id)
1581
+ end
1582
+
1583
+ def test_should_persist_many_association
1584
+ @owner_model.many :vehicles, :class_name => 'MongoMapperTest::Vehicle', :autosave => true
1585
+ @owner.vehicles[0].state_event = 'ignite'
1586
+ @owner.save
1587
+
1588
+ @vehicle.reload
1589
+ assert_equal 'idling', @vehicle.state
1590
+ end
1591
+
1592
+ def teardown
1593
+ MongoMapperTest.class_eval do
1594
+ remove_const('Vehicle')
1595
+ remove_const('Owner')
1596
+ end
1597
+ super
1598
+ end
1599
+ end
1301
1600
  end
1302
1601
 
1303
1602
  class MachineWithEventAttributesOnSaveBangTest < BaseTestCase
@@ -1364,11 +1663,6 @@ module MongoMapperTest
1364
1663
  assert_equal 'idling', @record.state
1365
1664
  end
1366
1665
 
1367
- def test_should_persist_new_state
1368
- @record.save!
1369
- assert_equal 'idling', @record.state
1370
- end
1371
-
1372
1666
  def test_should_run_after_callbacks
1373
1667
  ran_callback = false
1374
1668
  @machine.after_transition { ran_callback = true }
@@ -1439,7 +1733,7 @@ module MongoMapperTest
1439
1733
 
1440
1734
  def test_should_only_include_records_with_state_in_singular_with_scope
1441
1735
  parked = @model.create :state => 'parked'
1442
- idling = @model.create :state => 'idling'
1736
+ @model.create :state => 'idling'
1443
1737
 
1444
1738
  assert_equal [parked], @model.with_state(:parked).to_a
1445
1739
  end