state_machine 1.1.2 → 1.2.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.
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