lib/state_machine.rb in state_machine-0.2.1 vs lib/state_machine.rb in state_machine-0.3.0
- old
+ new
@@ -1,11 +1,11 @@
require 'state_machine/machine'
module PluginAWeek #:nodoc:
- # A state machine is a model of behavior composed of states, transitions,
- # and events. This helper adds support for defining this type of
- # functionality within your ActiveRecord models.
+ # A state machine is a model of behavior composed of states, events, and
+ # transitions. This helper adds support for defining this type of
+ # functionality within ActiveRecord models.
module StateMachine
def self.included(base) #:nodoc:
base.class_eval do
extend PluginAWeek::StateMachine::MacroMethods
end
@@ -17,14 +17,14 @@
#
# Configuration options:
# * +initial+ - The initial value of the attribute. This can either be the actual value or a Proc for dynamic initial states.
#
# This also requires a block which will be used to actually configure the
- # events and transitions for the state machine. *Note* that this block will
- # be executed within the context of the state machine. As a result, you will
- # not be able to access any class methods on the model unless you refer to
- # them directly (i.e. specifying the class name).
+ # events and transitions for the state machine. *Note* that this block
+ # will be executed within the context of the state machine. As a result,
+ # you will not be able to access any class methods on the model unless you
+ # refer to them directly (i.e. specifying the class name).
#
# For examples on the types of configured state machines and blocks, see
# the section below.
#
# == Examples
@@ -59,37 +59,45 @@
# end
#
# With a dynamic initial state:
#
# class Switch < ActiveRecord::Base
- # state_machine :status, :initial => Proc.new {|switch| (8..22).include?(Time.now.hour) ? 'on' : 'off'} do
+ # state_machine :status, :initial => lambda {|switch| (8..22).include?(Time.now.hour) ? 'on' : 'off'} do
# ...
# end
# end
#
# == Events and Transitions
#
# For more information about how to configure an event and its associated
# transitions, see PluginAWeek::StateMachine::Machine#event
+ #
+ # == Defining callbacks
+ #
+ # Within the +state_machine+ block, you can also define callbacks for
+ # particular states. For more information about defining these callbacks,
+ # see PluginAWeek::StateMachine::Machine#before_transition and
+ # PluginAWeek::StateMachine::Machine#after_transition.
def state_machine(*args, &block)
unless included_modules.include?(PluginAWeek::StateMachine::InstanceMethods)
write_inheritable_attribute :state_machines, {}
class_inheritable_reader :state_machines
- after_create :run_initial_state_machine_actions
-
include PluginAWeek::StateMachine::InstanceMethods
end
options = args.extract_options!
attribute = args.any? ? args.first.to_s : 'state'
- options[:initial] = state_machines[attribute].initial_state_without_processing if !options.include?(:initial) && state_machines[attribute]
- # This will create a new machine for subclasses as well so that the owner_class and
- # initial state can be overridden
- machine = state_machines[attribute] = PluginAWeek::StateMachine::Machine.new(self, attribute, options)
+ # Creates the state machine for this class. If a superclass has already
+ # defined the machine, then a copy of it will be used with its context
+ # changed to this class. If no machine has been defined before for the
+ # attribute, a new one will be created.
+ original = state_machines[attribute]
+ machine = state_machines[attribute] = original ? original.within_context(self, options) : PluginAWeek::StateMachine::Machine.new(self, attribute, options)
machine.instance_eval(&block) if block
+
machine
end
end
module InstanceMethods
@@ -101,28 +109,17 @@
# Defines the initial values for state machine attributes
def initialize_with_state_machine(attributes = nil)
initialize_without_state_machine(attributes)
- attribute_keys = (attributes || {}).keys.map!(&:to_s)
-
# Set the initial value of each state machine as long as the value wasn't
- # included in the attribute hash passed in
+ # included in the initial attributes
+ attributes = (attributes || {}).stringify_keys
self.class.state_machines.each do |attribute, machine|
- unless attribute_keys.include?(attribute)
- send("#{attribute}=", machine.initial_state(self))
- end
+ send("#{attribute}=", machine.initial_state(self)) unless attributes.include?(attribute)
end
yield self if block_given?
- end
-
- # Records the transition for the record going into its initial state
- def run_initial_state_machine_actions
- self.class.state_machines.each do |attribute, machine|
- callback = "after_enter_#{attribute}_#{self[attribute]}"
- run_callbacks(callback) if self[attribute] && self.class.respond_to?(callback)
- end
end
end
end
end