Find file
Fetching contributors…
Cannot retrieve contributors at this time
81 lines (58 sloc) 3.15 KB

What is transitions?

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.

Quick Example

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
    event :out_of_stock do
      transitions :to => :out_of_stock, :from => [:available, :discontinued]
    event :available do
      transitions :to => :available, :from => [:out_of_stock], :guard => lambda { |product| product.in_stock > 0 }

Using with Rails

This goes into your Gemfile:

gem "transitions", :require => ["transitions", "active_record/transitions"]

… and this into your AR model:

include ActiveRecord::Transitions

A note about persistence

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.

Event execution flow

On an event, with our quick example product going from :available to :discontinued it looks like this:

  1. baby_ninja.discontinue!(:reason => :pirates)

  2. call :exit handler of :available state

  3. call :guard of :available to :discontinue transition within #discontinue event

  4. call #event_failed(:event) and abort unless 3. returned true

  5. call :on_transition(:reason => :pirates) of :available to :discontinue transition within #discontinue event

  6. call :enter handler of :discontinue

  7. call #event_fired(:available, :discontinue)

  8. call #write_state(machine, :discontinue)

  9. call #write_state_without_persistence(machine, :discontinue)

  10. call baby_ninja#:success handler method of #discontinue event

A note about events

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.

Documentation, Guides & Examples


Copyright © 2010 Jakub Kuźma. See LICENSE for details.