README.rdoc in state_machine-0.9.4 vs README.rdoc in state_machine-0.10.0
- old
+ new
@@ -5,11 +5,11 @@
== Resources
API
-* http://rdoc.info/projects/pluginaweek/state_machine
+* http://rdoc.info/github/pluginaweek/state_machine/master/frames
Bugs
* http://pluginaweek.lighthouseapp.com/projects/13288-state_machine
@@ -35,18 +35,19 @@
Some brief, high-level features include:
* Defining state machines on any Ruby class
* Multiple state machines on a single class
* Namespaced state machines
-* before/after/around transition hooks with explicit transition requirements
-* Integration with ActiveModel, ActiveRecord, DataMapper, MongoMapper, and Sequel
+* before/after/around/failure transition hooks with explicit transition requirements
+* Integration with ActiveModel, ActiveRecord, DataMapper, Mongoid, MongoMapper, and Sequel
* State predicates
* State-driven instance / class behavior
* State values of any data type
* Dynamically-generated state values
* Event parallelization
* Attribute-based event transitions
+* Path analysis
* Inheritance
* Internationalization
* GraphViz visualization creator
Examples of the usage patterns for some of the above features are shown below.
@@ -62,10 +63,11 @@
* Transition callbacks
* Conditional transitions
* State-driven instance behavior
* Customized state values
* Parallel events
+* Path analysis
Class definition:
class Vehicle
attr_accessor :seatbelt_on, :time_used
@@ -77,10 +79,12 @@
after_transition :on => :repair, :do => :fix
after_transition any => :parked do |vehicle, transition|
vehicle.seatbelt_on = false
end
+ after_failure :on => :ignite, :do => :log_start_failure
+
around_transition do |vehicle, transition, block|
start = Time.now
block.call
vehicle.time_used += Time.now - start
end
@@ -167,10 +171,14 @@
end
def fix
# get the vehicle fixed by a mechanic
end
+
+ def log_start_failure
+ # log a failed attempt to start the vehicle
+ end
end
*Note* the comment made on the +initialize+ method in the class. In order for
state machine attributes to be properly initialized, <tt>super()</tt> must be called.
See StateMachine::MacroMethods for more information about this.
@@ -233,11 +241,22 @@
# Human-friendly names can be accessed for states/events
Vehicle.human_state_name(:first_gear) # => "first gear"
Vehicle.human_alarm_state_name(:active) # => "active"
Vehicle.human_state_event_name(:shift_down) # => "shift down"
- Vehicle.human_alarm_state_event_name(:enable_alarm) # => "enable alarm"
+ Vehicle.human_alarm_state_event_name(:enable) # => "enable"
+
+ # Available transition paths can be analyzed for an object
+ vehicle.state_paths # => [[#<StateMachine::Transition ...], [#<StateMachine::Transition ...], ...]
+ vehicle.state_paths.to_states # => [:parked, :idling, :first_gear, :stalled, :second_gear, :third_gear]
+ vehicle.state_paths.events # => [:park, :ignite, :shift_up, :idle, :crash, :repair, :shift_down]
+
+ # Find all paths that start and end on certain states
+ vehicle.state_paths(:from => :parked, :to => :first_gear) # => [[
+ # #<StateMachine::Transition attribute=:state event=:ignite from="parked" ...>,
+ # #<StateMachine::Transition attribute=:state event=:shift_up from="idling" ...>
+ # ]]
== Integrations
In addition to being able to define state machines on all Ruby classes, a set of
out-of-the-box integrations are available for some of the more popular Ruby
@@ -246,10 +265,11 @@
The integrations currently available include:
* ActiveModel classes
* ActiveRecord models
* DataMapper resources
+* Mongoid models
* MongoMapper models
* Sequel models
A brief overview of these integrations is described below.
@@ -303,10 +323,15 @@
# Generic transition callback *after* the transition is performed
def after_transition(vehicle, transition)
Audit.log(vehicle, transition)
end
+
+ # Generic callback after the transition fails to perform
+ def after_failure_to_transition(vehicle, transition)
+ Audit.error(vehicle, transition)
+ end
end
For more information about the various behaviors added for ActiveModel state
machines and how to build new integrations that use ActiveModel, see
StateMachine::Integrations::ActiveModel.
@@ -416,18 +441,61 @@
around_transition do |transition, block|
# mark start time
block.call
# mark stop time
end
+
+ # Generic callback after the transition fails to perform
+ after_transition_failure do |transition|
+ Audit.log(self, transition) # self is the record
+ end
end
*Note* that the DataMapper::Observer integration is optional and only available
when the dm-observer library is installed.
For more information about the various behaviors added for DataMapper state
machines, see StateMachine::Integrations::DataMapper.
+=== Mongoid
+
+The Mongoid integration adds support for automatically saving the record,
+basic scopes, validation errors and callbacks. For example,
+
+ class Vehicle
+ include Mongoid::Document
+
+ state_machine :initial => :parked do
+ before_transition :parked => any - :parked, :do => :put_on_seatbelt
+ after_transition any => :parked do |vehicle, transition|
+ vehicle.seatbelt = 'off' # self is the record
+ end
+ around_transition :benchmark
+
+ event :ignite do
+ transition :parked => :idling
+ end
+
+ state :first_gear, :second_gear do
+ validates_presence_of :seatbelt_on
+ end
+ end
+
+ def put_on_seatbelt
+ ...
+ end
+
+ def benchmark
+ ...
+ yield
+ ...
+ end
+ end
+
+For more information about the various behaviors added for Mongoid state
+machines, see StateMachine::Integrations::Mongoid.
+
=== MongoMapper
The MongoMapper integration adds support for automatically saving the record,
basic scopes, validation errors and callbacks. For example,
@@ -605,10 +673,11 @@
Test specific versions of integrations like so:
rake test INTEGRATION=active_model VERSION=3.0.0
rake test INTEGRATION=active_record VERSION=2.0.0
rake test INTEGRATION=data_mapper VERSION=0.9.4
+ rake test INTEGRATION=mongoid VERSION=2.0.0
rake test INTEGRATION=mongo_mapper VERSION=0.5.5
rake test INTEGRATION=sequel VERSION=2.8.0
== Caveats
@@ -625,9 +694,10 @@
If using specific integrations:
* ActiveModel[http://rubyonrails.org] integration: 3.0.0 or later
* ActiveRecord[http://rubyonrails.org] integration: 2.0.0 or later
* DataMapper[http://datamapper.org] integration: 0.9.4 or later
+* Mongoid[http://mongoid.org] integration: 2.0.0 or later
* MongoMapper[http://mongomapper.com] integration: 0.5.5 or later
* Sequel[http://sequel.rubyforge.org] integration: 2.8.0 or later
If graphing state machine: