transitions is a ruby state machine implementation based on Rick Olson’s ActiveModel::StateMachine. It was extracted from ActiveModel and turned into a gem when it got the axe in commit db49c706b.
transitions is currently being maintained by Jakub Kuźma.
require 'transitions' class Product include Transitions state_machine do state :available # first one is initial state state :out_of_stock, :exit => :exit_out_of_stock state :discontinued, :enter => lambda { |product| product.cancel_orders } event :discontinued do transitions :to => :discontinued, :from => [:available, :out_of_stock], :on_transition => :do_discontinue end event :out_of_stock do transitions :to => :out_of_stock, :from => [:available, :discontinued] end event :available do transitions :to => :available, :from => [:out_of_stock], :guard => lambda { |product| product.in_stock > 0 } end end end
This goes into your Gemfile:
gem "transitions", :require => ["transitions", "active_record/transitions"]
… and this into your AR model:
include ActiveRecord::Transitions
The property used to persist the models’ state is named state (really!), which should be a string column wide enough to fit your longest state name. It should also be mentioned that #save! is called after every successful event.
On an event, with our quick example product going from :available to :discontinued it looks like this:
-
baby_ninja.discontinue!(:reason => :pirates) -
call
:exithandler of:availablestate -
call
:guardof:available to :discontinuetransition within#discontinueevent -
call
#event_failed(:event)and abort unless3.returnedtrue -
call
:on_transition(:reason => :pirates)of:available to :discontinuetransition within#discontinueevent -
call
:enterhandler of:discontinue -
call
#event_fired(:available, :discontinue) -
call
#write_state(machine, :discontinue) -
call
#write_state_without_persistence(machine, :discontinue) -
call
baby_ninja#:successhandler method of#discontinueevent
When you declare an event discontinue, two methods are declared for you: discontinue and discontinue!. Both events will call write_state_without_persistence on successful transition, but only the bang(!)-version will call write_state.
Copyright © 2010 Jakub Kuźma. See LICENSE for details.