Class: StateMachine::Transition
- Inherits:
-
Object
- Object
- StateMachine::Transition
- Defined in:
- lib/state_machine/transition.rb
Overview
A transition represents a state change for a specific attribute.
Transitions consist of:
-
An event
-
A starting state
-
An ending state
Instance Attribute Summary collapse
-
#args ⇒ Object
The arguments passed in to the event that triggered the transition (does not include the
run_action
boolean argument if specified). -
#from ⇒ Object
readonly
The original state value before the transition.
-
#machine ⇒ Object
readonly
The state machine for which this transition is defined.
-
#object ⇒ Object
readonly
The object being transitioned.
-
#result ⇒ Object
readonly
The result of invoking the action associated with the machine.
-
#to ⇒ Object
readonly
The new state value after the transition.
-
#transient ⇒ Object
writeonly
Whether the transition is only existing temporarily for the object.
Class Method Summary collapse
-
.pause_supported? ⇒ Boolean
Determines whether the curreny ruby implementation supports pausing and resuming transitions.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Determines equality of transitions by testing whether the object, states, and event involved in the transition are equal.
-
#action ⇒ Object
The action that will be run when this transition is performed.
-
#attribute ⇒ Object
The attribute which this transition’s machine is defined for.
-
#attributes ⇒ Object
A hash of all the core attributes defined for this transition with their names as keys and values of the attributes as values.
-
#event ⇒ Object
The event that triggered the transition.
-
#from_name ⇒ Object
The state name before the transition.
-
#human_event ⇒ Object
The human-readable name of the event that triggered the transition.
-
#human_from_name ⇒ Object
The human-readable state name before the transition.
-
#human_to_name ⇒ Object
The new human-readable state name after the transition.
-
#initialize(object, machine, event, from_name, to_name, read_state = true) ⇒ Transition
constructor
Creates a new, specific transition.
-
#inspect ⇒ Object
Generates a nicely formatted description of this transitions’s contents.
-
#loopback? ⇒ Boolean
Does this transition represent a loopback (i.e. the from and to state are the same).
-
#perform(*args) ⇒ Object
Runs the actual transition and any before/after callbacks associated with the transition.
-
#persist ⇒ Object
Transitions the current value of the state to that specified by the transition.
-
#qualified_event ⇒ Object
The fully-qualified name of the event that triggered the transition.
-
#qualified_from_name ⇒ Object
The fully-qualified state name before the transition.
-
#qualified_to_name ⇒ Object
The new fully-qualified state name after the transition.
-
#reset ⇒ Object
Resets any tracking of which callbacks have already been run and whether the state has already been persisted.
-
#rollback ⇒ Object
Rolls back changes made to the object’s state via this transition.
-
#run_callbacks(options = {}, &block) ⇒ Object
Runs the before / after callbacks for this transition.
-
#to_name ⇒ Object
The new state name after the transition.
-
#transient? ⇒ Boolean
Is this transition existing for a short period only? If this is set, it indicates that the transition (or the event backing it) should not be written to the object if it fails.
-
#within_transaction ⇒ Object
Runs a block within a transaction for the object being transitioned.
Constructor Details
#initialize(object, machine, event, from_name, to_name, read_state = true) ⇒ Transition
Creates a new, specific transition
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/state_machine/transition.rb', line 94 def initialize(object, machine, event, from_name, to_name, read_state = true) #:nodoc: @object = object @machine = machine @args = [] @transient = false @resume_block = nil @event = machine.events.fetch(event) @from_state = machine.states.fetch(from_name) @from = read_state ? machine.read(object, :state) : @from_state.value @to_state = machine.states.fetch(to_name) @to = @to_state.value reset end |
Instance Attribute Details
#args ⇒ Object
The arguments passed in to the event that triggered the transition (does not include the run_action
boolean argument if specified)
79 80 81 |
# File 'lib/state_machine/transition.rb', line 79 def args @args end |
#from ⇒ Object (readonly)
The original state value before the transition
72 73 74 |
# File 'lib/state_machine/transition.rb', line 72 def from @from end |
#machine ⇒ Object (readonly)
The state machine for which this transition is defined
69 70 71 |
# File 'lib/state_machine/transition.rb', line 69 def machine @machine end |
#object ⇒ Object (readonly)
The object being transitioned
66 67 68 |
# File 'lib/state_machine/transition.rb', line 66 def object @object end |
#result ⇒ Object (readonly)
The result of invoking the action associated with the machine
82 83 84 |
# File 'lib/state_machine/transition.rb', line 82 def result @result end |
#to ⇒ Object (readonly)
The new state value after the transition
75 76 77 |
# File 'lib/state_machine/transition.rb', line 75 def to @to end |
#transient=(value) ⇒ Object (writeonly)
Whether the transition is only existing temporarily for the object
85 86 87 |
# File 'lib/state_machine/transition.rb', line 85 def transient=(value) @transient = value end |
Class Method Details
.pause_supported? ⇒ Boolean
Determines whether the curreny ruby implementation supports pausing and resuming transitions
89 90 91 |
# File 'lib/state_machine/transition.rb', line 89 def self.pause_supported? !defined?(RUBY_ENGINE) || %w(ruby maglev).include?(RUBY_ENGINE) end |
Instance Method Details
#==(other) ⇒ Object
Determines equality of transitions by testing whether the object, states, and event involved in the transition are equal
320 321 322 323 324 325 326 327 |
# File 'lib/state_machine/transition.rb', line 320 def ==(other) other.instance_of?(self.class) && other.object == object && other.machine == machine && other.from_name == from_name && other.to_name == to_name && other.event == event end |
#action ⇒ Object
The action that will be run when this transition is performed
116 117 118 |
# File 'lib/state_machine/transition.rb', line 116 def action machine.action end |
#attribute ⇒ Object
The attribute which this transition’s machine is defined for
111 112 113 |
# File 'lib/state_machine/transition.rb', line 111 def attribute machine.attribute end |
#attributes ⇒ Object
A hash of all the core attributes defined for this transition with their names as keys and values of the attributes as values.
Example
machine = StateMachine.new(Vehicle)
transition = StateMachine::Transition.new(Vehicle.new, machine, :ignite, :parked, :idling)
transition.attributes # => {:object => #<Vehicle:0xb7d60ea4>, :attribute => :state, :event => :ignite, :from => 'parked', :to => 'idling'}
192 193 194 |
# File 'lib/state_machine/transition.rb', line 192 def attributes @attributes ||= {:object => object, :attribute => attribute, :event => event, :from => from, :to => to} end |
#event ⇒ Object
The event that triggered the transition
121 122 123 |
# File 'lib/state_machine/transition.rb', line 121 def event @event.name end |
#from_name ⇒ Object
The state name before the transition
136 137 138 |
# File 'lib/state_machine/transition.rb', line 136 def from_name @from_state.name end |
#human_event ⇒ Object
The human-readable name of the event that triggered the transition
131 132 133 |
# File 'lib/state_machine/transition.rb', line 131 def human_event @event.human_name(@object.class) end |
#human_from_name ⇒ Object
The human-readable state name before the transition
146 147 148 |
# File 'lib/state_machine/transition.rb', line 146 def human_from_name @from_state.human_name(@object.class) end |
#human_to_name ⇒ Object
The new human-readable state name after the transition
161 162 163 |
# File 'lib/state_machine/transition.rb', line 161 def human_to_name @to_state.human_name(@object.class) end |
#inspect ⇒ Object
Generates a nicely formatted description of this transitions’s contents.
For example,
transition = StateMachine::Transition.new(object, machine, :ignite, :parked, :idling)
transition # => #<StateMachine::Transition attribute=:state event=:ignite from="parked" from_name=:parked to="idling" to_name=:idling>
335 336 337 |
# File 'lib/state_machine/transition.rb', line 335 def inspect "#<#{self.class} #{%w(attribute event from from_name to to_name).map {|attr| "#{attr}=#{send(attr).inspect}"} * ' '}>" end |
#loopback? ⇒ Boolean
Does this transition represent a loopback (i.e. the from and to state are the same)
Example
machine = StateMachine.new(Vehicle)
StateMachine::Transition.new(Vehicle.new, machine, :park, :parked, :parked).loopback? # => true
StateMachine::Transition.new(Vehicle.new, machine, :park, :idling, :parked).loopback? # => false
173 174 175 |
# File 'lib/state_machine/transition.rb', line 173 def loopback? from_name == to_name end |
#perform(*args) ⇒ Object
Runs the actual transition and any before/after callbacks associated with the transition. The action associated with the transition/machine can be skipped by passing in false
.
Examples
class Vehicle
state_machine :action => :save do
...
end
end
vehicle = Vehicle.new
transition = StateMachine::Transition.new(vehicle, machine, :ignite, :parked, :idling)
transition.perform # => Runs the +save+ action after setting the state attribute
transition.perform(false) # => Only sets the state attribute
transition.perform(Time.now) # => Passes in additional arguments and runs the +save+ action
transition.perform(Time.now, false) # => Passes in additional arguments and only sets the state attribute
214 215 216 217 218 219 220 |
# File 'lib/state_machine/transition.rb', line 214 def perform(*args) run_action = [true, false].include?(args.last) ? args.pop : true self.args = args # Run the transition !!TransitionCollection.new([self], :actions => run_action).perform end |
#persist ⇒ Object
Transitions the current value of the state to that specified by the transition. Once the state is persisted, it cannot be persisted again until this transition is reset.
Example
class Vehicle
state_machine do
event :ignite do
transition :parked => :idling
end
end
end
vehicle = Vehicle.new
transition = StateMachine::Transition.new(vehicle, Vehicle.state_machine, :ignite, :parked, :idling)
transition.persist
vehicle.state # => 'idling'
275 276 277 278 279 280 |
# File 'lib/state_machine/transition.rb', line 275 def persist unless @persisted machine.write(object, :state, to) @persisted = true end end |
#qualified_event ⇒ Object
The fully-qualified name of the event that triggered the transition
126 127 128 |
# File 'lib/state_machine/transition.rb', line 126 def qualified_event @event.qualified_name end |
#qualified_from_name ⇒ Object
The fully-qualified state name before the transition
141 142 143 |
# File 'lib/state_machine/transition.rb', line 141 def qualified_from_name @from_state.qualified_name end |
#qualified_to_name ⇒ Object
The new fully-qualified state name after the transition
156 157 158 |
# File 'lib/state_machine/transition.rb', line 156 def qualified_to_name @to_state.qualified_name end |
#reset ⇒ Object
Resets any tracking of which callbacks have already been run and whether the state has already been persisted
313 314 315 316 |
# File 'lib/state_machine/transition.rb', line 313 def reset @before_run = @persisted = @after_run = false @paused_block = nil end |
#rollback ⇒ Object
Rolls back changes made to the object’s state via this transition. This will revert the state back to the from
value.
Example
class Vehicle
state_machine :initial => :parked do
event :ignite do
transition :parked => :idling
end
end
end
vehicle = Vehicle.new # => #<Vehicle:0xb7b7f568 @state="parked">
transition = StateMachine::Transition.new(vehicle, Vehicle.state_machine, :ignite, :parked, :idling)
# Persist the new state
vehicle.state # => "parked"
transition.persist
vehicle.state # => "idling"
# Roll back to the original state
transition.rollback
vehicle.state # => "parked"
306 307 308 309 |
# File 'lib/state_machine/transition.rb', line 306 def rollback reset machine.write(object, :state, from) end |
#run_callbacks(options = {}, &block) ⇒ Object
Runs the before / after callbacks for this transition. If a block is provided, then it will be executed between the before and after callbacks.
Configuration options:
-
before
- Whether to run before callbacks. -
after
- Whether to run after callbacks. If false, then any around callbacks will be paused until called again withafter
enabled. Default is true.
This will return true if all before callbacks gets executed. After callbacks will not have an effect on the result.
242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/state_machine/transition.rb', line 242 def run_callbacks( = {}, &block) = {:before => true, :after => true}.merge() @success = false halted = pausable { before([:after], &block) } if [:before] # After callbacks are only run if: # * An around callback didn't halt after yielding # * They're enabled or the run didn't succeed after if !(@before_run && halted) && ([:after] || !@success) @before_run end |
#to_name ⇒ Object
The new state name after the transition
151 152 153 |
# File 'lib/state_machine/transition.rb', line 151 def to_name @to_state.name end |
#transient? ⇒ Boolean
Is this transition existing for a short period only? If this is set, it indicates that the transition (or the event backing it) should not be written to the object if it fails.
180 181 182 |
# File 'lib/state_machine/transition.rb', line 180 def transient? @transient end |
#within_transaction ⇒ Object
Runs a block within a transaction for the object being transitioned. By default, transactions are a no-op unless otherwise defined by the machine’s integration.
225 226 227 228 229 |
# File 'lib/state_machine/transition.rb', line 225 def within_transaction machine.within_transaction(object) do yield end end |