<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,5 +1,7 @@
 == master
 
+* Allow multiple state machines on the same class to target the same attribute
+* Use :attribute to customize the attribute target and remove :as, assuming the name is the first argument of #state_machine
 * Add support for customizing generated methods like #{attribute}_name using :as instead of always prefixing with the attribute name
 * Simplify reading from / writing to machine-related attributes on objects
 * Fix locale for ActiveRecord getting added to the i18n load path multiple times [Reiner Dieterich]</diff>
      <filename>CHANGELOG.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -5,10 +5,12 @@ require 'state_machine/machine'
 # functionality on any Ruby class.
 module StateMachine
   module MacroMethods
-    # Creates a new state machine for the given attribute.  The default
-    # attribute, if not specified, is &lt;tt&gt;:state&lt;/tt&gt;.
+    # Creates a new state machine with the given name.  The default name, if not
+    # specified, is &lt;tt&gt;:state&lt;/tt&gt;.
     # 
     # Configuration options:
+    # * &lt;tt&gt;:attribute&lt;/tt&gt; - The name of the attribute to store the state value
+    #   in.  By default, this is the same as the name of the machine.
     # * &lt;tt&gt;:initial&lt;/tt&gt; - The initial state of the attribute. This can be a
     #   static state or a lambda block which will be evaluated at runtime
     #   (e.g. lambda {|vehicle| vehicle.speed == 0 ? :parked : :idling}).
@@ -16,10 +18,6 @@ module StateMachine
     # * &lt;tt&gt;:action&lt;/tt&gt; - The instance method to invoke when an object
     #   transitions. Default is nil unless otherwise specified by the
     #   configured integration.
-    # * &lt;tt&gt;:as&lt;/tt&gt; - The name to use for prefixing all generated machine
-    #   instance / class methods (e.g. if the attribute is +state_id+, then
-    #   &quot;state&quot; would generate :state_name, :state_transitions, etc. instead of
-    #   :state_id_name and :state_id_transitions)
     # * &lt;tt&gt;:namespace&lt;/tt&gt; - The name to use for namespacing all generated
     #   state / event instance methods (e.g. &quot;heater&quot; would generate
     #   :turn_on_heater and :turn_off_heater for the :turn_on/:turn_off events).
@@ -54,7 +52,7 @@ module StateMachine
     # 
     # == Examples
     # 
-    # With the default attribute and no configuration:
+    # With the default name/attribute and no configuration:
     # 
     #   class Vehicle
     #     state_machine do
@@ -64,13 +62,14 @@ module StateMachine
     #     end
     #   end
     # 
-    # The above example will define a state machine for the +state+ attribute
-    # on the class.  Every vehicle will start without an initial state.
+    # The above example will define a state machine named &quot;state&quot; that will
+    # store the value in the +state+ attribute.  Every vehicle will start
+    # without an initial state.
     # 
-    # With a custom attribute:
+    # With a custom name / attribute:
     # 
     #   class Vehicle
-    #     state_machine :status do
+    #     state_machine :status, :attribute =&gt; :status_value do
     #       ...
     #     end
     #   end
@@ -94,7 +93,8 @@ module StateMachine
     # == Instance Methods
     # 
     # The following instance methods will be automatically generated by the
-    # state machine.  Any existing methods will not be overwritten.
+    # state machine based on the *name* of the machine.  Any existing methods
+    # will not be overwritten.
     # * &lt;tt&gt;state&lt;/tt&gt; - Gets the current value for the attribute
     # * &lt;tt&gt;state=(value)&lt;/tt&gt; - Sets the current value for the attribute
     # * &lt;tt&gt;state?(name)&lt;/tt&gt; - Checks the given state name against the current
@@ -295,55 +295,11 @@ module StateMachine
     # see StateMachine::Machine#before_transition and
     # StateMachine::Machine#after_transition.
     # 
-    # == Attribute aliases
-    # 
-    # When a state machine is defined, several methods are generated scoped by
-    # the name of the attribute, such as (if the attribute were &quot;state&quot;):
-    # * &lt;tt&gt;state_name&lt;/tt&gt;
-    # * &lt;tt&gt;state_event&lt;/tt&gt;
-    # * &lt;tt&gt;state_transitions&lt;/tt&gt;
-    # * etc.
-    # 
-    # If the attribute for the machine were something less common, such as
-    # &quot;state_id&quot; or &quot;state_value&quot;, this makes for more awkward scoped methods.
-    # 
-    # Rather than scope based on the attribute, these methods can be customized
-    # using the &lt;tt&gt;:as&lt;/tt&gt; option as essentially an alias.
-    # 
-    # For example,
-    # 
-    #   class Vehicle
-    #     state_machine :state_id, :as =&gt; :state do
-    #       event :turn_on do
-    #         transition all =&gt; :on
-    #       end
-    #       
-    #       event :turn_off do
-    #         transition all =&gt; :off
-    #       end
-    #       
-    #       state :on, :value =&gt; 1
-    #       state :off, :value =&gt; 2
-    #     end
-    #   end
-    # 
-    # ...will generate the following methods:
-    # * &lt;tt&gt;state_name&lt;/tt&gt;
-    # * &lt;tt&gt;state_event&lt;/tt&gt;
-    # * &lt;tt&gt;state_transitions&lt;/tt&gt;
-    # 
-    # ...instead of:
-    # * &lt;tt&gt;state_id_name&lt;/tt&gt;
-    # * &lt;tt&gt;state_id_event&lt;/tt&gt;
-    # * &lt;tt&gt;state_id_transitions&lt;/tt&gt;
-    # 
-    # However, it will continue to read and write to the +state_id+ attribute.
-    # 
     # == Namespaces
     # 
     # When a namespace is configured for a state machine, the name provided
     # will be used in generating the instance methods for interacting with
