state_pattern

A Ruby state pattern implementation.

require 'rubygems'
require 'state_pattern'

class On < StatePattern::State
  def press
    transition_to(Off)
    "#{stateable.button_name} is off"
  end
end

class Off < StatePattern::State
  def press
    transition_to(On)
    "#{stateable.button_name} is on"
  end
end

class Button
  include StatePattern
  add_states On, Off
  set_initial_state Off
  valid_transitions [On, :press] => Off, [Off, :press] => On

  #this method can be removed as it will be mapped automatically anyways
  #but it is good to leave the option to do the delegation yourself in case you want more freedom
  def press
    delegate_to_event(:press)
  end

  def button_name
    "Light button"
  end
end

button = Button.new
puts button.press # => "Light button is on"
puts button.press # => "Light button is off"
puts button.press # => "Light button is on"

Validations

One of the few drawbacks the state pattern has is that it can get difficult to see the global picture of your state machine when dealing with complex cases. To deal with this problem you have the option of using the valid_transitions statement to “draw” your state diagram in code. Whenever a state transition is performed, the valid_transitions hash is checked and if the transition is not valid a StatePattern::InvalidTransitionException is thrown.

Examples:

The most basic notation

valid_transitions On => Off, Off => On

With more than one target state

valid_transitions Up => [Middle, Down], Down => Middle, Middle => Up

Using event names to gain more detail

valid_transitions [Up, :switch] => [Middle, Down], [Down, :switch] => Middle, [Middle, :switch] => Up

Copyright © 2009 Daniel Cadenas. See LICENSE for details.