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 thepark
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 ofsuper(*args)
to allow the entire arguments list to be accessed by transition callbacks throughStateMachines::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 ofsuper
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 overridenpark
method will not be executed.