Helpers
MatcherHelpers
- Provides a set of helper methods for generating matchers that can be used to easily execute blocks for a group of states/events/transitions/etc.
- Blocks using these matchers can be defined at any point in the state machine and will always get applied to the proper object
Matchers cannot be used for
state
orevent
configurations
all
Represents a state/event that matches all known states in a machine.
any
An alias for all
all - [:parked, :idling, ...]
Matches every state/event except those specified
Examples - transition
class Vehicle
state_machine do
before_transition any => :parked, :do => lambda {...}
before_transition all - :parked => all - :idling, :do => lambda {}
event :park
transition all => :parked
end
event :crash
transition all - :parked => :stalled
end
end
end
In the above example, all
will match the following states since they are known:
parked
stalled
idling
Examples - Callbacks
# Matches from parked to idling or first_gear
before_transition :parked => [:idling, :first_gear], :do => ...
# Matches from every state except parked and idling to idling
before_transition all - [:parked, :idling] => :idling, :do => ...
# Matches all states to parked
before_transition all => :parked, :do => ...
# Matches every loopback
before_transition any => same, :do => ...
Examples - state
state_machine :initial => :parked do
...
state all - [:parked, :idling, :stalled] do
validates_presence_of :speed
def speed
gear * 10
end
end
end
Examples - event
For example:
state_machine :initial => :parked do
...
event all - [:crash] do
transition :stalled => :parked
end
end
same
Represents a state that matches the original from
state. This is useful for defining transitions
which are loopbacks.
Examples
class Vehicle
state_machine do
event :ignite
transition [:idling, :first_gear] => same # Allow ignite while still idling on first_gear
end
end
end
same
will match whichever the from state is. In the case of the ignite
event, it is essential
the same as the following:
transition :parked => :parked, :first_gear => :first_gear
paths_for
Helper
Generates a list of the possible transition sequences that can be run on the given object. These paths can reveal all of the possible states and events that can be encountered in the object's state machine based on the object's current state.
Configurations
from
The initial state to start all paths from. By default, this is the object's current state.
to
The target state to end all paths on. By default, paths will end when they loop back to the first transition on the path.
deep
Whether to allow the target state to be crossed more than once in a path. By default, paths will immediately stop when the target state (if specified) is reached. If this is enabled, then paths can continue even after reaching the target state; they will stop when reaching the target state a second time.
The object is never modified when the list of paths is generated.
Examples
class Vehicle
state_machine :initial => :parked do
event :ignite do
transition :parked => :idling
end
event :shift_up do
transition :idling => :first_gear, :first_gear => :second_gear
end
event :shift_down do
transition :second_gear => :first_gear, :first_gear => :idling
end
end
end
vehicle = Vehicle.new # => #<Vehicle:0xb7c27024 @state="parked">
vehicle.state # => "parked"
vehicle.state_paths
# => [
# [#<StateMachines::Transition attribute=:state event=:ignite
# from="parked" from_name=:parked to="idling" to_name=:idling>,
# #<StateMachines::Transition attribute=:state event=:shift_up
# from="idling" from_name=:idling to="first_gear" to_name=:first_gear>,
# #<StateMachines::Transition attribute=:state event=:shift_up from="first_gear"
# from_name=:first_gear to="second_gear" to_name=:second_gear>,
# #<StateMachines::Transition attribute=:state event=:shift_down
# from="second_gear" from_name=:second_gear to="first_gear" to_name=:first_gear>,
# #<StateMachines::Transition attribute=:state event=:shift_down
# from="first_gear" from_name=:first_gear to="idling" to_name=:idling>],
#
# [#<StateMachines::Transition attribute=:state event=:ignite from="parked" from_name=:parked
# to="idling" to_name=:idling>,
# #<StateMachines::Transition attribute=:state event=:shift_up from="idling" from_name=:idling
# to="first_gear" to_name=:first_gear>,
# #<StateMachines::Transition attribute=:state event=:shift_down from="first_gear"
# from_name=:first_gear to="idling" to_name=:idling>]
# ]
vehicle.state_paths(:from => :parked, :to => :second_gear)
# => [
# [#<StateMachines::Transition attribute=:state event=:ignite
# from="parked" from_name=:parked to="idling" to_name=:idling>,
# #<StateMachines::Transition attribute=:state event=:shift_up
# from="idling" from_name=:idling to="first_gear" to_name=:first_gear>,
# #<StateMachines::Transition attribute=:state event=:shift_up
# from="first_gear" from_name=:first_gear to="second_gear" to_name=:second_gear>]
# ]
In addition to getting the possible paths that can be accessed, you can also get summary information about the states / events that can be accessed at some point along one of the paths. For example:
# Get the list of states that can be accessed from the current state
vehicle.state_paths.to_states # => [:idling, :first_gear, :second_gear]
# Get the list of events that can be accessed from the current state
vehicle.state_paths.events # => [:ignite, :shift_up, :shift_down]