module StateMachine::Integrations::DataMapper::Observer
Adds support for creating before/after/around/failure transition callbacks within a DataMapper observer. These callbacks behave very similar to hooks during save/update/destroy/etc., but with the following modifications:
-
Each callback can define a set of transition requirements that must be met in order for the callback to get invoked.
-
An additional transition parameter is available that provides contextual information about the event (see StateMachine::Transition for more information)
To define a single observer for multiple state machines:
class StateMachineObserver include DataMapper::Observer observe Vehicle, Switch, Project after_transition do |transition| Audit.log(self, transition) end end
Requirements¶ ↑
To use this feature of the DataMapper integration, the dm-observer library must be available. This can be installed either directly or indirectly through dm-more. When loading DataMapper, be sure to load the dm-observer library as well like so:
require 'rubygems' require 'dm-core' require 'dm-observer'
If dm-observer is not available, then this feature will be skipped.
Public Instance Methods
Creates a callback that will be invoked after a transition is performed so long as the given configuration options match the transition.
See before_transition
for a description of the possible
configurations for defining callbacks.
# File lib/state_machine/integrations/data_mapper/observer.rb, line 103 def after_transition(*args, &block) add_transition_callback(:after_transition, *args, &block) end
Creates a callback that will be invoked after a transition failures to be performed so long as the given requirements match the transition.
Example¶ ↑
class Vehicle include DataMapper::Resource property :id, Serial property :state, :String state_machine :initial => :parked do event :ignite do transition :parked => :idling end end end class VehicleObserver after_transition_failure do |transition| # log failure end after_transition_failure :on => :ignite do # log failure end end
See before_transition
for a description of the possible
configurations for defining callbacks. Note however that
you cannot define the state requirements in these callbacks. You may only
define event requirements.
# File lib/state_machine/integrations/data_mapper/observer.rb, line 174 def after_transition_failure(*args, &block) add_transition_callback(:after_failure, *args, &block) end
Creates a callback that will be invoked around a transition so long as the given requirements match the transition.
Examples¶ ↑
class Vehicle include DataMapper::Resource property :id, Serial property :state, :String state_machine :initial => :parked do event :ignite do transition :parked => :idling end end end class VehicleObserver include DataMapper::Observer observe Vehicle around_transition do |transition, block| # track start time block.call # track end time end end
See before_transition
for a description of the possible
configurations for defining callbacks.
# File lib/state_machine/integrations/data_mapper/observer.rb, line 139 def around_transition(*args, &block) add_transition_callback(:around_transition, *args, &block) end
Creates a callback that will be invoked before a transition is performed, so long as the given configuration options match the transition. Each part of the transition (event, to state, from state) must match in order for the callback to get invoked.
See StateMachine::Machine#before_transition for more information about the various configuration options available.
Examples¶ ↑
class Vehicle include DataMapper::Resource property :id, Serial property :state, :String state_machine :initial => :parked do event :ignite do transition :parked => :idling end end end class VehicleObserver include DataMapper::Observer observe Vehicle before :save do # log message end # Target all state machines before_transition :parked => :idling, :on => :ignite do # put on seatbelt end # Target a specific state machine before_transition :state, any => :idling do # put on seatbelt end # Target all state machines without requirements before_transition do |transition| # log message end end
Note that in each of the above
before_transition
callbacks, the callback is executed within
the context of the object (i.e. the Vehicle instance being transition).
This means that self
refers to the vehicle record within each
callback block.
# File lib/state_machine/integrations/data_mapper/observer.rb, line 93 def before_transition(*args, &block) add_transition_callback(:before_transition, *args, &block) end
Private Instance Methods
Adds the transition callback to a specific machine or all of the state machines for each observed class.
# File lib/state_machine/integrations/data_mapper/observer.rb, line 181 def add_transition_callback(type, *args, &block) if args.any? && !args.first.is_a?(Hash) # Specific machine(s) being targeted names = args args = args.last.is_a?(Hash) ? [args.pop] : [] else # Target all state machines names = nil end # Add the transition callback to each class being observed observing.each do |klass| state_machines = if names names.map {|name| klass.state_machines.fetch(name)} else klass.state_machines.values end state_machines.each {|machine| machine.send(type, *args, &block)} end if observing end