2012-10-19 02:23:23 -04:00
|
|
|
# AASM - Ruby state machines [![Build Status](https://secure.travis-ci.org/aasm/aasm.png)](http://travis-ci.org/aasm/aasm) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/aasm/aasm)
|
2008-02-22 18:23:19 -05:00
|
|
|
|
2008-03-04 18:59:58 -05:00
|
|
|
This package contains AASM, a library for adding finite state machines to Ruby classes.
|
2008-02-22 18:23:19 -05:00
|
|
|
|
2012-01-16 11:11:51 -05:00
|
|
|
AASM started as the acts_as_state_machine plugin but has evolved into a more generic library
|
|
|
|
that no longer targets only ActiveRecord models. It currently provides adapters for
|
|
|
|
[ActiveRecord](http://api.rubyonrails.org/classes/ActiveRecord/Base.html) and
|
|
|
|
[Mongoid](http://mongoid.org/).
|
2008-02-22 18:23:19 -05:00
|
|
|
|
2011-08-31 15:50:59 -04:00
|
|
|
## Features ##
|
2008-02-22 18:23:19 -05:00
|
|
|
|
2008-05-29 10:24:01 -04:00
|
|
|
* States
|
|
|
|
* Machines
|
|
|
|
* Events
|
|
|
|
* Transitions
|
2008-02-22 18:23:19 -05:00
|
|
|
|
2011-08-31 15:50:59 -04:00
|
|
|
## New Callbacks ##
|
2008-02-22 18:23:19 -05:00
|
|
|
|
2009-02-26 16:18:22 -05:00
|
|
|
The callback chain & order on a successful event looks like:
|
|
|
|
|
2011-08-31 15:56:09 -04:00
|
|
|
oldstate:exit*
|
|
|
|
event:before
|
|
|
|
__find transition, if possible__
|
|
|
|
transition:on_transition*
|
|
|
|
oldstate:before_exit
|
|
|
|
newstate:before_enter
|
|
|
|
newstate:enter*
|
|
|
|
__update state__
|
|
|
|
event:success*
|
|
|
|
oldstate:after_exit
|
|
|
|
newstate:after_enter
|
|
|
|
event:after
|
|
|
|
obj:aasm_event_fired*
|
|
|
|
|
|
|
|
(*) marks old callbacks
|
2008-03-04 18:59:58 -05:00
|
|
|
|
|
|
|
|
2011-08-31 15:50:59 -04:00
|
|
|
## Installation ##
|
2008-03-04 18:59:58 -05:00
|
|
|
|
2011-10-23 15:21:51 -04:00
|
|
|
### Manually from RubyGems.org ###
|
2009-10-23 16:33:01 -04:00
|
|
|
|
2011-08-31 15:50:59 -04:00
|
|
|
```sh
|
|
|
|
% gem install aasm
|
|
|
|
```
|
2008-04-29 20:51:12 -04:00
|
|
|
|
2011-10-23 15:21:51 -04:00
|
|
|
### Or if you are using Bundler ###
|
|
|
|
|
|
|
|
```ruby
|
|
|
|
# Gemfile
|
|
|
|
gem 'aasm'
|
|
|
|
```
|
|
|
|
|
2011-08-31 15:50:59 -04:00
|
|
|
### Building your own gems ###
|
2008-03-04 18:59:58 -05:00
|
|
|
|
2011-08-31 15:50:59 -04:00
|
|
|
```sh
|
|
|
|
% rake build
|
2011-08-31 17:56:57 -04:00
|
|
|
% sudo gem install pkg/aasm-x.y.z.gem
|
2011-08-31 15:50:59 -04:00
|
|
|
```
|
2008-03-04 18:59:58 -05:00
|
|
|
|
2012-01-16 11:27:15 -05:00
|
|
|
## Examples ##
|
|
|
|
|
|
|
|
### Simple Example ###
|
2008-03-04 18:59:58 -05:00
|
|
|
|
|
|
|
Here's a quick example highlighting some of the features.
|
|
|
|
|
2011-08-31 15:50:59 -04:00
|
|
|
```ruby
|
2011-11-26 15:11:57 -05:00
|
|
|
class Conversation
|
|
|
|
include AASM
|
2008-03-04 18:59:58 -05:00
|
|
|
|
2011-11-26 15:11:57 -05:00
|
|
|
aasm :column => :current_state do # defaults to aasm_state
|
|
|
|
state :unread, :initial => true
|
|
|
|
state :read
|
|
|
|
state :closed
|
2008-03-04 18:59:58 -05:00
|
|
|
|
2011-11-26 15:11:57 -05:00
|
|
|
event :view do
|
2008-12-29 10:05:07 -05:00
|
|
|
transitions :to => :read, :from => [:unread]
|
2008-03-04 18:59:58 -05:00
|
|
|
end
|
|
|
|
|
2011-11-26 15:11:57 -05:00
|
|
|
event :close do
|
2008-12-29 10:05:07 -05:00
|
|
|
transitions :to => :closed, :from => [:read, :unread]
|
2008-03-04 18:59:58 -05:00
|
|
|
end
|
|
|
|
end
|
2011-11-26 15:11:57 -05:00
|
|
|
|
|
|
|
end
|
2011-08-31 15:50:59 -04:00
|
|
|
```
|
2008-03-04 18:59:58 -05:00
|
|
|
|
2012-01-16 11:27:15 -05:00
|
|
|
### A Slightly More Complex Example ###
|
2009-02-26 12:06:43 -05:00
|
|
|
|
|
|
|
This example uses a few of the more complex features available.
|
|
|
|
|
2011-08-31 15:50:59 -04:00
|
|
|
```ruby
|
2009-02-26 12:06:43 -05:00
|
|
|
class Relationship
|
|
|
|
include AASM
|
2010-01-17 01:12:18 -05:00
|
|
|
|
2012-02-05 07:32:32 -05:00
|
|
|
aasm :column => :status do
|
2011-11-26 15:11:57 -05:00
|
|
|
state :dating, :enter => :make_happy, :exit => :make_depressed
|
|
|
|
state :intimate, :enter => :make_very_happy, :exit => :never_speak_again
|
|
|
|
state :married, :enter => :give_up_intimacy, :exit => :buy_exotic_car_and_wear_a_combover
|
|
|
|
|
|
|
|
event :get_intimate do
|
|
|
|
transitions :to => :intimate, :from => [:dating], :guard => :drunk?
|
|
|
|
end
|
|
|
|
|
2012-10-19 02:29:05 -04:00
|
|
|
# Will allow transitioning from any state if guard allows it
|
2011-11-26 15:11:57 -05:00
|
|
|
event :get_married do
|
2012-10-19 02:29:05 -04:00
|
|
|
transitions :to => :married, :guard => :willing_to_give_up_manhood?
|
2011-11-26 15:11:57 -05:00
|
|
|
end
|
2009-02-26 12:06:43 -05:00
|
|
|
end
|
2011-11-26 15:11:57 -05:00
|
|
|
aasm_initial_state Proc.new { |relationship| relationship.strictly_for_fun? ? :intimate : :dating }
|
|
|
|
|
2009-02-26 12:06:43 -05:00
|
|
|
def strictly_for_fun?; end
|
|
|
|
def drunk?; end
|
|
|
|
def willing_to_give_up_manhood?; end
|
|
|
|
def make_happy; end
|
|
|
|
def make_depressed; end
|
|
|
|
def make_very_happy; end
|
|
|
|
def never_speak_again; end
|
|
|
|
def give_up_intimacy; end
|
|
|
|
def buy_exotic_car_and_wear_a_combover; end
|
|
|
|
end
|
2011-08-31 15:50:59 -04:00
|
|
|
```
|
2009-02-26 12:06:43 -05:00
|
|
|
|
2012-01-16 11:27:15 -05:00
|
|
|
### Callbacks around events ###
|
2011-09-04 11:59:55 -04:00
|
|
|
```ruby
|
|
|
|
class Relationship
|
|
|
|
include AASM
|
|
|
|
|
2011-11-26 15:11:57 -05:00
|
|
|
aasm do
|
|
|
|
state :dating
|
|
|
|
state :married
|
2011-09-04 11:59:55 -04:00
|
|
|
|
2011-11-26 15:11:57 -05:00
|
|
|
event :get_married,
|
|
|
|
:before => :make_vows,
|
|
|
|
:after => :eat_wedding_cake do
|
|
|
|
transitions :to => :married, :from => [:dating]
|
|
|
|
end
|
2011-11-26 15:23:36 -05:00
|
|
|
end
|
2011-09-04 11:59:55 -04:00
|
|
|
end
|
|
|
|
```
|
|
|
|
|
2012-01-16 11:27:15 -05:00
|
|
|
### Persistence example ###
|
|
|
|
```ruby
|
|
|
|
class InvalidPersistor < ActiveRecord::Base
|
|
|
|
include AASM
|
|
|
|
aasm :column => :status, :skip_validation_on_save => true do
|
|
|
|
state :sleeping, :initial => true
|
|
|
|
state :running
|
|
|
|
event :run do
|
|
|
|
transitions :to => :running, :from => :sleeping
|
|
|
|
end
|
|
|
|
event :sleep do
|
|
|
|
transitions :to => :sleeping, :from => :running
|
|
|
|
end
|
|
|
|
end
|
|
|
|
validates_presence_of :name
|
|
|
|
end
|
|
|
|
```
|
|
|
|
This model can change AASM states which are stored into the database, even if the model itself is invalid!
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-11-25 18:11:30 -05:00
|
|
|
## Changelog ##
|
2011-09-04 11:59:55 -04:00
|
|
|
|
2012-07-01 05:35:20 -04:00
|
|
|
Look at the [CHANGELOG](https://github.com/aasm/aasm/blob/master/CHANGELOG.md) for details.
|
2011-11-25 18:11:30 -05:00
|
|
|
|
|
|
|
|
|
|
|
## Authors ##
|
|
|
|
|
|
|
|
* [Scott Barron](https://github.com/rubyist)
|
|
|
|
* [Travis Tilley](https://github.com/ttilley)
|
2011-11-25 18:13:19 -05:00
|
|
|
* [Thorsten Böttger](http://github.com/alto)
|
2008-03-04 18:59:58 -05:00
|
|
|
|
|
|
|
|
2011-08-31 15:50:59 -04:00
|
|
|
## Warranty ##
|
2008-03-04 18:59:58 -05:00
|
|
|
|
|
|
|
This software is provided "as is" and without any express or
|
|
|
|
implied warranties, including, without limitation, the implied
|
|
|
|
warranties of merchantibility and fitness for a particular
|
|
|
|
purpose.
|
2011-11-25 18:11:30 -05:00
|
|
|
|
|
|
|
## License ##
|
|
|
|
|
2012-01-16 11:24:58 -05:00
|
|
|
Copyright (c) 2006-2012 Scott Barron
|
2011-11-25 18:11:30 -05:00
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
|
|
a copy of this software and associated documentation files (the
|
|
|
|
"Software"), to deal in the Software without restriction, including
|
|
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be
|
|
|
|
included in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
|
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
|
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|