Skip to content
Browse files

Fixing up state machine docs

  • Loading branch information...
1 parent 6e45bf5 commit 71328a9856734dda82620f42e5161c7a74696145 @mikel mikel committed
Showing with 141 additions and 88 deletions.
  1. +13 −0 activemodel/README
  2. +128 −88 activemodel/lib/active_model/state_machine.rb
View
13 activemodel/README
@@ -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]
+
View
216 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'

0 comments on commit 71328a9

Please sign in to comment.
Something went wrong with that request. Please try again.