module StateMachine::InstanceMethods
Public Instance Methods
Runs one or more events in parallel. All events will run through the following steps:
-
Before callbacks
-
Persist state
-
Invoke action
-
After callbacks
For example, if two events (for state machines A and B) are run in parallel, the order in which steps are run is:
-
A - Before transition callbacks
-
B - Before transition callbacks
-
A - Persist new state
-
B - Persist new state
-
A - Invoke action
-
B - Invoke action (only if different than A's action)
-
A - After transition callbacks
-
B - After transition callbacks
Note that multiple events on the same state machine / attribute cannot be run in parallel. If this is attempted, an ArgumentError will be raised.
Halting callbacks¶ ↑
When running multiple events in parallel, special consideration should be taken with regard to how halting within callbacks affects the flow.
For before callbacks, any :halt
error that's thrown will immediately cancel the perform for all transitions. As a result, it's possible for one event's transition to affect the continuation of another.
On the other hand, any :halt
error that's thrown within an after callback with only affect that event's transition. Other transitions will continue to run their own callbacks.
Example¶ ↑
class Vehicle state_machine :initial => :parked do event :ignite do transition :parked => :idling end event :park do transition :idling => :parked end end state_machine :alarm_state, :namespace => 'alarm', :initial => :on do event :enable do transition all => :active end event :disable do transition all => :off end end end vehicle = Vehicle.new # => #<Vehicle:0xb7c02850 @state="parked", @alarm_state="active"> vehicle.state # => "parked" vehicle.alarm_state # => "active" vehicle.fire_events(:ignite, :disable_alarm) # => true vehicle.state # => "idling" vehicle.alarm_state # => "off" # If any event fails, the entire event chain fails vehicle.fire_events(:ignite, :enable_alarm) # => false vehicle.state # => "idling" vehicle.alarm_state # => "off" # Exception raised on invalid event vehicle.fire_events(:park, :invalid) # => StateMachine::InvalidEvent: :invalid is an unknown event vehicle.state # => "idling" vehicle.alarm_state # => "off"
# File lib/state_machine/extensions.rb 102 def fire_events(*events) 103 self.class.state_machines.fire_events(self, *events) 104 end
Run one or more events in parallel. If any event fails to run, then a StateMachine::InvalidTransition
exception will be raised.
See StateMachine::InstanceMethods#fire_events
for more information.
Example¶ ↑
class Vehicle state_machine :initial => :parked do event :ignite do transition :parked => :idling end event :park do transition :idling => :parked end end state_machine :alarm_state, :namespace => 'alarm', :initial => :active do event :enable do transition all => :active end event :disable do transition all => :off end end end vehicle = Vehicle.new # => #<Vehicle:0xb7c02850 @state="parked", @alarm_state="active"> vehicle.fire_events(:ignite, :disable_alarm) # => true vehicle.fire_events!(:ignite, :disable_alarm) # => StateMachine::InvalidTranstion: Cannot run events in parallel: ignite, disable_alarm
# File lib/state_machine/extensions.rb 139 def fire_events!(*events) 140 run_action = [true, false].include?(events.last) ? events.pop : true 141 fire_events(*(events + [run_action])) || raise(StateMachine::InvalidParallelTransition.new(self, events)) 142 end