-    # events/states in the machine.  This is particularly useful when a class
+    # states/events in the machine.  This is particularly useful when a class
     # has multiple state machines and it would be difficult to differentiate
     # between the various states / events.
     # </diff>
      <filename>lib/state_machine.rb</filename>
    </modified>
    <modified>
      <diff>@@ -84,14 +84,14 @@ module StateMachine
     # you can build two state machines (one public and one protected) like so:
     # 
     #   class Vehicle &lt; ActiveRecord::Base
-    #     alias_attribute :public_state # Allow both machines to share the same state
     #     attr_protected :state_event # Prevent access to events in the first machine
     #     
     #     state_machine do
     #       # Define private events here
     #     end
     #     
-    #     state_machine :public_state do
+    #     # Public machine targets the same state as the private machine
+    #     state_machine :public_state, :attribute =&gt; :state do
     #       # Define public events here
     #     end
     #   end
@@ -310,8 +310,10 @@ module StateMachine
         
         # Skips defining reader/writer methods since this is done automatically
         def define_state_accessor
+          name = self.name
+          
           owner_class.validates_each(attribute) do |record, attr, value|
-            machine = record.class.state_machine(attr)
+            machine = record.class.state_machine(name)
             machine.invalidate(record, attr, :invalid) unless machine.states.match(record)
           end
         end
@@ -321,13 +323,12 @@ module StateMachine
         # *anything* is set for the attribute's value
         def define_state_predicate
           name = self.name
