event

Overridden event methods won't get invoked when using attribute-based event transitions

Instance methods

The following instance methods are generated when a new event is defined (Event park is used as an example):

park(..., run_action = true)

Fires the :park event, transitioning from the current state to the next valid state. If the last argument is a boolean, it will control whether the machine's action gets run.

park!(..., run_action = true)

Fires the :park event, transitioning from the current state to the next valid state. If the transition fails, then a StateMachines::InvalidTransition error will be raised. If the last argument is a boolean, it will control whether the machine's action gets run.

can_park?(requirements = {})

Checks whether the :park event can be fired given the current state of the object. This will not run validations or callbacks in ORM integrations. It will only determine if the state machine defines a valid transition for the event. To check whether an event can fire and passes validations, use event attributes (e.g. state_event) as described in the "Events" documentation of each ORM integration.

park_transition(requirements = {})

Gets the next transition that would be performed if the :park event were to be fired now on the object or nil if no transitions can be performed. Like can_park? this will also not run validations or callbacks. It will only determine if the state machine defines a valid transition for the event.

With a namespace of "car", the above names map to the following methods:

  • can_park_car?
  • park_car_transition
  • park_car
  • park_car!

The can_park? and park_transition helpers both take an optional set of requirements for determining what transitions are available for the current object. These requirements include:

  • :from - One or more states to transition from. If none are specified, then this will be the object's current state.
  • :to - One or more states to transition to. If none are specified, then this will match any to state.
  • :guard - Whether to guard transitions with the if/unless conditionals defined for each one. Default is true.

Defining Additional Arguments

  • Additional arguments can be passed into events and accessed by transition hooks:

    class Vehicle
      state_machine do
        after_transition :on => :park do |vehicle, transition|
          kind = *transition.args # :parallel
          ...
        end
        after_transition :on => :park, :do => :take_deep_breath
    
        event :park do
          ...
        end
    
        def take_deep_breath(transition)
          kind = *transition.args # :parallel
          ...
        end
      end
    end
    
    vehicle = Vehicle.new
    vehicle.park(:parallel)
    
  • If the last argument is a boolean, it will be used as the run_action parameter to the event action. Using the park action example from above, you can might call it like so:

    vehicle.park                    # => Uses default args and runs machine action
    vehicle.park(:parallel)         # => Specifies the `kind` argument and runs the machine action
    vehicle.park(:parallel, false)  # => Specifies the `kind` argument and *skips* the machine action
    

    If you decide to override the park event method and define additional arguments, you can do so as shown below:

    class Vehicle
      state_machine do
        event :park do
          ...
        end
      end
    
      def park(kind = :parallel, *args)
        take_deep_breath if kind ### :parallel
        super
      end
    end
    
  • super is called instead of super(*args) to allow the entire arguments list to be accessed by transition callbacks through StateMachines::Transition#args

Overriding Default Method

Although before_transition, after_transition, and around_transition hooks allow you to define to be executed as a result of the event's transition, you can also override the event main method in order to have a little more fine-grained control.

  class Vehicle
    state_machine do
      event :park do
        ...
      end
    end

    def park(*)
      take_deep_breath  # Executes before the transition (and before_transition hooks) even if no transition is possible
      if result = super # Runs the transition and all before/after/around hooks
        applaud         # Executes after the transition (and after_transition hooks)
      end
      result
    end
  end

Note:

  • The method signature is defined with an unlimited argument list in order to allow callers to continue passing arguments that are expected by state_machine. For example, it will still allow calls to park with a single parameter for skipping the configured action.
  • The overridden event method must call super in order to run the logic for running the next possible transition. In order to remain consistent with other events, the result of super is returned.
  • Any behavior defined in this method will not get executed if you're taking advantage of attribute-based event transitions. For example:

    vehicle = Vehicle.new
    vehicle.state_event = 'park'
    vehicle.save
    

    In this case, :park event will run before/after/around transition hooks and transition the state, but the behavior defined in the overriden park method will not be executed.

results matching ""

    No results matching ""