Ruby state machine

From wikinotes

Simple creation of state machines.

Documentation

github https://github.com/pluginaweek/state_machine
api docs https://rdoc.info/github/pluginaweek/state_machine/master/frames

Extensions

ruby state machines - audit trail

Example

  • events trigger state changes
  • states are the various states that can be assigned
  • Optionally, you can trigger code whenever a particular state is activated
  • Optionally, you can skip the state-machine, and assign attributes text values
class Vehicle

  # :state is the attribute storing the state
  state_machine :state, :initial => :parked do

    # event methods trigger a state change
    # 
    #   vehicle.park
    #   vehicle.can_park?
    #   vehicle.parked?
    event :park do
      transition [:idling, :first_gear] => :parked
    end
  
    event :shift_up do
      transition :parkged => :idling,
                 :idling => :first_gear,
                 :first_gear => :second_gear,
                 :second_gear => :third_gear
      end
    end

    # symbol methods are fired when a state 
    # is activated
    def :parked do
      def speed
        0
      end
    end
  end

end
Vehicle.state_machine[:state].states.map(&:name)  # list all states
vehicle = Vehicle.new
vehicle.shift_up
vehicle.shift_up
vehicle.park

Syntax

Assignment

vehicle = Vehicle.new
vehicle.park                   # run event 'park'
vehicle.state = "parked"       # skip state machine, assign directly

Events

vehicle.state
vehicle.state_name
vehicle.parked?                # each state has boolean check
vehicle.can_park?              # can use state?
vehicle.fire_{statemachine_name}_event(:park)  # execute variable event

implement handlers for when events change state using symbol-methods, or overrides with super.

class Foo
  state_machine :status do
    event :complete do
      transition :started => :finished
    end
  end

  def :complete(param)
    puts param
  end

  # OR

  def complete(param)
    puts param
    super
  end
end

Transitions/Introspection

# for all states
Vehicle.state_machine[:state].states.map(&:name)  # list all states
# from current state
vehicle.{state_name}_events           # [:ignite, ..]                         (events that can run from current state)
vehicle.{state_name}_paths            # [Transition, Transition, ...]         (transitions from current state)
vehicle.{state_name}_paths.to_states  # [:parked, :idling, :first_gear, ...]  (states available from current state)
vehicle.{state_name}_paths.events     # [:park, :ignite, :shift_up, ...]      (events available from current state)