Skip to content

Commit

Permalink
Fixing up state machine docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mikel committed Jan 18, 2010
1 parent 6e45bf5 commit 71328a9
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 88 deletions.
13 changes: 13 additions & 0 deletions activemodel/README
Expand Up @@ -154,3 +154,16 @@ functionality from the following modules:

{Learn more}[link:classes/ActiveModel/Serialization.html]


* Turning your object into a finite State Machine

ActiveModel::StateMachine provides a clean way to include all the methods
you need to transform your object into a finite State Machine...

light = TrafficLight.new
light.current_state #=> :red
light.change_color! #=> true
light.current_state #=> :green

{Learn more}[link:classes/ActiveModel/StateMachine.html]

216 changes: 128 additions & 88 deletions activemodel/lib/active_model/state_machine.rb
@@ -1,112 +1,152 @@
module ActiveModel
# ==== Examples
#
# class TrafficLight

# ActiveModel::StateMachine provides methods that turn your object into a
# finite state machine, able to move from one state to another.
#
# A minimal implementation could be:
#
# class EmailMessage
# include ActiveModel::StateMachine
#
#
# state_machine do
# state :red
# state :green
# state :yellow
# state :blink
#
# event :change_color do
# transitions :to => :red, :from => [:yellow],
# :on_transition => :catch_runners
# transitions :to => :green, :from => [:red]
# transitions :to => :yellow, :from => [:green]
# end
#
# event :defect do
# transitions :to => :blink, :from => [:yellow, :red, :green]
# end
#
# event :repair do
# transitions :to => :red, :from => [:blink]
# end
# state :unread
# state :read
# end
#
# def catch_runners
# puts "That'll be $250."
#
# event :open_email do
# transitions :to => :read, :from => :unread
# end
# end
#
# light = TrafficLight.new
# light.current_state # => :red
# light.change_color # => true
# light.current_state # => :green
# light.green? # => true
# light.change_color! # => true
# light.current_state # => :yellow
# light.red? # => false
# light.change_color # => true
# "That'll be $250."
#
#
# * The initial state for TrafficLight is red which is the first state defined.
#
# # Want to know the initial_state?
# TrafficLight.state_machine.initial_state # => :red
#
# * On a succesful transition to red (from yellow), the local +catch_runners+
# method is executed
#
# * The object acts differently depending on its current state, for instance,
# the change_color! method has a different action depending on the current
# color of the light
#
# * Get the possible events for a state
#
# TrafficLight.state_machine.events_for(:red) # => [:change_color, :defect]
# TrafficLight.state_machine.events_for(:blink) # => [:repair]
#
#
# === Examples
#
# class TrafficLight
# include ActiveModel::StateMachine
#
# attr_reader :runners_caught
#
# def initialize
# @runners_caught = 0
# end
#
# state_machine do
# state :red
# state :green
# state :yellow
# state :blink
#
# event :change_color do
# transitions :to => :red, :from => [:yellow],
# :on_transition => :catch_runners
# transitions :to => :green, :from => [:red]
# transitions :to => :yellow, :from => [:green]
# end
#
# event :defect do
# transitions :to => :blink, :from => [:yellow, :red, :green]
# end
#
# event :repair do
# transitions :to => :red, :from => [:blink]
# end
# end
#
# def catch_runners
# @runners_caught += 1
# end
# end
#
# light = TrafficLight.new
# light.current_state # => :red
# light.change_color! # => true
# light.current_state # => :green
# light.green? # => true
# light.change_color! # => true
# light.current_state # => :yellow
# light.red? # => false
# light.change_color! # => true
# light.runners_caught # => 1
#
# * The initial state for TrafficLight is red which is the first state defined.
#
# TrafficLight.state_machine.initial_state # => :red
#
# * Call an event to transition a state machine, e.g. <tt>change_color!</tt>.
# You can call the event with or without the exclamation mark, however, the common Ruby
# idiom is to name methods that directly change the state of the receivier with
# an exclamation mark, so <tt>change_color!</tt> is preferred over <tt>change_color</tt>.
#
# light.current_state #=> :green
# light.change_color! #=> true
# light.current_state #=> :yellow
#
# * On a succesful transition to red (from yellow), the local +catch_runners+
# method is executed
#
# light.current_state #=> :red
# light.change_color! #=> true
# light.runners_caught #=> 1
#
# * The object acts differently depending on its current state, for instance,
# the change_color! method has a different action depending on the current
# color of the light
#
# light.change_color! #=> true
# light.current_state #=> :red
# light.change_color! #=> true
# light.current_state #=> :green
#
# * Get the possible events for a state
#
# TrafficLight.state_machine.events_for(:red) # => [:change_color, :defect]
# TrafficLight.state_machine.events_for(:blink) # => [:repair]
#
# The StateMachine also supports the following features :
#
# * Success callbacks on event transition
# * Success callbacks on event transition
#
# event :sample, :success => :we_win do
# ...
# end
#
# * Enter and exit callbacks par state
# event :sample, :success => :we_win do
# ...
# end
#
# state :open, :enter => [:alert_twitter, :send_emails], :exit => :alert_twitter
# * Enter and exit callbacks par state
#
# * Guards on transition
# state :open, :enter => [:alert_twitter, :send_emails], :exit => :alert_twitter
#
# event :close do
# # You may only close the store if the safe is locked!!
# transitions :to => :closed, :from => :open, :guard => :safe_locked?
# end
# * Guards on transition
#
# * Setting the initial state
#
# state_machine :initial => :yellow do
# ...
# end
# event :close do
# # You may only close the store if the safe is locked!!
# transitions :to => :closed, :from => :open, :guard => :safe_locked?
# end
#
# * Named the state machine, to have more than one
# * Setting the initial state
#
# class Stated
# include ActiveModel::StateMachine
# state_machine :initial => :yellow do
# ...
# end
#
# strate_machine :name => :ontest do
# end
# * Named the state machine, to have more than one
#
# state_machine do
# end
# class Stated
# include ActiveModel::StateMachine
#
# strate_machine :name => :ontest do
# end
#
# state_machine do
# end
# end
#
# # Get the state of the <tt>:ontest</tt> state machine
# stat.current_state(:ontest)
# # Get the initial state
# Stated.state_machine(:ontest).initial_state
#
# # Get the state of the <tt>:ontest</tt> state machine
# stat.current_state(:ontest)
# # Get the initial state
# Stated.state_machine(:ontest).initial_state
#
# * Changing the state
# * Changing the state
#
# stat.current_state(:default, :astate) # => :astate
# # But you must give the name of the state machine, here <tt>:default</tt>
# stat.current_state(:default, :astate) # => :astate
# # But you must give the name of the state machine, here <tt>:default</tt>
#
module StateMachine
autoload :Event, 'active_model/state_machine/event'
Expand Down

0 comments on commit 71328a9

Please sign in to comment.