Edge State Machine¶ ↑
Edge State Machine is a complete state machine solution. It offers support for ActiveRecord, Mongoid and MongoMapper for persistence.
<img src=“https://secure.travis-ci.org/danpersa/edge-state-machine.png”/>
Supported Features¶ ↑
-
Multiple state machines per class each of them acting independently
-
Find errors in state machine definitions as early as possible
-
Transition guards
-
Multiple actions executed on transitions
-
Multiple actions executed on entering and exiting a state
-
No other dependencies for non-persistent state machines
-
Minimal dependencies for persistent ones
Installation¶ ↑
If you’re using Rails + ActiveRecord + Bundler
# in your Gemfile gem "edge-state-machine", :require => ["edge-state-machine", "active_record/edge-state-machine"] # in your AR models that will use the state machine include ::EdgeStateMachine include ActiveRecord::EdgeStateMachine state_machine do state :available # first one is initial state state :out_of_stock state :discontinue event :discontinue do transitions :to => :discontinue, :from => [:available, :out_of_stock], :on_transition => :do_discontinue end event :out_of_stock do transitions :to => :out_of_stock, :from => [:available, :discontinue] end event :available do transitions :to => :available, :from => [:out_of_stock], :on_transition => :send_alerts end end
If you’re using Rails + Mongoid + Bundler
# in your Gemfile gem "edge-state-machine", :require => ["edge-state-machine", "mongoid/edge-state-machine"] # in your AR models that will use the state machine include ::EdgeStateMachine include Mongoid::EdgeStateMachine state_machine do state :available # first one is initial state state :out_of_stock state :discontinue event :discontinue do transitions :to => :discontinue, :from => [:available, :out_of_stock], :on_transition => :do_discontinue end event :out_of_stock do transitions :to => :out_of_stock, :from => [:available, :discontinue] end event :available do transitions :to => :available, :from => [:out_of_stock], :on_transition => :send_alerts end end
If you’re using Rails + MongoMapper + Bundler
# in your Gemfile gem "edge-state-machine", :require => ["edge-state-machine", "mongo_mapper/edge-state-machine"] # in your models that will use the state machine include ::EdgeStateMachine include MongoMapper::EdgeStateMachine state_machine do state :available # first one is initial state state :out_of_stock state :discontinue event :discontinue do transitions :to => :discontinue, :from => [:available, :out_of_stock], :on_transition => :do_discontinue end event :out_of_stock do transitions :to => :out_of_stock, :from => [:available, :discontinue] end event :available do transitions :to => :available, :from => [:out_of_stock], :on_transition => :send_alerts end end
State Machine Examples¶ ↑
Microwave State Machine¶ ↑
class Microwave state_machine :microwave do # name should be optional, if the name is not present, it should have a default name # we give state machines names, so we can pun many machines inside a class initial_state :unplugged # initial state should be optional, if the initial state is not present, the initial state will be the first defined state state :unplugged state :plugged state :door_opened do enter :light_on # enter should be executed on entering the state exit :light_off # exit method should be executed on exiting the state end state :door_closed state :started_in_grill_mode do enter lambda { |t| p "Entering hate" } # should have support for Procs exit :grill_off end state :started do enter :microwaves_on exit :microwaves_off end event :plug_in do transition :from => :unplugged, :to => :plugged end event :open_door do transition :from => :plugged, :to => :door_opened end event :close_door do transition :from => :door_opened, :to => :door_closed, :on_transition => :put_food_in_the_microwave # we can put many actions in an Array for the on_transition parameter end event :start do transition :from => :door_closed, :to => [:started, :started_in_grill_mode], :on_transition => :start_spinning_the_food, :guard => :grill_button_pressed? # the method grill_button_pressed? should choose the next state end event :stop do transition :from => [:started, :started_in_grill_mode], :to => :door_closed end end end
Dice State Machine¶ ↑
class Dice state_machine do state :one state :two state :three state :four state :five state :six event :roll do transition :from => [:one, :two, :three, :four, :five, :six], :to => [:one, :two, :three, :four, :five, :six], :guard => :roll_result, :on_transition => :display_dice_rolling_animation end end def roll_result # return one of the states end def display_dice_rolling_animation # draw the new position of the dice end end class User state_machine do state :pending # first one is initial state state :active state :blocked # the user in this state can't sign in event :activate do transition :from => [:pending], :to => :active, :on_transition => :do_activate end event :block do transition :from => [:pending, :active], :to => :blocked end end end
Other Examples¶ ↑
For other (more complex) examples, please check the following links:
Notes¶ ↑
For classes with multiple state machines, the state names, machine names must be unique per class.
The same thing with the event names.
Credits¶ ↑
The gem is based on Rick Olson’s code of ActiveModel::StateMachine, axed from ActiveModel in this commit.
And on Krzysiek Heród’s gem, Transitions, which added Mongoid support.