Class StateMachine::Transition
In: lib/state_machine/transition.rb
Parent: Object

A transition represents a state change for a specific attribute.

Transitions consist of:

  • An event
  • A starting state
  • An ending state

Methods

Attributes

args  [RW]  The arguments passed in to the event that triggered the transition (does not include the run_action boolean argument if specified)
from  [R]  The original state value before the transition
machine  [R]  The state machine for which this transition is defined
object  [R]  The object being transitioned
result  [R]  The result of invoking the action associated with the machine
to  [R]  The new state value after the transition
transient  [W]  Whether the transition is only existing temporarily for the object

Public Instance methods

Determines equality of transitions by testing whether the object, states, and event involved in the transition are equal

[Source]

     # File lib/state_machine/transition.rb, line 310
310:     def ==(other)
311:       other.instance_of?(self.class) &&
312:       other.object == object &&
313:       other.machine == machine &&
314:       other.from_name == from_name &&
315:       other.to_name == to_name &&
316:       other.event == event
317:     end

The action that will be run when this transition is performed

[Source]

     # File lib/state_machine/transition.rb, line 106
106:     def action
107:       machine.action
108:     end

The attribute which this transition‘s machine is defined for

[Source]

     # File lib/state_machine/transition.rb, line 101
101:     def attribute
102:       machine.attribute
103:     end

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'}

[Source]

     # File lib/state_machine/transition.rb, line 182
182:     def attributes
183:       @attributes ||= {:object => object, :attribute => attribute, :event => event, :from => from, :to => to}
184:     end

The event that triggered the transition

[Source]

     # File lib/state_machine/transition.rb, line 111
111:     def event
112:       @event.name
113:     end

The state name before the transition

[Source]

     # File lib/state_machine/transition.rb, line 126
126:     def from_name
127:       @from_state.name
128:     end

The human-readable name of the event that triggered the transition

[Source]

     # File lib/state_machine/transition.rb, line 121
121:     def human_event
122:       @event.human_name(@object.class)
123:     end

The human-readable state name before the transition

[Source]

     # File lib/state_machine/transition.rb, line 136
136:     def human_from_name
137:       @from_state.human_name(@object.class)
138:     end

The new human-readable state name after the transition

[Source]

     # File lib/state_machine/transition.rb, line 151
151:     def human_to_name
152:       @to_state.human_name(@object.class)
153:     end

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>

[Source]

     # File lib/state_machine/transition.rb, line 325
325:     def inspect
326:       "#<#{self.class} #{%w(attribute event from from_name to to_name).map {|attr| "#{attr}=#{send(attr).inspect}"} * ' '}>"
327:     end

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

[Source]

     # File lib/state_machine/transition.rb, line 163
163:     def loopback?
164:       from_name == to_name
165:     end

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

[Source]

     # File lib/state_machine/transition.rb, line 204
204:     def perform(*args)
205:       run_action = [true, false].include?(args.last) ? args.pop : true
206:       self.args = args
207:       
208:       # Run the transition
209:       !!TransitionCollection.new([self], :actions => run_action).perform
210:     end

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'

[Source]

     # File lib/state_machine/transition.rb, line 265
265:     def persist
266:       unless @persisted
267:         machine.write(object, :state, to)
268:         @persisted = true
269:       end
270:     end

The fully-qualified name of the event that triggered the transition

[Source]

     # File lib/state_machine/transition.rb, line 116
116:     def qualified_event
117:       @event.qualified_name
118:     end

The fully-qualified state name before the transition

[Source]

     # File lib/state_machine/transition.rb, line 131
131:     def qualified_from_name
132:       @from_state.qualified_name
133:     end

The new fully-qualified state name after the transition

[Source]

     # File lib/state_machine/transition.rb, line 146
146:     def qualified_to_name
147:       @to_state.qualified_name
148:     end

Resets any tracking of which callbacks have already been run and whether the state has already been persisted

[Source]

     # File lib/state_machine/transition.rb, line 303
303:     def reset
304:       @before_run = @persisted = @after_run = false
305:       @paused_block = nil
306:     end

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"

[Source]

     # File lib/state_machine/transition.rb, line 296
296:     def rollback
297:       reset
298:       machine.write(object, :state, from)
299:     end

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 with after enabled. Default is true.

This will return true if all before callbacks gets executed. After callbacks will not have an effect on the result.

[Source]

     # File lib/state_machine/transition.rb, line 232
232:     def run_callbacks(options = {}, &block)
233:       options = {:before => true, :after => true}.merge(options)
234:       @success = false
235:       
236:       halted = pausable { before(options[:after], &block) } if options[:before]
237:       
238:       # After callbacks are only run if:
239:       # * An around callback didn't halt after yielding
240:       # * They're enabled or the run didn't succeed
241:       after if !(@before_run && halted) && (options[:after] || !@success)
242:       
243:       @before_run
244:     end

The new state name after the transition

[Source]

     # File lib/state_machine/transition.rb, line 141
141:     def to_name
142:       @to_state.name
143:     end

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.

[Source]

     # File lib/state_machine/transition.rb, line 170
170:     def transient?
171:       @transient
172:     end

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.

[Source]

     # File lib/state_machine/transition.rb, line 215
215:     def within_transaction
216:       machine.within_transaction(object) do
217:         yield
218:       end
219:     end

[Validate]