state_machine
https://github.com/pluginaweek/state_machine
Ruby
Adds support for creating state machines for attributes on any Ruby class
StateMachine::Machine#transition
Creates a new transition that determines what to change the current state
to when an event fires.
== Defining transitions
The options for a new transition uses the Hash syntax to map beginning
states to ending states. For example,
transition :parked => :idling, :idling => :first_gear, :on => :ignite
In this case, when the +ignite+ event is fired, this transition will cause
the state to be +idling+ if it's current state is +parked+ or +first_gear+
if it's current state is +idling+.
To help define these implicit transitions, a set of helpers are available
for slightly more complex matching:
* <tt>all</tt> - Matches every state in the machine
* <tt>all - [:parked, :idling, ...]</tt> - Matches every state except those specified
* <tt>any</tt> - An alias for +all+ (matches every state in the machine)
* <tt>same</tt> - Matches the same state being transitioned from
See StateMachine::MatcherHelpers for more information.
Examples:
transition all => nil, :on => :ignite # Transitions to nil regardless of the current state
transition all => :idling, :on => :ignite # Transitions to :idling regardless of the current state
transition all - [:idling, :first_gear] => :idling, :on => :ignite # Transitions every state but :idling and :first_gear to :idling
transition nil => :idling, :on => :ignite # Transitions to :idling from the nil state
transition :parked => :idling, :on => :ignite # Transitions to :idling if :parked
transition [:parked, :stalled] => :idling, :on => :ignite # Transitions to :idling if :parked or :stalled
transition :parked => same, :on => :park # Loops :parked back to :parked
transition [:parked, :stalled] => same, :on => [:park, :stall] # Loops either :parked or :stalled back to the same state on the park and stall events
transition all - :parked => same, :on => :noop # Loops every state but :parked back to the same state
# Transitions to :idling if :parked, :first_gear if :idling, or :second_gear if :first_gear
transition :parked => :idling, :idling => :first_gear, :first_gear => :second_gear, :on => :shift_up
== Verbose transitions
Transitions can also be defined use an explicit set of configuration
options:
* <tt>:from</tt> - A state or array of states that can be transitioned from.
If not specified, then the transition can occur for *any* state.
* <tt>:to</tt> - The state that's being transitioned to. If not specified,
then the transition will simply loop back (i.e. the state will not change).
* <tt>:except_from</tt> - A state or array of states that *cannot* be
transitioned from.
These options must be used when defining transitions within the context
of a state.
Examples:
transition :to => nil, :on => :park
transition :to => :idling, :on => :ignite
transition :except_from => [:idling, :first_gear], :to => :idling, :on => :ignite
transition :from => nil, :to => :idling, :on => :ignite
transition :from => [:parked, :stalled], :to => :idling, :on => :ignite
== Conditions
In addition to the state requirements for each transition, a condition
can also be defined to help determine whether that transition is
available. These options will work on both the normal and verbose syntax.
Configuration options:
* <tt>:if</tt> - A method, proc or string to call to determine if the
transition should occur (e.g. :if => :moving?, or :if => lambda {|vehicle| vehicle.speed > 60}).
The condition should return or evaluate to true or false.
* <tt>:unless</tt> - A method, proc or string to call to determine if the
transition should not occur (e.g. :unless => :stopped?, or :unless => lambda {|vehicle| vehicle.speed <= 60}).
The condition should return or evaluate to true or false.
Examples:
transition :parked => :idling, :on => :ignite, :if => :moving?
transition :parked => :idling, :on => :ignite, :unless => :stopped?
transition :idling => :first_gear, :first_gear => :second_gear, :on => :shift_up, :if => :seatbelt_on?
transition :from => :parked, :to => :idling, :on => ignite, :if => :moving?
transition :from => :parked, :to => :idling, :on => ignite, :unless => :stopped?
== Order of operations
Transitions are evaluated in the order in which they're defined. As a
result, if more than one transition applies to a given object, then the
first transition that matches will be performed.Edit
git clone [email protected]:pluginaweek/state_machine.git
cd state_machine
open lib/state_machine/machine.rb
Contribute
# Make a new branchgit checkout -b -your-name--update-docs-StateMachine--Machine-transition-for-pr
# Commit to gitgit add lib/state_machine/machine.rbgit commit -m "better docs for StateMachine::Machine#transition"
# Open pull requestgem install hub # on a mac you can `brew install hub`
hub fork
git push <your name> -your-name--update-docs-StateMachine--Machine-transition-for-pr
hub pull-request
# Celebrate!