= Travis Build Status 

{<img src="https://secure.travis-ci.org/troessner/transitions.png"/>}[http://travis-ci.org/troessner/transitions]

= Synopsis

<tt>transitions</tt> is a ruby state machine implementation.

= Installation

== Rails

This goes into your Gemfile:

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

… and this into your ORM model:

 include ActiveModel::Transitions

== Standalone

 gem install transitions

= Using transitions

 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

= Features

== Events

When you declare an event, say <tt>discontinue</tt>, two methods are declared for
you: <tt>discontinue</tt> and <tt>discontinue!</tt>. Both events will modify the <tt>state</tt> attribute on successful transition,
but only the bang(!)-version will call <tt>save!</tt>.

== Automatic scope generation

<tt>transitions</tt> will automatically generate scopes for you if you are using ActiveRecord and tell it to do so via the <tt>auto_scopes</tt> option:

Given a model like this:

  class Order < ActiveRecord::Base
    include ActiveModel::Transitions
    state_machine :auto_scopes => true do
      state :pick_line_items
      state :picking_line_items
    end
  end

you can use this feature a la:

  >> Order.pick_line_items
  => []
  >> Order.create!
  => #<Order id: 3, state: "pick_line_items", description: nil, created_at: "2011-08-23 15:48:46", updated_at: "2011-08-23 15:48:46">
  >> Order.pick_line_items
  => [#<Order id: 3, state: "pick_line_items", description: nil, created_at: "2011-08-23 15:48:46", updated_at: "2011-08-23 15:48:46">]

== Using <tt>on_transition</tt>

Each event definition takes an optional "on_transition" argument, which allows you to execute methods on transition.
You can pass in a Symbol, a String, a Proc or an Array containing method names as Symbol or String like this:

  event :discontinue do
    transitions :to => :discontinued, :from => [:available, :out_of_stock], :on_transition => [:do_discontinue, :notify_clerk]
  end

== Using <tt>success</tt>

In case you need to trigger a method call after a successful transition you can use <tt>success</tt>:

  event :discontinue, :success => :notfiy_admin do
    transitions :to => :discontinued, :from => [:available, :out_of_stock]
  end

In addition to just specify the method name on the record as a symbol you can pass a lambda to
perfom some more complex success callbacks:

  event :discontinue, :success => lambda { |order) AdminNotifier.notify_about_discontinued_order(order) } do
    transitions :to => :discontinued, :from => [:available, :out_of_stock]
  end

== Timestamps

If you'd like to note the time of a state change, Transitions comes with timestamps free!
To activate them, simply pass the :timestamp option to the event definition with a value of either true or
the name of the timestamp column.
*NOTE - This should be either true, a String or a Symbol*

  # This will look for an attribute called exploded_at or exploded_on (in that order)
  # If present, it will be updated
  event :explode, :timestamp => true do
    transitions :from => :complete, :to => :exploded
  end

  # This will look for an attribute named repaired_on to update upon save
  event :rebuild, :timestamp => :repaired_on do
    transitions :from => :exploded, :to => :rebuilt
  end

== Listing all the available states

You can easily get a listing of all available states:

  Order.available_states # Uses the <tt>default</tt> state machine
  # => [:pick_line_items, :picking_line_items]

In case you have multiple state machines you can also pass the state machine name:

  Order.available_states(:your_machine)

= Documentation, Guides & Examples

- {Online API Documentation}[http://rdoc.info/github/troessner/transitions/master/Transitions]
- Krzysiek Heród (aka {Netizer}[http://github.com/netizer]) wrote a nice
  {blog post}[http://dev.netizer.pl/transitions-state-machine-for-rails-3.html]
  about using Transitions in ActiveRecord.

= Copyright

Copyright (c) 2010 Jakub Kuźma, Timo Rößner. See LICENSE for details.