def before_transition(*args, &block)
      options = (args.last.is_a?(Hash) ? args.pop : {})
      options[:do] = args if args.any?
      add_callback(:before, options, &block)
    end
def before_transition(*args, &block)
      options = (args.last.is_a?(Hash) ? args.pop : {})
      options[:do] = args if args.any?
      add_callback(:before, options, &block)
    end
Creates a callback that will be invoked *before* a transition is
 performed so long as the given requirements match the transition.

 == The callback

 Callbacks must be defined as either an argument, in the :do option, or
 as a block.  For example,

   class Vehicle
     state_machine do
       before_transition :set_alarm
       before_transition :set_alarm, all => :parked
       before_transition all => :parked, :do => :set_alarm
       before_transition all => :parked do |vehicle, transition|
         vehicle.set_alarm
       end
       ...
     end
   end

 Notice that the first three callbacks are the same in terms of how the
 methods to invoke are defined.  However, using the <tt>:do</tt> can
 provide for a more fluid DSL.

 In addition, multiple callbacks can be defined like so:

   class Vehicle
     state_machine do
       before_transition :set_alarm, :lock_doors, all => :parked
       before_transition all => :parked, :do => [:set_alarm, :lock_doors]
       before_transition :set_alarm do |vehicle, transition|
         vehicle.lock_doors
       end
     end
   end

 Notice that the different ways of configuring methods can be mixed.

 == State requirements

 Callbacks can require that the machine be transitioning from and to
 specific states.  These requirements use a Hash syntax to map beginning
 states to ending states.  For example,

   before_transition :parked => :idling, :idling => :first_gear, :do => :set_alarm

 In this case, the +set_alarm+ callback will only be called if the machine
 is transitioning from +parked+ to +idling+ or from +idling+ to +parked+.

 To help define state requirements, a set of helpers are available for
 slightly more complex matching:
 * <tt>all</tt> - Matches every state/event in the machine
 * <tt>all - [:parked, :idling, ...]</tt> - Matches every state/event except those specified
 * <tt>any</tt> - An alias for +all+ (matches every state/event in the machine)
 * <tt>same</tt> - Matches the same state being transitioned from

 See StateMachines::MatcherHelpers for more information.

 Examples:

   before_transition :parked => [:idling, :first_gear], :do => ...     # Matches from parked to idling or first_gear
   before_transition all - [:parked, :idling] => :idling, :do => ...   # Matches from every state except parked and idling to idling
   before_transition all => :parked, :do => ...                        # Matches all states to parked
   before_transition any => same, :do => ...                           # Matches every loopback

 == Event requirements

 In addition to state requirements, an event requirement can be defined so
 that the callback is only invoked on specific events using the +on+
 option.  This can also use the same matcher helpers as the state
 requirements.

 Examples:

   before_transition :on => :ignite, :do => ...                        # Matches only on ignite
   before_transition :on => all - :ignite, :do => ...                  # Matches on every event except ignite
   before_transition :parked => :idling, :on => :ignite, :do => ...    # Matches from parked to idling on ignite

 == Verbose Requirements

 Requirements can also be defined using verbose options rather than the
 implicit Hash syntax and helper methods described above.

 Configuration options:
 * <tt>:from</tt> - One or more states being transitioned from.  If none
   are specified, then all states will match.
 * <tt>:to</tt> - One or more states being transitioned to.  If none are
   specified, then all states will match.
 * <tt>:on</tt> - One or more events that fired the transition.  If none
   are specified, then all events will match.
 * <tt>:except_from</tt> - One or more states *not* being transitioned from
 * <tt>:except_to</tt> - One more states *not* being transitioned to
 * <tt>:except_on</tt> - One or more events that *did not* fire the transition

 Examples:

   before_transition :from => :ignite, :to => :idling, :on => :park, :do => ...
   before_transition :except_from => :ignite, :except_to => :idling, :except_on => :park, :do => ...

 == Conditions

 In addition to the state/event requirements, a condition can also be
 defined to help determine whether the callback should be invoked.

 Configuration options:
 * <tt>:if</tt> - A method, proc or string to call to determine if the
   callback should occur (e.g. :if => :allow_callbacks, or
   :if => lambda {|user| user.signup_step > 2}). The method, proc or string
   should return or evaluate to a true or false value.
 * <tt>:unless</tt> - A method, proc or string to call to determine if the
   callback should not occur (e.g. :unless => :skip_callbacks, or
   :unless => lambda {|user| user.signup_step <= 2}). The method, proc or
   string should return or evaluate to a true or false value.

 Examples:

   before_transition :parked => :idling, :if => :moving?, :do => ...
   before_transition :on => :ignite, :unless => :seatbelt_on?, :do => ...

 == Accessing the transition

 In addition to passing the object being transitioned, the actual
 transition describing the context (e.g. event, from, to) can be accessed
 as well.  This additional argument is only passed if the callback allows
 for it.

 For example,

   class Vehicle
     # Only specifies one parameter (the object being transitioned)
     before_transition all => :parked do |vehicle|
       vehicle.set_alarm
     end

     # Specifies 2 parameters (object being transitioned and actual transition)
     before_transition all => :parked do |vehicle, transition|
       vehicle.set_alarm(transition)
     end
   end

 *Note* that the object in the callback will only be passed in as an
 argument if callbacks are configured to *not* be bound to the object
 involved.  This is the default and may change on a per-integration basis.

 See StateMachines::Transition for more information about the
 attributes available on the transition.

 == Usage with delegates

 As noted above, state_machine uses the callback method's argument list
 arity to determine whether to include the transition in the method call.
 If you're using delegates, such as those defined in ActiveSupport or
 Forwardable, the actual arity of the delegated method gets masked.  This
 means that callbacks which reference delegates will always get passed the
 transition as an argument.  For example:

   class Vehicle
     extend Forwardable
     delegate :refresh => :dashboard

     state_machine do
       before_transition :refresh
       ...
     end

     def dashboard
       @dashboard ||= Dashboard.new
     end
   end

   class Dashboard
     def refresh(transition)
       # ...
     end
   end

 In the above example, <tt>Dashboard#refresh</tt> *must* defined a
 +transition+ argument.  Otherwise, an +ArgumentError+ exception will get
 raised.  The only way around this is to avoid the use of delegates and
 manually define the delegate method so that the correct arity is used.

 == Examples

 Below is an example of a class with one state machine and various types
 of +before+ transitions defined for it:

   class Vehicle
     state_machine do
       # Before all transitions
       before_transition :update_dashboard

       # Before specific transition:
       before_transition [:first_gear, :idling] => :parked, :on => :park, :do => :take_off_seatbelt

       # With conditional callback:
       before_transition all => :parked, :do => :take_off_seatbelt, :if => :seatbelt_on?

       # Using helpers:
       before_transition all - :stalled => same, :on => any - :crash, :do => :update_dashboard
       ...
     end
   end

 As can be seen, any number of transitions can be created using various
 combinations of configuration options.