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.
- data/.gitignore +7 -11
- data/.travis.yml +49 -7
- data/Appraisals +255 -87
- data/CHANGELOG.md +30 -0
- data/README.md +142 -21
- data/Rakefile +1 -11
- data/examples/Gemfile +5 -0
- data/examples/Gemfile.lock +14 -0
- data/examples/auto_shop.rb +2 -0
- data/examples/car.rb +2 -0
- data/examples/doc/AutoShop.html +2856 -0
- data/examples/doc/AutoShop_state.png +0 -0
- data/examples/doc/Car.html +919 -0
- data/examples/doc/Car_state.png +0 -0
- data/examples/doc/TrafficLight.html +2230 -0
- data/examples/doc/TrafficLight_state.png +0 -0
- data/examples/doc/Vehicle.html +7921 -0
- data/examples/doc/Vehicle_state.png +0 -0
- data/examples/doc/_index.html +136 -0
- data/examples/doc/class_list.html +47 -0
- data/examples/doc/css/common.css +1 -0
- data/examples/doc/css/full_list.css +55 -0
- data/examples/doc/css/style.css +322 -0
- data/examples/doc/file_list.html +46 -0
- data/examples/doc/frames.html +13 -0
- data/examples/doc/index.html +136 -0
- data/examples/doc/js/app.js +205 -0
- data/examples/doc/js/full_list.js +173 -0
- data/examples/doc/js/jquery.js +16 -0
- data/examples/doc/method_list.html +734 -0
- data/examples/doc/top-level-namespace.html +105 -0
- data/examples/rails-rest/migration.rb +1 -5
- data/examples/rails-rest/view__form.html.erb +34 -0
- data/examples/rails-rest/view_edit.html.erb +2 -21
- data/examples/rails-rest/view_index.html.erb +6 -4
- data/examples/rails-rest/view_new.html.erb +2 -11
- data/examples/rails-rest/view_show.html.erb +5 -3
- data/examples/traffic_light.rb +2 -0
- data/examples/vehicle.rb +2 -0
- data/gemfiles/active_model-3.0.0.gemfile.lock +9 -6
- data/gemfiles/active_model-3.0.5.gemfile.lock +10 -7
- data/gemfiles/active_model-3.1.1.gemfile.lock +12 -10
- data/gemfiles/{active_model-3.2.0.gemfile → active_model-3.2.1.gemfile} +1 -1
- data/gemfiles/{graphviz-0.9.0.gemfile → active_model-3.2.12.gemfile} +1 -1
- data/gemfiles/active_model-3.2.12.gemfile.lock +36 -0
- data/gemfiles/{active_record-3.2.0.gemfile → active_model-3.2.13.rc1.gemfile} +1 -2
- data/gemfiles/active_model-3.2.13.rc1.gemfile.lock +36 -0
- data/gemfiles/active_model-4.0.0.gemfile +9 -0
- data/gemfiles/active_model-4.0.0.gemfile.lock +78 -0
- data/gemfiles/active_record-2.0.0.gemfile +2 -1
- data/gemfiles/active_record-2.0.0.gemfile.lock +15 -6
- data/gemfiles/active_record-2.0.5.gemfile +2 -1
- data/gemfiles/active_record-2.0.5.gemfile.lock +15 -6
- data/gemfiles/active_record-2.1.0.gemfile +2 -1
- data/gemfiles/active_record-2.1.0.gemfile.lock +15 -6
- data/gemfiles/active_record-2.1.2.gemfile +2 -1
- data/gemfiles/active_record-2.1.2.gemfile.lock +15 -6
- data/gemfiles/active_record-2.2.3.gemfile +2 -1
- data/gemfiles/active_record-2.2.3.gemfile.lock +15 -6
- data/gemfiles/active_record-2.3.12.gemfile +2 -1
- data/gemfiles/active_record-2.3.12.gemfile.lock +15 -6
- data/gemfiles/active_record-2.3.5.gemfile +9 -0
- data/gemfiles/active_record-2.3.5.gemfile.lock +39 -0
- data/gemfiles/active_record-3.0.0.gemfile +2 -1
- data/gemfiles/active_record-3.0.0.gemfile.lock +18 -11
- data/gemfiles/active_record-3.0.5.gemfile +2 -1
- data/gemfiles/active_record-3.0.5.gemfile.lock +19 -12
- data/gemfiles/active_record-3.1.1.gemfile +2 -1
- data/gemfiles/active_record-3.1.1.gemfile.lock +22 -16
- data/gemfiles/active_record-3.2.12.gemfile +9 -0
- data/gemfiles/active_record-3.2.12.gemfile.lock +51 -0
- data/gemfiles/active_record-3.2.13.rc1.gemfile +9 -0
- data/gemfiles/active_record-3.2.13.rc1.gemfile.lock +51 -0
- data/gemfiles/active_record-4.0.0.gemfile +11 -0
- data/gemfiles/active_record-4.0.0.gemfile.lock +83 -0
- data/gemfiles/data_mapper-0.10.2.gemfile +1 -0
- data/gemfiles/data_mapper-0.10.2.gemfile.lock +13 -9
- data/gemfiles/data_mapper-0.9.11.gemfile +1 -0
- data/gemfiles/data_mapper-0.9.11.gemfile.lock +31 -7
- data/gemfiles/data_mapper-0.9.4.gemfile.lock +25 -14
- data/gemfiles/data_mapper-0.9.7.gemfile +1 -0
- data/gemfiles/data_mapper-0.9.7.gemfile.lock +27 -15
- data/gemfiles/data_mapper-1.0.0.gemfile.lock +20 -17
- data/gemfiles/data_mapper-1.0.1.gemfile.lock +20 -17
- data/gemfiles/data_mapper-1.0.2.gemfile.lock +20 -17
- data/gemfiles/data_mapper-1.1.0.gemfile.lock +19 -16
- data/gemfiles/data_mapper-1.2.0.gemfile.lock +19 -16
- data/gemfiles/default.gemfile.lock +8 -5
- data/gemfiles/graphviz-0.9.17.gemfile +7 -0
- data/gemfiles/graphviz-0.9.17.gemfile.lock +29 -0
- data/gemfiles/graphviz-0.9.21.gemfile.lock +7 -4
- data/gemfiles/graphviz-1.0.0.gemfile.lock +7 -4
- data/gemfiles/graphviz-1.0.3.gemfile +7 -0
- data/gemfiles/graphviz-1.0.3.gemfile.lock +29 -0
- data/gemfiles/graphviz-1.0.8.gemfile +7 -0
- data/gemfiles/graphviz-1.0.8.gemfile.lock +29 -0
- data/gemfiles/mongo_mapper-0.10.0.gemfile +1 -0
- data/gemfiles/mongo_mapper-0.10.0.gemfile.lock +14 -11
- data/gemfiles/mongo_mapper-0.11.1.gemfile +7 -0
- data/gemfiles/mongo_mapper-0.11.1.gemfile.lock +44 -0
- data/gemfiles/mongo_mapper-0.11.2.gemfile +9 -0
- data/gemfiles/mongo_mapper-0.11.2.gemfile.lock +48 -0
- data/gemfiles/mongo_mapper-0.12.0.gemfile +9 -0
- data/gemfiles/mongo_mapper-0.12.0.gemfile.lock +48 -0
- data/gemfiles/mongo_mapper-0.5.5.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.5.8.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.6.0.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.6.10.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.7.0.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.7.5.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.8.0.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.8.3.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.8.4.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.8.6.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.9.0.gemfile.lock +7 -4
- data/gemfiles/mongoid-2.0.0.gemfile +2 -0
- data/gemfiles/mongoid-2.0.0.gemfile.lock +22 -18
- data/gemfiles/mongoid-2.1.4.gemfile +2 -0
- data/gemfiles/mongoid-2.1.4.gemfile.lock +21 -17
- data/gemfiles/mongoid-2.2.4.gemfile +2 -0
- data/gemfiles/mongoid-2.2.4.gemfile.lock +21 -17
- data/gemfiles/mongoid-2.3.3.gemfile +2 -0
- data/gemfiles/mongoid-2.3.3.gemfile.lock +21 -17
- data/gemfiles/mongoid-2.4.0.gemfile +9 -0
- data/gemfiles/mongoid-2.4.0.gemfile.lock +47 -0
- data/gemfiles/mongoid-2.4.10.gemfile +9 -0
- data/gemfiles/mongoid-2.4.10.gemfile.lock +47 -0
- data/gemfiles/mongoid-2.5.2.gemfile +9 -0
- data/gemfiles/mongoid-2.5.2.gemfile.lock +47 -0
- data/gemfiles/mongoid-2.6.0.gemfile +9 -0
- data/gemfiles/mongoid-2.6.0.gemfile.lock +47 -0
- data/gemfiles/mongoid-3.0.0.gemfile +8 -0
- data/gemfiles/mongoid-3.0.0.gemfile.lock +45 -0
- data/gemfiles/mongoid-3.0.22.gemfile +8 -0
- data/gemfiles/mongoid-3.0.22.gemfile.lock +45 -0
- data/gemfiles/mongoid-3.1.0.gemfile +8 -0
- data/gemfiles/mongoid-3.1.0.gemfile.lock +45 -0
- data/gemfiles/sequel-2.11.0.gemfile +2 -1
- data/gemfiles/sequel-2.11.0.gemfile.lock +11 -6
- data/gemfiles/sequel-2.12.0.gemfile +2 -1
- data/gemfiles/sequel-2.12.0.gemfile.lock +11 -6
- data/gemfiles/sequel-2.8.0.gemfile +2 -1
- data/gemfiles/sequel-2.8.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.0.0.gemfile +2 -1
- data/gemfiles/sequel-3.0.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.10.0.gemfile +9 -0
- data/gemfiles/sequel-3.10.0.gemfile.lock +33 -0
- data/gemfiles/sequel-3.13.0.gemfile +2 -1
- data/gemfiles/sequel-3.13.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.14.0.gemfile +2 -1
- data/gemfiles/sequel-3.14.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.23.0.gemfile +2 -1
- data/gemfiles/sequel-3.23.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.24.0.gemfile +2 -1
- data/gemfiles/sequel-3.24.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.29.0.gemfile +2 -1
- data/gemfiles/sequel-3.29.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.34.0.gemfile +9 -0
- data/gemfiles/sequel-3.34.0.gemfile.lock +33 -0
- data/gemfiles/sequel-3.35.0.gemfile +9 -0
- data/gemfiles/sequel-3.35.0.gemfile.lock +33 -0
- data/gemfiles/sequel-3.4.0.gemfile +9 -0
- data/gemfiles/sequel-3.4.0.gemfile.lock +33 -0
- data/gemfiles/sequel-3.44.0.gemfile +9 -0
- data/gemfiles/sequel-3.44.0.gemfile.lock +33 -0
- data/lib/state_machine.rb +6 -0
- data/lib/state_machine/branch.rb +9 -8
- data/lib/state_machine/callback.rb +2 -2
- data/lib/state_machine/core.rb +10 -0
- data/lib/state_machine/core_ext.rb +1 -0
- data/lib/state_machine/eval_helpers.rb +5 -3
- data/lib/state_machine/event.rb +17 -6
- data/lib/state_machine/graph.rb +92 -0
- data/lib/state_machine/integrations.rb +13 -1
- data/lib/state_machine/integrations/active_model.rb +14 -20
- data/lib/state_machine/integrations/active_model/observer.rb +3 -3
- data/lib/state_machine/integrations/active_model/observer_update.rb +42 -0
- data/lib/state_machine/integrations/active_record.rb +52 -25
- data/lib/state_machine/integrations/active_record/locale.rb +1 -1
- data/lib/state_machine/integrations/active_record/versions.rb +1 -17
- data/lib/state_machine/integrations/base.rb +15 -6
- data/lib/state_machine/integrations/data_mapper.rb +98 -35
- data/lib/state_machine/integrations/data_mapper/versions.rb +46 -8
- data/lib/state_machine/integrations/mongo_mapper.rb +39 -12
- data/lib/state_machine/integrations/mongo_mapper/locale.rb +1 -1
- data/lib/state_machine/integrations/mongo_mapper/versions.rb +3 -20
- data/lib/state_machine/integrations/mongoid.rb +52 -14
- data/lib/state_machine/integrations/mongoid/locale.rb +1 -1
- data/lib/state_machine/integrations/mongoid/versions.rb +52 -26
- data/lib/state_machine/integrations/sequel.rb +82 -33
- data/lib/state_machine/integrations/sequel/versions.rb +19 -44
- data/lib/state_machine/machine.rb +99 -59
- data/lib/state_machine/machine_collection.rb +1 -2
- data/lib/state_machine/macro_methods.rb +29 -0
- data/lib/state_machine/node_collection.rb +1 -1
- data/lib/state_machine/state.rb +18 -10
- data/lib/state_machine/state_context.rb +2 -2
- data/lib/state_machine/transition.rb +8 -1
- data/lib/state_machine/transition_collection.rb +2 -1
- data/lib/state_machine/version.rb +1 -1
- data/lib/state_machine/yard.rb +8 -0
- data/lib/state_machine/yard/handlers.rb +12 -0
- data/lib/state_machine/yard/handlers/base.rb +32 -0
- data/lib/state_machine/yard/handlers/event.rb +25 -0
- data/lib/state_machine/yard/handlers/machine.rb +344 -0
- data/lib/state_machine/yard/handlers/state.rb +25 -0
- data/lib/state_machine/yard/handlers/transition.rb +47 -0
- data/lib/state_machine/yard/templates.rb +3 -0
- data/lib/state_machine/yard/templates/default/class/html/setup.rb +30 -0
- data/lib/state_machine/yard/templates/default/class/html/state_machines.erb +12 -0
- data/lib/tasks/state_machine.rb +2 -1
- data/lib/yard-state_machine.rb +2 -0
- data/state_machine.gemspec +4 -3
- data/test/files/switch.rb +4 -0
- data/test/test_helper.rb +5 -0
- data/test/unit/branch_test.rb +117 -36
- data/test/unit/callback_test.rb +5 -2
- data/test/unit/eval_helpers_test.rb +49 -1
- data/test/unit/event_collection_test.rb +3 -1
- data/test/unit/event_test.rb +182 -12
- data/test/unit/graph_test.rb +98 -0
- data/test/unit/integrations/active_model_test.rb +82 -12
- data/test/unit/integrations/active_record_test.rb +393 -37
- data/test/unit/integrations/base_test.rb +7 -2
- data/test/unit/integrations/data_mapper_test.rb +326 -72
- data/test/unit/integrations/mongo_mapper_test.rb +338 -44
- data/test/unit/integrations/mongoid_test.rb +606 -98
- data/test/unit/integrations/sequel_test.rb +429 -102
- data/test/unit/integrations_test.rb +28 -6
- data/test/unit/machine_collection_test.rb +6 -2
- data/test/unit/machine_test.rb +134 -82
- data/test/unit/node_collection_test.rb +2 -2
- data/test/unit/path_test.rb +1 -1
- data/test/unit/state_test.rb +65 -21
- data/test/unit/transition_collection_test.rb +43 -23
- data/test/unit/transition_test.rb +8 -2
- metadata +303 -221
- data/gemfiles/active_model-3.2.0.gemfile.lock +0 -32
- data/gemfiles/active_record-3.2.0.gemfile.lock +0 -43
- data/gemfiles/graphviz-0.9.0.gemfile.lock +0 -26
@@ -283,6 +283,22 @@ module StateMachine
|
|
283
283
|
# end
|
284
284
|
# end
|
285
285
|
#
|
286
|
+
# === Callback Order
|
287
|
+
#
|
288
|
+
# Callbacks occur in the following order. Callbacks specific to state_machine
|
289
|
+
# are bolded. The remaining callbacks are part of Mongoid.
|
290
|
+
#
|
291
|
+
# * (-) save
|
292
|
+
# * (1) *before_transition*
|
293
|
+
# * (-) valid
|
294
|
+
# * (2) before_validation
|
295
|
+
# * (3) after_validation
|
296
|
+
# * (4) before_save
|
297
|
+
# * (5) before_create
|
298
|
+
# * (6) after_create
|
299
|
+
# * (7) after_save
|
300
|
+
# * (8) *after_transition*
|
301
|
+
#
|
286
302
|
# == Internationalization
|
287
303
|
#
|
288
304
|
# Any error message that is generated from performing invalid transitions
|
@@ -341,17 +357,10 @@ module StateMachine
|
|
341
357
|
# The default options to use for state machines using this integration
|
342
358
|
@defaults = {:action => :save}
|
343
359
|
|
344
|
-
# Whether this integration is available. Only true if Mongoid::Document
|
345
|
-
# is defined.
|
346
|
-
def self.available?
|
347
|
-
defined?(::Mongoid::Document)
|
348
|
-
end
|
349
|
-
|
350
|
-
# Should this integration be used for state machines in the given class?
|
351
360
|
# Classes that include Mongoid::Document will automatically use the
|
352
361
|
# Mongoid integration.
|
353
|
-
def self.
|
354
|
-
|
362
|
+
def self.matching_ancestors
|
363
|
+
%w(Mongoid::Document)
|
355
364
|
end
|
356
365
|
|
357
366
|
def self.extended(base) #:nodoc:
|
@@ -365,33 +374,62 @@ module StateMachine
|
|
365
374
|
action == :save
|
366
375
|
end
|
367
376
|
|
377
|
+
# Gets the db default for the machine's attribute
|
378
|
+
def owner_class_attribute_default
|
379
|
+
attribute_field && attribute_field.default_val
|
380
|
+
end
|
381
|
+
|
382
|
+
# Gets the field for this machine's attribute (if it exists)
|
383
|
+
def attribute_field
|
384
|
+
owner_class.fields[attribute.to_s] || owner_class.fields[owner_class.aliased_fields[attribute.to_s]]
|
385
|
+
end
|
386
|
+
|
368
387
|
# Defines an initialization hook into the owner class for setting the
|
369
388
|
# initial state of the machine *before* any attributes are set on the
|
370
389
|
# object
|
371
390
|
def define_state_initializer
|
372
391
|
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
373
392
|
def initialize(*)
|
374
|
-
@attributes ||= {}
|
375
|
-
self.class.state_machines.initialize_states(self, :dynamic => false)
|
376
|
-
|
377
393
|
super do |*args|
|
378
394
|
self.class.state_machines.initialize_states(self, :static => false)
|
379
395
|
yield(*args) if block_given?
|
380
396
|
end
|
381
397
|
end
|
398
|
+
|
399
|
+
def apply_pre_processed_defaults
|
400
|
+
defaults = {}
|
401
|
+
self.class.state_machines.initialize_states(self, :static => :force, :dynamic => false, :to => defaults)
|
402
|
+
defaults.each do |attr, value|
|
403
|
+
send(:"\#{attr}=", value) unless attributes.include?(attr)
|
404
|
+
end
|
405
|
+
super
|
406
|
+
end
|
382
407
|
end_eval
|
383
408
|
end
|
384
409
|
|
385
410
|
# Skips defining reader/writer methods since this is done automatically
|
386
411
|
def define_state_accessor
|
387
|
-
owner_class.field(attribute, :type => String) unless
|
412
|
+
owner_class.field(attribute, :type => String) unless attribute_field
|
388
413
|
super
|
389
414
|
end
|
390
415
|
|
391
416
|
# Uses around callbacks to run state events if using the :save hook
|
392
417
|
def define_action_hook
|
393
418
|
if action_hook == :save
|
394
|
-
|
419
|
+
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
420
|
+
def insert(*)
|
421
|
+
self.class.state_machine(#{name.inspect}).send(:around_save, self) { super.persisted? }
|
422
|
+
self
|
423
|
+
end
|
424
|
+
|
425
|
+
def update(*)
|
426
|
+
self.class.state_machine(#{name.inspect}).send(:around_save, self) { super }
|
427
|
+
end
|
428
|
+
|
429
|
+
def upsert(*)
|
430
|
+
self.class.state_machine(#{name.inspect}).send(:around_save, self) { super }
|
431
|
+
end
|
432
|
+
end_eval
|
395
433
|
else
|
396
434
|
super
|
397
435
|
end
|
@@ -1,4 +1,4 @@
|
|
1
1
|
filename = "#{File.dirname(__FILE__)}/../active_model/locale.rb"
|
2
|
-
translations = eval(IO.read(filename), binding, filename)
|
2
|
+
translations = eval(IO.read(File.expand_path(filename)), binding, filename)
|
3
3
|
translations[:en][:mongoid] = translations[:en].delete(:activemodel)
|
4
4
|
translations
|
@@ -1,53 +1,79 @@
|
|
1
1
|
module StateMachine
|
2
2
|
module Integrations #:nodoc:
|
3
3
|
module Mongoid
|
4
|
-
version '2.
|
4
|
+
version '2.x' do
|
5
5
|
def self.active?
|
6
|
-
::Mongoid::VERSION =~ /^2
|
6
|
+
::Mongoid::VERSION =~ /^2\./
|
7
7
|
end
|
8
8
|
|
9
9
|
def define_state_initializer
|
10
10
|
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
11
|
-
# Initializes dynamic states
|
12
11
|
def initialize(*)
|
12
|
+
@attributes ||= {}
|
13
|
+
self.class.state_machines.initialize_states(self, :static => :force, :dynamic => false)
|
14
|
+
|
13
15
|
super do |*args|
|
14
16
|
self.class.state_machines.initialize_states(self, :static => false)
|
15
17
|
yield(*args) if block_given?
|
16
18
|
end
|
17
19
|
end
|
18
|
-
|
19
|
-
# Initializes static states
|
20
|
-
def apply_default_attributes(*)
|
21
|
-
result = super
|
22
|
-
self.class.state_machines.initialize_states(self, :dynamic => false, :to => result) if new_record?
|
23
|
-
result
|
24
|
-
end
|
25
20
|
end_eval
|
26
21
|
end
|
27
22
|
|
23
|
+
def owner_class_attribute_default
|
24
|
+
attribute_field && attribute_field.default
|
25
|
+
end
|
26
|
+
|
28
27
|
def define_action_hook
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
if action_hook == :save
|
29
|
+
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
30
|
+
def insert(*)
|
31
|
+
self.class.state_machine(#{name.inspect}).send(:around_save, self) { super.persisted? }
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def update(*)
|
36
|
+
self.class.state_machine(#{name.inspect}).send(:around_save, self) { super }
|
37
|
+
end
|
38
|
+
end_eval
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
32
42
|
end
|
33
43
|
end
|
34
44
|
|
35
|
-
version '2.0.x' do
|
45
|
+
version '2.0.x - 2.3.x' do
|
36
46
|
def self.active?
|
37
|
-
::Mongoid::VERSION =~ /^2\.0\./
|
47
|
+
::Mongoid::VERSION =~ /^2\.[0-3]\./
|
38
48
|
end
|
39
49
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
def attribute_field
|
51
|
+
owner_class.fields[attribute.to_s]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
version '2.0.x - 2.2.x' do
|
56
|
+
def self.active?
|
57
|
+
::Mongoid::VERSION =~ /^2\.[0-2]\./
|
58
|
+
end
|
59
|
+
|
60
|
+
def define_state_initializer
|
61
|
+
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
62
|
+
# Initializes dynamic states
|
63
|
+
def initialize(*)
|
64
|
+
super do |*args|
|
65
|
+
self.class.state_machines.initialize_states(self, :static => false)
|
66
|
+
yield(*args) if block_given?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Initializes static states
|
71
|
+
def apply_default_attributes(*)
|
72
|
+
result = super
|
73
|
+
self.class.state_machines.initialize_states(self, :static => :force, :dynamic => false, :to => result) if new_record?
|
74
|
+
result
|
75
|
+
end
|
76
|
+
end_eval
|
51
77
|
end
|
52
78
|
end
|
53
79
|
end
|
@@ -134,18 +134,6 @@ module StateMachine
|
|
134
134
|
# end
|
135
135
|
# end
|
136
136
|
#
|
137
|
-
# If using the +save+ action for the machine, this option will be ignored as
|
138
|
-
# the transaction will be created by Sequel within +save+. To avoid
|
139
|
-
# this, use a different action like so:
|
140
|
-
#
|
141
|
-
# class Vehicle < Sequel::Model
|
142
|
-
# state_machine :initial => :parked, :use_transactions => false, :action => :save_state do
|
143
|
-
# ...
|
144
|
-
# end
|
145
|
-
#
|
146
|
-
# alias_method :save_state, :save
|
147
|
-
# end
|
148
|
-
#
|
149
137
|
# == Validation errors
|
150
138
|
#
|
151
139
|
# If an event fails to successfully fire because there are no matching
|
@@ -265,26 +253,38 @@ module StateMachine
|
|
265
253
|
# The +TransitionLog+ model uses a second connection to the database that
|
266
254
|
# allows new records to be saved without being affected by rollbacks in the
|
267
255
|
# +Vehicle+ model's transaction.
|
256
|
+
#
|
257
|
+
# === Callback Order
|
258
|
+
#
|
259
|
+
# Callbacks occur in the following order. Callbacks specific to state_machine
|
260
|
+
# are bolded. The remaining callbacks are part of Sequel.
|
261
|
+
#
|
262
|
+
# * (-) save
|
263
|
+
# * (-) begin transaction (if enabled)
|
264
|
+
# * (1) *before_transition*
|
265
|
+
# * (2) before_validation
|
266
|
+
# * (-) validate
|
267
|
+
# * (3) after_validation
|
268
|
+
# * (4) before_save
|
269
|
+
# * (5) before_create
|
270
|
+
# * (-) create
|
271
|
+
# * (6) after_create
|
272
|
+
# * (7) after_save
|
273
|
+
# * (8) *after_transition*
|
274
|
+
# * (-) end transaction (if enabled)
|
275
|
+
# * (9) after_commit
|
268
276
|
module Sequel
|
269
277
|
include Base
|
270
278
|
|
271
279
|
require 'state_machine/integrations/sequel/versions'
|
272
280
|
|
273
281
|
# The default options to use for state machines using this integration
|
274
|
-
class << self; attr_reader :defaults; end
|
275
282
|
@defaults = {:action => :save}
|
276
283
|
|
277
|
-
# Whether this integration is available. Only true if Sequel::Model is
|
278
|
-
# defined.
|
279
|
-
def self.available?
|
280
|
-
defined?(::Sequel::Model)
|
281
|
-
end
|
282
|
-
|
283
|
-
# Should this integration be used for state machines in the given class?
|
284
284
|
# Classes that include Sequel::Model will automatically use the Sequel
|
285
285
|
# integration.
|
286
|
-
def self.
|
287
|
-
|
286
|
+
def self.matching_ancestors
|
287
|
+
%w(Sequel::Model)
|
288
288
|
end
|
289
289
|
|
290
290
|
# Forces the change in state to be recognized regardless of whether the
|
@@ -331,7 +331,6 @@ module StateMachine
|
|
331
331
|
|
332
332
|
# Loads all of the Sequel plugins necessary to run
|
333
333
|
def load_plugins
|
334
|
-
owner_class.plugin(:validation_class_methods)
|
335
334
|
owner_class.plugin(:hook_class_methods)
|
336
335
|
end
|
337
336
|
|
@@ -346,18 +345,20 @@ module StateMachine
|
|
346
345
|
def define_state_initializer
|
347
346
|
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
348
347
|
def initialize_set(*)
|
349
|
-
self.class.state_machines.initialize_states(self) { super }
|
348
|
+
self.class.state_machines.initialize_states(self, :static => :force) { super }
|
350
349
|
end
|
351
350
|
end_eval
|
352
351
|
end
|
353
352
|
|
354
353
|
# Skips defining reader/writer methods since this is done automatically
|
355
354
|
def define_state_accessor
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
355
|
+
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
356
|
+
def validate(*)
|
357
|
+
super
|
358
|
+
machine = self.class.state_machine(#{name.inspect})
|
359
|
+
machine.invalidate(self, :state, :invalid) unless machine.states.match(self)
|
360
|
+
end
|
361
|
+
end_eval
|
361
362
|
end
|
362
363
|
|
363
364
|
# Defines validation hooks if the machine's action is to save the model
|
@@ -366,6 +367,43 @@ module StateMachine
|
|
366
367
|
define_validation_hook if action == :save
|
367
368
|
end
|
368
369
|
|
370
|
+
# Uses around callbacks to run state events if using the :save hook
|
371
|
+
def define_action_hook
|
372
|
+
if action == :save
|
373
|
+
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
374
|
+
def #{action_hook}(*args)
|
375
|
+
opts = args.last.is_a?(Hash) ? args.last : {}
|
376
|
+
yielded = false
|
377
|
+
result = self.class.state_machine(#{name.inspect}).send(:around_save, self) do
|
378
|
+
yielded = true
|
379
|
+
super
|
380
|
+
end
|
381
|
+
|
382
|
+
if yielded || result
|
383
|
+
result
|
384
|
+
else
|
385
|
+
#{handle_save_failure}
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end_eval
|
389
|
+
else
|
390
|
+
super
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
# Handles how save failures (due to invalid transitions) are raised
|
395
|
+
def handle_save_failure
|
396
|
+
'raise_hook_failure(:before_transition) if raise_on_failure?(opts)'
|
397
|
+
end
|
398
|
+
|
399
|
+
# Runs state events around the machine's :save action
|
400
|
+
def around_save(object)
|
401
|
+
result = transaction(object) do
|
402
|
+
object.class.state_machines.transitions(object, action).perform { yield }
|
403
|
+
end
|
404
|
+
result
|
405
|
+
end
|
406
|
+
|
369
407
|
# Adds hooks into validation for automatically firing events
|
370
408
|
def define_validation_hook
|
371
409
|
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
@@ -375,9 +413,16 @@ module StateMachine
|
|
375
413
|
end_eval
|
376
414
|
end
|
377
415
|
|
378
|
-
#
|
379
|
-
def
|
380
|
-
|
416
|
+
# Gets the db default for the machine's attribute
|
417
|
+
def owner_class_attribute_default
|
418
|
+
if owner_class.db.table_exists?(owner_class.table_name) && column = owner_class.db_schema[attribute.to_sym]
|
419
|
+
column[:default]
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
# Uses the DB literal to match the default against the specified state
|
424
|
+
def owner_class_attribute_default_matches?(state)
|
425
|
+
owner_class.db.literal(state.value) == owner_class_attribute_default
|
381
426
|
end
|
382
427
|
|
383
428
|
# Creates a scope for finding records *with* a particular state or
|
@@ -421,7 +466,11 @@ module StateMachine
|
|
421
466
|
# Runs a new database transaction, rolling back any changes if the
|
422
467
|
# yielded block fails (i.e. returns false).
|
423
468
|
def transaction(object)
|
424
|
-
|
469
|
+
result = nil
|
470
|
+
object.db.transaction do
|
471
|
+
raise ::Sequel::Error::Rollback unless result = yield
|
472
|
+
end
|
473
|
+
result
|
425
474
|
end
|
426
475
|
|
427
476
|
# Creates a new callback in the callback chain, always ensuring that
|
@@ -17,7 +17,7 @@ module StateMachine
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def set(*)
|
20
|
-
self.class.state_machines.initialize_states(self, :dynamic => false) if values.empty?
|
20
|
+
self.class.state_machines.initialize_states(self, :static => :force, :dynamic => false) if values.empty?
|
21
21
|
super
|
22
22
|
end
|
23
23
|
end_eval
|
@@ -26,6 +26,7 @@ module StateMachine
|
|
26
26
|
def define_validation_hook
|
27
27
|
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
28
28
|
def valid?(*args)
|
29
|
+
opts = args.first.is_a?(Hash) ? args.first : {}
|
29
30
|
yielded = false
|
30
31
|
result = self.class.state_machines.transitions(self, :save, :after => false).perform do
|
31
32
|
yielded = true
|
@@ -40,31 +41,19 @@ module StateMachine
|
|
40
41
|
end
|
41
42
|
end_eval
|
42
43
|
end
|
44
|
+
end
|
45
|
+
|
46
|
+
version '2.8.x - 3.13.x' do
|
47
|
+
def self.active?
|
48
|
+
!defined?(::Sequel::MAJOR) || ::Sequel::MAJOR == 2 || ::Sequel::MAJOR == 3 && ::Sequel::MINOR <= 13
|
49
|
+
end
|
43
50
|
|
44
|
-
def
|
45
|
-
|
46
|
-
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
47
|
-
def #{action_hook}(*)
|
48
|
-
yielded = false
|
49
|
-
result = self.class.state_machines.transitions(self, :save).perform do
|
50
|
-
yielded = true
|
51
|
-
super
|
52
|
-
end
|
53
|
-
|
54
|
-
if yielded || result
|
55
|
-
result
|
56
|
-
else
|
57
|
-
#{handle_save_failure}
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end_eval
|
61
|
-
else
|
62
|
-
super
|
63
|
-
end
|
51
|
+
def handle_validation_failure
|
52
|
+
'raise_on_save_failure ? save_failure(:validation) : result'
|
64
53
|
end
|
65
54
|
|
66
|
-
def
|
67
|
-
|
55
|
+
def handle_save_failure
|
56
|
+
'save_failure(:save) if raise_on_save_failure'
|
68
57
|
end
|
69
58
|
end
|
70
59
|
|
@@ -79,26 +68,16 @@ module StateMachine
|
|
79
68
|
def load_inflector
|
80
69
|
end
|
81
70
|
|
82
|
-
def action_hook
|
83
|
-
action == :save ? :save : super
|
84
|
-
end
|
85
|
-
|
86
71
|
def model_from_dataset(dataset)
|
87
72
|
dataset.model_classes[nil]
|
88
73
|
end
|
89
|
-
end
|
90
|
-
|
91
|
-
version '2.8.x - 3.13.x' do
|
92
|
-
def self.active?
|
93
|
-
!defined?(::Sequel::MAJOR) || ::Sequel::MAJOR == 2 || ::Sequel::MAJOR == 3 && ::Sequel::MINOR <= 13
|
94
|
-
end
|
95
|
-
|
96
|
-
def handle_validation_failure
|
97
|
-
'raise_on_save_failure ? save_failure(:validation) : result'
|
98
|
-
end
|
99
74
|
|
100
|
-
def
|
101
|
-
|
75
|
+
def define_state_accessor
|
76
|
+
name = self.name
|
77
|
+
owner_class.validates_each(attribute) do |record, attr, value|
|
78
|
+
machine = record.class.state_machine(name)
|
79
|
+
machine.invalidate(record, :state, :invalid) unless machine.states.match(record)
|
80
|
+
end
|
102
81
|
end
|
103
82
|
end
|
104
83
|
|
@@ -108,11 +87,7 @@ module StateMachine
|
|
108
87
|
end
|
109
88
|
|
110
89
|
def handle_validation_failure
|
111
|
-
'raise_on_failure?(
|
112
|
-
end
|
113
|
-
|
114
|
-
def handle_save_failure
|
115
|
-
'raise_hook_failure(:save)'
|
90
|
+
'raise_on_failure?(opts) ? raise_hook_failure(:validation) : result'
|
116
91
|
end
|
117
92
|
end
|
118
93
|
end
|