= Travis Build Status
{}[http://travis-ci.org/troessner/transitions]
= Synopsis
`transitions` 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 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.
== Automatic scope generation
`transitions` will automatically generate scopes for you if you are using ActiveRecord and tell it to do so via the `auto_scopes` 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.pick_line_items
=> [#]
== Using `on_transition`
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 `success`
In case you need to trigger a method call after a successful transition you can use `success`:
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 `default` 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.