class EnumStateMachine::TransitionCollection

Represents a collection of transitions in a state machine

Attributes

skip_actions[R]

Whether to skip running the action for each transition's machine

skip_after[R]

Whether to skip running the after callbacks

use_transaction[R]

Whether transitions should wrapped around a transaction block

Public Class Methods

new(transitions = [], options = {}) click to toggle source

Creates a new collection of transitions that can be run in parallel. Each transition must be for a different attribute.

Configuration options:

  • :actions - Whether to run the action configured for each transition

  • :after - Whether to run after callbacks

  • :transaction - Whether to wrap transitions within a transaction

Calls superclass method
   # File lib/enum_state_machine/transition_collection.rb
22 def initialize(transitions = [], options = {})
23   super(transitions)
24   
25   # Determine the validity of the transitions as a whole
26   @valid = all?
27   reject! {|transition| !transition}
28   
29   attributes = map {|transition| transition.attribute}.uniq
30   raise ArgumentError, 'Cannot perform multiple transitions in parallel for the same state machine attribute' if attributes.length != length
31   
32   assert_valid_keys(options, :actions, :after, :transaction)
33   options = {:actions => true, :after => true, :transaction => true}.merge(options)
34   @skip_actions = !options[:actions]
35   @skip_after = !options[:after]
36   @use_transaction = options[:transaction]
37 end

Public Instance Methods

perform(&block) click to toggle source

Runs each of the collection's transitions in parallel.

All transitions will run through the following steps:

  1. Before callbacks

  2. Persist state

  3. Invoke action

  4. After callbacks (if configured)

  5. Rollback (if action is unsuccessful)

If a block is passed to this method, that block will be called instead of invoking each transition's action.

   # File lib/enum_state_machine/transition_collection.rb
50 def perform(&block)
51   reset
52   
53   if valid?
54     if use_event_attributes? && !block_given?
55       each do |transition|
56         transition.transient = true
57         transition.machine.write(object, :event_transition, transition)
58       end
59       
60       run_actions
61     else
62       within_transaction do
63         catch(:halt) { run_callbacks(&block) }
64         rollback unless success?
65       end
66     end
67   end
68   
69   if actions.length == 1 && results.include?(actions.first)
70     results[actions.first]
71   else
72     success?
73   end
74 end

Private Instance Methods

actions() click to toggle source

Gets the list of actions to run. If configured to skip actions, then this will return an empty collection.

    # File lib/enum_state_machine/transition_collection.rb
102 def actions
103   empty? ? [nil] : map {|transition| transition.action}.uniq
104 end
catch_exceptions() { || ... } click to toggle source

Wraps the given block with a rescue handler so that any exceptions that occur will automatically result in the transition rolling back any changes that were made to the object involved.

    # File lib/enum_state_machine/transition_collection.rb
168 def catch_exceptions
169   begin
170     yield
171   rescue Exception
172     rollback
173     raise
174   end
175 end
object() click to toggle source

Gets the object being transitioned

   # File lib/enum_state_machine/transition_collection.rb
96 def object
97   first.object
98 end
persist() click to toggle source

Transitions the current value of the object's states to those specified by each transition

    # File lib/enum_state_machine/transition_collection.rb
139 def persist
140   each {|transition| transition.persist}
141 end
reset() click to toggle source

Resets any information tracked from previous attempts to perform the collection

    # File lib/enum_state_machine/transition_collection.rb
115 def reset
116   @results = {}
117   @success = false
118 end
rollback() click to toggle source

Rolls back changes made to the object's states via each transition

    # File lib/enum_state_machine/transition_collection.rb
161 def rollback
162   each {|transition| transition.rollback}
163 end
run_actions() { || ... } click to toggle source

Runs the actions for each transition. If a block is given method, then it will be called instead of invoking each transition's action.

The results of the actions will be used to determine success?.

    # File lib/enum_state_machine/transition_collection.rb
147 def run_actions
148   catch_exceptions do
149     @success = if block_given?
150       result = yield
151       actions.each {|action| results[action] = result}
152       !!result
153     else
154       actions.compact.each {|action| !skip_actions && results[action] = object.send(action)}
155       results.values.all?
156     end
157   end
158 end
run_callbacks(index = 0, &block) click to toggle source

Runs each transition's callbacks recursively. Once all before callbacks have been executed, the transitions will then be persisted and the configured actions will be run.

If any transition fails to run its callbacks, :halt will be thrown.

    # File lib/enum_state_machine/transition_collection.rb
125 def run_callbacks(index = 0, &block)
126   if transition = self[index]
127     throw :halt unless transition.run_callbacks(:after => !skip_after) do
128       run_callbacks(index + 1, &block)
129       {:result => results[transition.action], :success => success?}
130     end
131   else
132     persist
133     run_actions(&block)
134   end
135 end
success?() click to toggle source

Did each transition perform successfully? This will only be true if the following requirements are met:

  • No before callbacks halt

  • All actions run successfully (always true if skipping actions)

   # File lib/enum_state_machine/transition_collection.rb
91 def success?
92   @success
93 end
use_event_attributes?() click to toggle source

Determines whether an event attribute be used to trigger the transitions in this collection or whether the transitions be run directly outside of the action.

    # File lib/enum_state_machine/transition_collection.rb
109 def use_event_attributes?
110   !skip_actions && !skip_after && actions.all? && actions.length == 1 && first.machine.action_hook?
111 end
valid?() click to toggle source

Is this a valid set of transitions? If the collection was creating with any false values for transitions, then the the collection will be marked as invalid.

   # File lib/enum_state_machine/transition_collection.rb
83 def valid?
84   @valid
85 end
within_transaction() { || ... } click to toggle source

Runs a block within a transaction for the object being transitioned. If transactions are disabled, then this is a no-op.

    # File lib/enum_state_machine/transition_collection.rb
179 def within_transaction
180   if use_transaction && !empty?
181     first.within_transaction do
182       yield
183       success?
184     end
185   else
186     yield
187   end
188 end