README.rdoc in state_machine-0.4.1 vs README.rdoc in state_machine-0.4.2
- old
+ new
@@ -34,30 +34,36 @@
state machine is :)
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 transition hooks with explicit transition requirements
* ActiveRecord integration
* DataMapper integration
* Sequel integration
* States of any data type
* State predicates
+* State-driven behavior
* GraphViz visualization creator
Examples of the usage patterns for some of the above features are shown below.
You can find more detailed documentation in the actual API.
== Usage
=== Example
-Below is an example of many of the features offered by this plugin, including
+Below is an example of many of the features offered by this plugin, including:
* Initial states
+* Namespaced states
* Transition callbacks
* Conditional transitions
+* State-driven behavior
+Class definition:
+
class Vehicle
attr_accessor :seatbelt_on
state_machine :state, :initial => 'parked' do
before_transition :from => %w(parked idling), :do => :put_on_seatbelt
@@ -96,14 +102,43 @@
end
event :repair do
transition :to => 'parked', :from => 'stalled', :if => :auto_shop_busy?
end
+
+ state 'parked' do
+ def speed
+ 0
+ end
+ end
+
+ state 'idling', 'first_gear' do
+ def speed
+ 10
+ end
+ end
+
+ state 'second_gear' do
+ def speed
+ 20
+ end
+ end
end
+ state_machine :hood_state, :initial => 'closed', :namespace => 'hood' do
+ event :open do
+ transition :to => 'opened', :from => 'closed'
+ end
+
+ event :close do
+ transition :to => 'closed', :from => 'opened'
+ end
+ end
+
def initialize
@seatbelt_on = false
+ super() # NOTE: This *must* be called, otherwise states won't get initialized
end
def put_on_seatbelt
@seatbelt_on = true
end
@@ -126,24 +161,43 @@
vehicle = Vehicle.new # => #<Vehicle:0xb7cf4eac @state="parked", @seatbelt_on=false>
vehicle.parked? # => true
vehicle.can_ignite? # => true
vehicle.next_ignite_transition # => #<StateMachine::Transition:0xb7c34cec ...>
+ vehicle.speed # => 0
+
vehicle.ignite # => true
vehicle.parked? # => false
vehicle.idling? # => true
+ vehicle.speed # => 10
vehicle # => #<Vehicle:0xb7cf4eac @state="idling", @seatbelt_on=true>
+
vehicle.shift_up # => true
+ vehicle.speed # => 10
vehicle # => #<Vehicle:0xb7cf4eac @state="first_gear", @seatbelt_on=true>
+
vehicle.shift_up # => true
+ vehicle.speed # => 20
vehicle # => #<Vehicle:0xb7cf4eac @state="second_gear", @seatbelt_on=true>
# The bang (!) operator can raise exceptions if the event fails
vehicle.park! # => StateMachine::InvalidTransition: Cannot transition via :park from "second_gear"
# Generic state predicates can raise exceptions if the value does not exist
vehicle.state?('parked') # => true
vehicle.state?('invalid') # => ArgumentError: "parked" is not a known state value
+
+ # Namespaced machines have uniquely-generated methods
+ vehicle.can_open_hood? # => true
+ vehicle.open_hood # => true
+ vehicle.can_close_hood? # => true
+
+ vehicle.hood_opened? # => true
+ vehicle.hood_closed? # => false
+
+*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.
== 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