An open API service indexing awesome lists of open source software.

https://github.com/danpersa/edge-state-machine


https://github.com/danpersa/edge-state-machine

Last synced: 2 months ago
JSON representation

Awesome Lists containing this project

README

        

= Edge State Machine

Edge State Machine is a complete state machine solution.
It offers support for ActiveRecord, Mongoid and MongoMapper for persistence.

{}[http://travis-ci.org/danpersa/edge-state-machine]

== 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:

* {Examples without Persistence}[https://github.com/danpersa/edge-state-machine/tree/master/spec/non_persistent/samples]
* {Examples with ActiveRecord}[https://github.com/danpersa/edge-state-machine/tree/master/spec/active_record/samples]
* {Examples with Mongoid}[https://github.com/danpersa/edge-state-machine/tree/master/spec/mongoid/samples]
* {Examples with Mongoid}[https://github.com/danpersa/edge-state-machine/tree/master/spec/mongoid/samples]
* {Examples with MongoMapper}[https://github.com/danpersa/edge-state-machine/tree/master/spec/mongo_mapper/samples]
== 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}[http://github.com/rails/rails/commit/db49c706b62e7ea2ab93f05399dbfddf5087ee0c].

And on Krzysiek Heród's gem, {Transitions}[https://github.com/netizer/transitions], which added Mongoid support.