-          attribute = self.attribute
           
           # Still use class_eval here instance of define_instance_method since
           # we need to be able to call +super+
           @instance_helper_module.class_eval do
             define_method(&quot;#{name}?&quot;) do |*args|
-              args.empty? ? super(*args) : self.class.state_machine(attribute).states.matches?(self, *args)
+              args.empty? ? super(*args) : self.class.state_machine(name).states.matches?(self, *args)
             end
           end
         end
@@ -388,17 +389,18 @@ module StateMachine
         # inheritance is respected properly.
         def define_scope(name, scope)
           name = name.to_sym
-          attribute = self.attribute
+          machine_name = self.name
           
-          # Created the scope and then override it with state translation
+          # Create the scope and then override it with state translation
           owner_class.named_scope(name)
           owner_class.scopes[name] = lambda do |klass, *states|
-            machine_states = klass.state_machine(attribute).states
+            machine_states = klass.state_machine(machine_name).states
             values = states.flatten.map {|state| machine_states.fetch(state).value}
             
             ::ActiveRecord::NamedScope::Scope.new(klass, scope.call(values))
           end
           
+          # Prevent the Machine class from wrapping the scope
           false
         end
         
@@ -409,10 +411,10 @@ module StateMachine
         # * #{type}_#{qualified_event}_from_#{from}
         # * #{type}_#{qualified_event}_to_#{to}
         # * #{type}_#{qualified_event}
-        # * #{type}_transition_#{attribute}_from_#{from}_to_#{to}
-        # * #{type}_transition_#{attribute}_from_#{from}
-        # * #{type}_transition_#{attribute}_to_#{to}
-        # * #{type}_transition_#{attribute}
+        # * #{type}_transition_#{machine_name}_from_#{from}_to_#{to}
+        # * #{type}_transition_#{machine_name}_from_#{from}
+        # * #{type}_transition_#{machine_name}_to_#{to}
+        # * #{type}_transition_#{machine_name}
         # * #{type}_transition
         # 
         # This will always return true regardless of the results of the</diff>
      <filename>lib/state_machine/integrations/active_record.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,7 @@
   :activerecord =&gt; {
     :errors =&gt; {
       :messages =&gt; {
+        :invalid =&gt; StateMachine::Machine.default_messages[:invalid],
         :invalid_event =&gt; StateMachine::Machine.default_messages[:invalid_event] % ['{{state}}'],
         :invalid_transition =&gt; StateMachine::Machine.default_messages[:invalid_transition] % ['{{event}}']
       }</diff>
      <filename>lib/state_machine/integrations/active_record/locale.rb</filename>
    </modified>
    <modified>
      <diff>@@ -94,16 +94,13 @@ module StateMachine
     #     include DataMapper::Resource
     #     ...
     #     
-    #     # Allow both machines to share the same state
-    #     alias_method :public_state, :state
-    #     alias_method :public_state=, :state=
-    #     
     #     state_machine do
     #       # Define private events here
     #     end
     #     protected :state_event= # Prevent access to events in the first machine
     #     
-    #     state_machine :public_state do
+    #     # Allow both machines to share the same state
+    #     state_machine :public_state, :attribute =&gt; :state do
     #       # Define public events here
     #     end
     #   end
@@ -112,7 +109,7 @@ module StateMachine
     # 
     # By default, the use of transactions during an event transition is
     # turned off to be consistent with DataMapper.  This means that if
-    # changes are made to the database during a before callback, but the the
+    # changes are made to the database during a before callback, but the
     # transition fails to complete, those changes will *not* be rolled back.
     # 
     # For example,
@@ -274,9 +271,9 @@ module StateMachine
           owner_class.property(attribute, String) unless owner_class.properties.has_property?(attribute)
           
           if supports_validations?
-            attribute = self.attribute
+            name = self.name
             owner_class.validates_with_block(attribute) do
-              machine = self.class.state_machine(attribute)
+              machine = self.class.state_machine(name)
               machine.states.match(self) ? true : [false, machine.generate_message(:invalid)]
             end
           end</diff>
      <filename>lib/state_machine/integrations/data_mapper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -109,19 +109,19 @@ module StateMachine
           # state machines for each observed class.
           def add_transition_callback(type, *args, &amp;block)
             if args.any? &amp;&amp; !args.first.is_a?(Hash)
-              # Specific attribute(s) being targeted
-              attributes = args
+              # Specific machine(s) being targeted
+              names = args
               args = args.last.is_a?(Hash) ? [args.pop] : []
             else
               # Target all state machines
-              attributes = nil
+              names = nil
             end
             
             # Add the transition callback to each class being observed
             observing.each do |klass|
               state_machines =
-                if attributes
-                  attributes.map {|attribute| klass.state_machines.fetch(attribute)}
+                if names
+                  names.map {|name| klass.state_machines.fetch(name)}
                 else
                   klass.state_machines.values
                 end</diff>
      <filename>lib/state_machine/integrations/data_mapper/observer.rb</filename>
    </modified>
    <modified>
      <diff>@@ -84,17 +84,14 @@ module StateMachine
     # you can build two state machines (one public and one protected) like so:
     # 
     #   class Vehicle &lt; Sequel::Model
-    #     # Allow both machines to share the same state
-    #     alias_method :public_state, :state
-    #     alias_method :public_state=, :state=
-    #     
     #     set_restricted_columns :state_event # Prevent access to events in the first machine
     #     
     #     state_machine do
     #       # Define private events here
     #     end
     #     
-    #     state_machine :public_state do
+    #     # Allow both machines to share the same state
+    #     state_machine :public_state, :attribute =&gt; :state do
     #       # Define public events here
     #     end
     #   end
@@ -242,8 +239,9 @@ module StateMachine
       protected
         # Skips defining reader/writer methods since this is done automatically
         def define_state_accessor
+          name = self.name
           owner_class.validates_each(attribute) do |record, attr, value|
-            machine = record.class.state_machine(attr)
+            machine = record.class.state_machine(name)
             machine.invalidate(record, attr, :invalid) unless machine.states.match(record)
           end
         end</diff>
      <filename>lib/state_machine/integrations/sequel.rb</filename>
    </modified>
    <modified>
      <diff>@@ -113,14 +113,14 @@ module StateMachine
   # 
   # Callbacks are supported for hooking before and after every possible
   # transition in the machine.  Each callback is invoked in the order in which
-  # it was defined.  See StateMachine::Machine#before_transition
-  # and StateMachine::Machine#after_transition for documentation
-  # on how to define new callbacks.
+  # it was defined.  See StateMachine::Machine#before_transition and
+  # StateMachine::Machine#after_transition for documentation on how to define
+  # new callbacks.
   # 
-  # *Note* that callbacks only get executed within the context of an event.
-  # As a result, if a class has an initial state when it's created, any
-  # callbacks that would normally get executed when the object enters that
-  # state will *not* get triggered.
+  # *Note* that callbacks only get executed within the context of an event.  As
+  # a result, if a class has an initial state when it's created, any callbacks
+  # that would normally get executed when the object enters that state will
+  # *not* get triggered.
   # 
   # For example,
   # 
@@ -229,7 +229,7 @@ module StateMachine
   #   
   #   [Vehicle, Switch, Project].each do |klass|
   #     klass.state_machines.each do |attribute, machine|
-  #       machine.before_transition klass.method(:before_transition)
+  #       machine.before_transition StateMachineObserver.method(:before_transition)
   #     end
   #   end
   # 
@@ -300,10 +300,10 @@ module StateMachine
       # in the new owner class (the original will remain unchanged).
       def find_or_create(owner_class, *args, &amp;block)
         options = args.last.is_a?(Hash) ? args.pop : {}
-        attribute = args.first || :state
+        name = args.first || :state
         
         # Find an existing machine
-        if owner_class.respond_to?(:state_machines) &amp;&amp; machine = owner_class.state_machines[attribute]
+        if owner_class.respond_to?(:state_machines) &amp;&amp; machine = owner_class.state_machines[name]
           # Only create a new copy if changes are being made to the machine in
           # a subclass
           if machine.owner_class != owner_class &amp;&amp; (options.any? || block_given?)
@@ -316,7 +316,7 @@ module StateMachine
           machine.instance_eval(&amp;block) if block_given?
         else
           # No existing machine: create a new one
-          machine = new(owner_class, attribute, options, &amp;block)
+          machine = new(owner_class, name, options, &amp;block)
         end
         
         machine
@@ -347,7 +347,7 @@ module StateMachine
           end
           
           # Draw each of the class's state machines
-          klass.state_machines.each do |name, machine|
+          klass.state_machines.each_value do |machine|
             machine.draw(options)
           end
         end
@@ -365,9 +365,6 @@ module StateMachine
     # The class that the machine is defined in
     attr_accessor :owner_class
     
-    # The attribute for which the machine is being defined
-    attr_reader :attribute
-    
     # The name of the machine, used for scoping methods generated for the
     # machine as a whole (not states or events)
     attr_reader :name
@@ -406,7 +403,7 @@ module StateMachine
     # Creates a new state machine for the given attribute
     def initialize(owner_class, *args, &amp;block)
       options = args.last.is_a?(Hash) ? args.pop : {}
-      assert_valid_keys(options, :as, :initial, :action, :plural, :namespace, :integration, :messages, :use_transactions)
+      assert_valid_keys(options, :attribute, :initial, :action, :plural, :namespace, :integration, :messages, :use_transactions)
       
       # Find an integration that matches this machine's owner class
       if integration = options[:integration] ? StateMachine::Integrations.find(options[:integration]) : StateMachine::Integrations.match(owner_class)
@@ -418,8 +415,8 @@ module StateMachine
       options = {:use_transactions =&gt; true}.merge(options)
       
       # Set machine configuration
-      @attribute = args.first || :state
-      @name = options[:as] || @attribute
+      @name = args.first || :state
+      @attribute = options[:attribute] || @name
       @events = EventCollection.new(self)
       @states = StateCollection.new(self)
       @callbacks = {:before =&gt; [], :after =&gt; []}
@@ -472,10 +469,9 @@ module StateMachine
         include instance_helper_module
       end
       
-      # Record this machine as matched to the attribute in the current owner
-      # class.  This will override any machines mapped to the same attribute
-      # in any superclasses.
-      owner_class.state_machines[attribute] = self
+      # Record this machine as matched to the name in the current owner class.
+      # This will override any machines mapped to the same name in any superclasses.
+      owner_class.state_machines[name] = self
     end
     
     # Sets the initial state of the machine.  This can be either the static name
@@ -505,11 +501,11 @@ module StateMachine
     #     machine.states.match(object)
     #   end
     def define_instance_method(method, &amp;block)
-      attribute = self.attribute
+      name = self.name
       
       @instance_helper_module.class_eval do
         define_method(method) do |*args|
-          block.call(self.class.state_machine(attribute), self, *args)
+          block.call(self.class.state_machine(name), self, *args)
         end
       end
     end
@@ -525,11 +521,11 @@ module StateMachine
     #     machine.states.keys
     #   end
     def define_class_method(method, &amp;block)
-      attribute = self.attribute
+      name = self.name
       
       @class_helper_module.class_eval do
         define_method(method) do |*args|
-          block.call(self.state_machine(attribute), self, *args)
+          block.call(self.state_machine(name), self, *args)
         end
       end
     end
@@ -626,7 +622,7 @@ module StateMachine
     #   end
     #   
     #   class Vehicle &lt; ActiveRecord::Base
-    #     state_machine :state_id, :as =&gt; 'state', :initial =&gt; :parked do
+    #     state_machine :attribute =&gt; :state_id, :initial =&gt; :parked do
     #       event :ignite do
     #         transition :parked =&gt; :idling
     #       end
@@ -852,7 +848,7 @@ module StateMachine
       ivar ? object.instance_variable_get(&quot;@#{attribute}&quot;) : object.send(attribute)
     end
     
-    # Sets a new value in the given object's state.
+    # Sets a new value in the given object's attribute.
     # 
     # For example,
     # 
@@ -862,9 +858,11 @@ module StateMachine
     #     end
     #   end
     #   
-    #   vehicle = Vehicle.new   # =&gt; #&lt;Vehicle:0xb7d94ab0 @state=&quot;parked&quot;&gt;
-    #   Vehicle.state_machine.write(vehicle, 'idling')
-    #   vehicle.state           # =&gt; &quot;idling&quot;
+    #   vehicle = Vehicle.new                                   # =&gt; #&lt;Vehicle:0xb7d94ab0 @state=&quot;parked&quot;&gt;
+    #   Vehicle.state_machine.write(vehicle, :state, 'idling')  # =&gt; Equivalent to vehicle.state = 'idling'
+    #   Vehicle.state_machine.write(vehicle, :event, 'park')    # =&gt; Equivalent to vehicle.state_event = 'park'
+    #   vehicle.state                                           # =&gt; &quot;idling&quot;
+    #   vehicle.event                                           # =&gt; &quot;park&quot;
     def write(object, attribute, value)
       object.send(&quot;#{self.attribute(attribute)}=&quot;, value)
     end
@@ -1124,12 +1122,12 @@ module StateMachine
     # 
     #   class Vehicle
     #     # Only specifies one parameter (the object being transitioned)
-    #     before_transition :to =&gt; :parked do |vehicle|
+    #     before_transition all =&gt; :parked do |vehicle|
     #       vehicle.set_alarm
     #     end
     #     
     #     # Specifies 2 parameters (object being transitioned and actual transition)
-    #     before_transition :to =&gt; :parked do |vehicle, transition|
+    #     before_transition all =&gt; :parked do |vehicle, transition|
     #       vehicle.set_alarm(transition)
     #     end
     #   end
@@ -1155,7 +1153,7 @@ module StateMachine
     #       before_transition [:first_gear, :idling] =&gt; :parked, :on =&gt; :park, :do =&gt; :take_off_seatbelt
     #       
     #       # With conditional callback:
-    #       before_transition :to =&gt; :parked, :do =&gt; :take_off_seatbelt, :if =&gt; :seatbelt_on?
+    #       before_transition all =&gt; :parked, :do =&gt; :take_off_seatbelt, :if =&gt; :seatbelt_on?
     #       
     #       # Using helpers:
     #       before_transition all - :stalled =&gt; same, :on =&gt; any - :crash, :do =&gt; :update_dashboard
@@ -1217,7 +1215,7 @@ module StateMachine
     # 
     # Configuration options:
     # * &lt;tt&gt;:name&lt;/tt&gt; - The name of the file to write to (without the file extension).
-    #   Default is &quot;#{owner_class.name}_#{attribute}&quot;
+    #   Default is &quot;#{owner_class.name}_#{name}&quot;
     # * &lt;tt&gt;:path&lt;/tt&gt; - The path to write the graph file to.  Default is the
     #   current directory (&quot;.&quot;).
     # * &lt;tt&gt;:format&lt;/tt&gt; - The image format to generate the graph in.
@@ -1229,7 +1227,7 @@ module StateMachine
     # * &lt;tt&gt;:output&lt;/tt&gt; - Whether to generate the output of the graph
     def draw(options = {})
       options = {
-        :name =&gt; &quot;#{owner_class.name}_#{attribute}&quot;,
+        :name =&gt; &quot;#{owner_class.name}_#{name}&quot;,
         :path =&gt; '.',
         :format =&gt; 'png',
         :font =&gt; 'Arial',
@@ -1322,8 +1320,6 @@ module StateMachine
         
         # Add helpers for interacting with the action
         if action
-          name = self.name
-          
           # Tracks the event / transition to invoke when the action is called
           event_attribute = attribute(:event)
           event_transition_attribute = attribute(:event_transition)
@@ -1348,7 +1344,7 @@ module StateMachine
         action = self.action
         private_method = owner_class.private_method_defined?(action_hook)
         
-        if (owner_class.method_defined?(action_hook) || private_method) &amp;&amp; !owner_class.state_machines.any? {|attribute, machine| machine.action == action &amp;&amp; machine != self}
+        if (owner_class.method_defined?(action_hook) || private_method) &amp;&amp; !owner_class.state_machines.any? {|name, machine| machine.action == action &amp;&amp; machine != self}
           # Action is defined and hasn't already been overridden by another machine
           @instance_helper_module.class_eval do
             # Override the default action to invoke the before / after hooks</diff>
      <filename>lib/state_machine/machine.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@ module StateMachine
     # values are only set if the machine's attribute doesn't already exist
     # (which must mean the defaults are being skipped)
     def initialize_states(object)
-      each do |attribute, machine|
+      each_value do |machine|
         value = machine.read(object, :state)
         machine.write(object, :state, machine.initial_state(object).value) if value.nil? || value.respond_to?(:empty?) &amp;&amp; value.empty?
       end
@@ -17,19 +17,19 @@ module StateMachine
       run_action = [true, false].include?(events.last) ? events.pop : true
       
       # Generate the transitions to run for each event
-      transitions = events.collect do |name|
+      transitions = events.collect do |event_name|
         # Find the actual event being run
         event = nil
-        detect do |attribute, machine|
-          event = machine.events[name, :qualified_name]
+        detect do |name, machine|
+          event = machine.events[event_name, :qualified_name]
         end
         
-        raise InvalidEvent, &quot;#{name.inspect} is an unknown state machine event&quot; unless event
+        raise InvalidEvent, &quot;#{event_name.inspect} is an unknown state machine event&quot; unless event
         
         # Get the transition that will be performed for the event
         unless transition = event.transition_for(object)
           machine = event.machine
-          machine.invalidate(object, machine.attribute, :invalid_transition, [[:event, name]])
+          machine.invalidate(object, :state, :invalid_transition, [[:event, event_name]])
         end
         
         transition
@@ -107,7 +107,7 @@ module StateMachine
     #   vehicle.state_event_transition                # =&gt; #&lt;StateMachine::Transition attribute=:state event=:ignite from=&quot;parked&quot; from_name=:parked to=&quot;idling&quot; to_name=:idling&gt;
     def fire_event_attributes(object, action, complete = true)
       # Get the transitions to fire for each applicable machine
-      transitions = map {|attribute, machine| machine.action == action ? machine.events.attribute_transition_for(object, true) : nil}.compact
+      transitions = map {|name, machine| machine.action == action ? machine.events.attribute_transition_for(object, true) : nil}.compact
       return yield if transitions.empty?
       
       # The value generated by the yielded block (the actual action)
@@ -122,7 +122,7 @@ module StateMachine
             action_value = yield
           end
         rescue Exception
-          # Revert attribute modifications
+          # Revert object modifications
           transitions.each do |transition|
             transition.machine.write(object, :event, transition.event)
             transition.machine.write(object, :event_transition, nil) if complete</diff>
      <filename>lib/state_machine/machine_collection.rb</filename>
    </modified>
    <modified>
      <diff>@@ -156,11 +156,11 @@ module StateMachine
     # a new module will be included in the owner class.
     def context(&amp;block)
       owner_class = machine.owner_class
-      attribute = machine.attribute
+      machine_name = machine.name
       name = self.name
       
       # Evaluate the method definitions
-      context = ConditionProxy.new(owner_class, lambda {|object| object.class.state_machine(attribute).states.matches?(object, name)})
+      context = ConditionProxy.new(owner_class, lambda {|object| object.class.state_machine(machine_name).states.matches?(object, name)})
       context.class_eval(&amp;block)
       context.instance_methods.each do |method|
         methods[method.to_sym] = context.instance_method(method)
@@ -168,7 +168,7 @@ module StateMachine
         # Calls the method defined by the current state of the machine
         context.class_eval &lt;&lt;-end_eval, __FILE__, __LINE__
           def #{method}(*args, &amp;block)
-            self.class.state_machine(#{attribute.inspect}).states.match!(self).call(self, #{method.inspect}, *args, &amp;block)
+            self.class.state_machine(#{machine_name.inspect}).states.match!(self).call(self, #{method.inspect}, *args, &amp;block)
           end
         end_eval
       end</diff>
      <filename>lib/state_machine/state.rb</filename>
    </modified>
    <modified>
      <diff>@@ -262,14 +262,14 @@ class EventCollectionWithValidationsTest &lt; Test::Unit::TestCase
   end
 end
 
-class EventCollectionWithCustomMachineNameTest &lt; Test::Unit::TestCase
+class EventCollectionWithCustomMachineAttributeTest &lt; Test::Unit::TestCase
   def setup
     @klass = Class.new do
       def save
       end
     end
     
-    @machine = StateMachine::Machine.new(@klass, :state_id, :as =&gt; 'state', :initial =&gt; :parked, :action =&gt; :save)
+    @machine = StateMachine::Machine.new(@klass, :state, :attribute =&gt; :state_id, :initial =&gt; :parked, :action =&gt; :save)
     @events = StateMachine::EventCollection.new(@machine)
     
     @machine.event :ignite</diff>
      <filename>test/unit/event_collection_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -367,6 +367,60 @@ begin
       end
     end
     
+    class MachineWithOwnerSubclassTest &lt; ActiveRecord::TestCase
+      def setup
+        @model = new_model
+        @machine = StateMachine::Machine.new(@model, :state)
+        
+        @subclass = Class.new(@model)
+        @subclass_machine = @subclass.state_machine(:state) {}
+        @subclass_machine.state :parked, :idling, :first_gear
+      end
+      
+      def test_should_only_include_records_with_subclass_states_in_with_scope
+        parked = @subclass.create :state =&gt; 'parked'
+        idling = @subclass.create :state =&gt; 'idling'
+        
+        assert_equal [parked, idling], @subclass.with_states(:parked, :idling)
+      end
+      
+      def test_should_only_include_records_without_subclass_states_in_without_scope
+        parked = @subclass.create :state =&gt; 'parked'
+        idling = @subclass.create :state =&gt; 'idling'
+        first_gear = @subclass.create :state =&gt; 'first_gear'
+        
+        assert_equal [parked, idling], @subclass.without_states(:first_gear)
+      end
+    end
+    
+    class MachineWithCustomAttributeTest &lt; ActiveRecord::TestCase
+      def setup
+        @model = new_model
+        @machine = StateMachine::Machine.new(@model, :status, :attribute =&gt; :state)
+        @machine.state :parked
+        
+        @record = @model.new
+      end
+      
+      def test_should_add_validation_errors_to_custom_attribute
+        @record.state = 'invalid'
+        
+        assert !@record.valid?
+        assert_equal ['State is invalid'], @record.errors.full_messages
+        
+        @record.state = 'parked'
+        assert @record.valid?
+      end
+      
+      def test_should_check_custom_attribute_for_predicate
+        @record.state = nil
+        assert !@record.status?(:parked)
+        
+        @record.state = 'parked'
+        assert @record.status?(:parked)
+      end
+    end
+    
     class MachineWithCallbacksTest &lt; ActiveRecord::TestCase
       def setup
         @model = new_model</diff>
      <filename>test/unit/integrations/active_record_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -232,6 +232,32 @@ begin
       end
     end
     
+    class MachineWithOwnerSubclassTest &lt; BaseTestCase
+      def setup
+        @resource = new_resource
+        @machine = StateMachine::Machine.new(@resource, :state)
+        
+        @subclass = Class.new(@resource)
+        @subclass_machine = @subclass.state_machine(:state) {}
+        @subclass_machine.state :parked, :idling, :first_gear
+      end
+      
+      def test_should_only_include_records_with_subclass_states_in_with_scope
+        parked = @subclass.create :state =&gt; 'parked'
+        idling = @subclass.create :state =&gt; 'idling'
+        
+        assert_equal [parked, idling], @subclass.with_states(:parked, :idling)
+      end
+      
+      def test_should_only_include_records_without_subclass_states_in_without_scope
+        parked = @subclass.create :state =&gt; 'parked'
+        idling = @subclass.create :state =&gt; 'idling'
+        first_gear = @subclass.create :state =&gt; 'first_gear'
+        
+        assert_equal [parked, idling], @subclass.without_states(:first_gear)
+      end
+    end
+    
     class MachineWithCallbacksTest &lt; BaseTestCase
       def setup
         @resource = new_resource
@@ -572,6 +598,26 @@ begin
         end
       end
       
+      class MachineWithValidationsAndCustomAttributeTest &lt; BaseTestCase
+        def setup
+          @resource = new_resource
+          @machine = StateMachine::Machine.new(@resource, :status, :attribute =&gt; :state)
+          @machine.state :parked
+          
+          @record = @resource.new
+        end
+        
+        def test_should_add_validation_errors_to_custom_attribute
+          @record.state = 'invalid'
+          
+          assert !@record.valid?
+          assert_equal ['is invalid'], @record.errors.on(:state)
+          
+          @record.state = 'parked'
+          assert @record.valid?
+        end
+      end
+      
       class MachineWithStateDrivenValidationsTest &lt; BaseTestCase
         def setup
           @resource = new_resource do</diff>
      <filename>test/unit/integrations/data_mapper_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -252,6 +252,52 @@ begin
       end
     end
     
+    class MachineWithOwnerSubclassTest &lt; BaseTestCase
+      def setup
+        @model = new_model
+        @machine = StateMachine::Machine.new(@model, :state)
+        
+        @subclass = Class.new(@model)
+        @subclass_machine = @subclass.state_machine(:state) {}
+        @subclass_machine.state :parked, :idling, :first_gear
+      end
+      
+      def test_should_only_include_records_with_subclass_states_in_with_scope
+        parked = @subclass.create :state =&gt; 'parked'
+        idling = @subclass.create :state =&gt; 'idling'
+        
+        assert_equal [parked, idling], @subclass.with_states(:parked, :idling).all
+      end
+      
+      def test_should_only_include_records_without_subclass_states_in_without_scope
+        parked = @subclass.create :state =&gt; 'parked'
+        idling = @subclass.create :state =&gt; 'idling'
+        first_gear = @subclass.create :state =&gt; 'first_gear'
+        
+        assert_equal [parked, idling], @subclass.without_states(:first_gear).all
+      end
+    end
+    
+    class MachineWithCustomAttributeTest &lt; BaseTestCase
+      def setup
+        @model = new_model
+        @machine = StateMachine::Machine.new(@model, :status, :attribute =&gt; :state)
+        @machine.state :parked
+        
+        @record = @model.new
+      end
+      
+      def test_should_add_validation_errors_to_custom_attribute
+        @record.state = 'invalid'
+        
+        assert !@record.valid?
+        assert_equal ['is invalid'], @record.errors.on(:state)
+        
+        @record.state = 'parked'
+        assert @record.valid?
+      end
+    end
+    
     class MachineWithCallbacksTest &lt; BaseTestCase
       def setup
         @model = new_model</diff>
      <filename>test/unit/integrations/sequel_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -151,22 +151,22 @@ class MachineByDefaultTest &lt; Test::Unit::TestCase
   end
 end
 
-class MachineWithCustomAttributeTest &lt; Test::Unit::TestCase
+class MachineWithCustomNameTest &lt; Test::Unit::TestCase
   def setup
     @klass = Class.new
     @machine = StateMachine::Machine.new(@klass, :status)
     @object = @klass.new
   end
   
-  def test_should_use_custom_attribute_for_name
+  def test_should_use_custom_name
     assert_equal :status, @machine.name
   end
   
-  def test_should_use_custom_attribute
+  def test_should_use_custom_name_for_attribute
     assert_equal :status, @machine.attribute
   end
   
-  def test_should_prefix_custom_attributes_with_custom_attribute
+  def test_should_prefix_custom_attributes_with_custom_name
     assert_equal :status_event, @machine.attribute(:event)
   end
   
@@ -1486,6 +1486,40 @@ class MachineWithExistingMachinesOnOwnerClassTest &lt; Test::Unit::TestCase
   end
 end
 
+class MachineWithExistingMachinesWithSameAttributesOnOwnerClassTest &lt; Test::Unit::TestCase
+  def setup
+    @klass = Class.new
+    @machine = StateMachine::Machine.new(@klass, :initial =&gt; :parked)
+    @second_machine = StateMachine::Machine.new(@klass, :public_state, :attribute =&gt; :state)
+    @object = @klass.new
+  end
+  
+  def test_should_track_each_state_machine
+    expected = {:state =&gt; @machine, :public_state =&gt; @second_machine}
+    assert_equal expected, @klass.state_machines
+  end
+  
+  def test_should_initialize_based_on_first_available_initial_state
+    assert_equal 'parked', @object.state
+  end
+  
+  def test_should_allow_transitions_on_both_machines
+    @machine.event :ignite do
+      transition :parked =&gt; :idling
+    end
+    
+    @second_machine.event :park do
+      transition :idling =&gt; :parked
+    end
+    
+    @object.ignite
+    assert_equal 'idling', @object.state
+    
+    @object.park
+    assert_equal 'parked', @object.state
+  end
+end
+
 class MachineWithNamespaceTest &lt; Test::Unit::TestCase
   def setup
     @klass = Class.new
@@ -1532,7 +1566,7 @@ class MachineWithNamespaceTest &lt; Test::Unit::TestCase
   end
 end
 
-class MachineWithCustomNameTest &lt; Test::Unit::TestCase
+class MachineWithCustomAttributeTest &lt; Test::Unit::TestCase
   def setup
     StateMachine::Integrations.const_set('Custom', Module.new do  
       class &lt;&lt; self; attr_reader :defaults; end
@@ -1548,7 +1582,7 @@ class MachineWithCustomNameTest &lt; Test::Unit::TestCase
     end)
     
     @klass = Class.new
-    @machine = StateMachine::Machine.new(@klass, :state_id, :as =&gt; 'state', :initial =&gt; :active, :integration =&gt; :custom) do
+    @machine = StateMachine::Machine.new(@klass, :state, :attribute =&gt; :state_id, :initial =&gt; :active, :integration =&gt; :custom) do
       event :ignite do
         transition :parked =&gt; :idling
       end
@@ -1556,12 +1590,12 @@ class MachineWithCustomNameTest &lt; Test::Unit::TestCase
     @object = @klass.new
   end
   
-  def test_should_not_define_a_reader_attribute_for_the_attribute
-    assert !@object.respond_to?(:state)
+  def test_should_define_a_reader_attribute_for_the_attribute
+    assert @object.respond_to?(:state_id)
   end
   
-  def test_should_not_define_a_writer_attribute_for_the_attribute
-    assert !@object.respond_to?(:state=)
+  def test_should_define_a_writer_attribute_for_the_attribute
+    assert @object.respond_to?(:state_id=)
   end
   
   def test_should_define_a_predicate_for_the_attribute
@@ -1596,6 +1630,11 @@ class MachineWithCustomNameTest &lt; Test::Unit::TestCase
     assert @klass.respond_to?(:without_states)
   end
   
+  def test_should_define_state_machines_reader
+    expected = {:state =&gt; @machine}
+    assert_equal expected, @klass.state_machines
+  end
+  
   def teardown
     StateMachine::Integrations.send(:remove_const, 'Custom')
   end</diff>
      <filename>test/unit/machine_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -197,10 +197,10 @@ class TransitionWithNamespaceTest &lt; Test::Unit::TestCase
   end
 end
 
-class TransitionWithCustomMachineNameTest &lt; Test::Unit::TestCase
+class TransitionWithCustomMachineAttributeTest &lt; Test::Unit::TestCase
   def setup
     @klass = Class.new
-    @machine = StateMachine::Machine.new(@klass, :state_id, :as =&gt; 'state')
+    @machine = StateMachine::Machine.new(@klass, :state, :attribute =&gt; :state_id)
     @machine.state :off, :value =&gt; 1
     @machine.state :active, :value =&gt; 2
     @machine.event :activate</diff>
      <filename>test/unit/transition_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>77a11b85e35a35ee679bf079d831772f519b14b1</id>
    </parent>
  </parents>
  <author>
    <name>Aaron Pfeifer</name>
    <email>aaron.pfeifer@gmail.com</email>
  </author>
  <url>http://github.com/pluginaweek/state_machine/commit/5f8cd2f9c25044f9df716be3818e3a146f7c0a24</url>
  <id>5f8cd2f9c25044f9df716be3818e3a146f7c0a24</id>
  <committed-date>2009-06-14T10:31:45-07:00</committed-date>
  <authored-date>2009-06-14T10:31:45-07:00</authored-date>
  <message>Use :attribute to customize the attribute target and remove :as, assuming the name is the first argument of #state_machine
Allow multiple state machines on the same class to target the same attribute</message>
  <tree>2706667debddea8dd8f6b373e44f2c20134b01e3</tree>
  <committer>
    <name>Aaron Pfeifer</name>
    <email>aaron.pfeifer@gmail.com</email>
  </committer>
</commit>
