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