# File lib/state_machine/machine_collection.rb, line 110
    def fire_event_attributes(object, action, complete = true)
      # Get the transitions to fire for each applicable machine
      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)
      action_value = nil
      
      # Make sure all events were valid
      if result = transitions.all? {|transition| transition != false}
        begin
          result = Transition.perform(transitions, :after => complete) do
            # Prevent events from being evaluated multiple times if actions are nested
            transitions.each {|transition| transition.machine.write(object, :event, nil)}
            action_value = yield
          end
        rescue Exception
          # Revert object modifications
          transitions.each do |transition|
            transition.machine.write(object, :event, transition.event)
            transition.machine.write(object, :event_transition, nil) if complete
          end
          
          raise
        end
        
        transitions.each do |transition|
          # Revert event unless transition was successful
          transition.machine.write(object, :event, transition.event) unless complete && result
          
          # Track transition if partial transition completed successfully
          transition.machine.write(object, :event_transition, !complete && result ? transition : nil)
        end
      end
      
      action_value.nil? ? result : action_value
    end