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 or event 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]

results matching ""

    No results matching ""