Class: StateMachines::TransitionCollection

Inherits:
Array
  • Object
show all
Defined in:
lib/state_machines/transition_collection.rb

Overview

Represents a collection of transitions in a state machine

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(transitions = [], options = {}) ⇒ TransitionCollection

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

Raises:

  • (ArgumentError)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/state_machines/transition_collection.rb', line 27

def initialize(transitions = [], options = {})
  super(transitions)

  # Determine the validity of the transitions as a whole
  @valid = all?
  reject!(&:!)

  attributes = map(&:attribute).uniq
  raise ArgumentError, 'Cannot perform multiple transitions in parallel for the same state machine attribute' if attributes.length != length

  StateMachines::OptionsValidator.assert_valid_keys!(options, :actions, :after, :use_transactions, :fiber)
  options = { actions: true, after: true, use_transactions: true }.merge(options)
  @skip_actions = !options[:actions]
  @skip_after = !options[:after]
  @use_transactions = options[:use_transactions]
  @options = options

  # Reset transitions when creating a new collection
  # But preserve paused transitions to allow resuming
  each do |transition|
    transition.reset unless transition.paused?
  end
end

Instance Attribute Details

#optionsObject (readonly)

Options passed to the collection



18
19
20
# File 'lib/state_machines/transition_collection.rb', line 18

def options
  @options
end

#skip_actionsObject (readonly)

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



9
10
11
# File 'lib/state_machines/transition_collection.rb', line 9

def skip_actions
  @skip_actions
end

#skip_afterObject (readonly)

Whether to skip running the after callbacks



12
13
14
# File 'lib/state_machines/transition_collection.rb', line 12

def skip_after
  @skip_after
end

#use_transactionsObject (readonly)

Whether transitions should wrapped around a transaction block



15
16
17
# File 'lib/state_machines/transition_collection.rb', line 15

def use_transactions
  @use_transactions
end

Instance Method Details

#perform(&block) ⇒ Object

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.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/state_machines/transition_collection.rb', line 62

def perform(&block)
  reset

  if valid?
    if use_event_attributes? && !block_given?
      each do |transition|
        transition.transient = true
        transition.machine.write(object, :event_transition, transition)
      end

      run_actions
    else
      within_transaction do
        catch(:halt) { run_callbacks(&block) }
        rollback unless success?
      end
    end
  end

  if actions.length == 1 && results.include?(actions.first)
    results[actions.first]
  else
    success?
  end
end