class StateMachines::MachineCollection

Represents a collection of state machines for a class

Public Instance Methods

fire_events(object, *events) click to toggle source

Runs one or more events in parallel on the given object. See StateMachines::InstanceMethods#fire_events for more information.

# File lib/state_machines/machine_collection.rb, line 44
def fire_events(object, *events)
  run_action = [true, false].include?(events.last) ? events.pop : true

  # Generate the transitions to run for each event
  transitions = events.collect do |event_name|
    # Find the actual event being run
    event = nil
    detect {|name, machine| event = machine.events[event_name, :qualified_name]}

    raise(InvalidEvent.new(object, event_name)) unless event

    # Get the transition that will be performed for the event
    unless transition = event.transition_for(object)
      event.on_failure(object)
    end
    transition
  end.compact

  # Run the events in parallel only if valid transitions were found for
  # all of them
  if events.length == transitions.length
    TransitionCollection.new(transitions, {use_transactions: resolve_use_transactions, actions: run_action}).perform
  else
    false
  end
end
initialize_states(object, options = {}, attributes = {}) { || ... } click to toggle source

Initializes the state of each machine in the given object. This can allow states to be initialized in two groups: static and dynamic. For example:

machines.initialize_states(object) do
  # After static state initialization, before dynamic state initialization
end

If no block is provided, then all states will still be initialized.

Valid configuration options:

  • :static - Whether to initialize static states. Unless set to false, the state will be initialized regardless of its current value. Default is true.

  • :dynamic - Whether to initialize dynamic states. If set to :force, the state will be initialized regardless of its current value. Default is true.

  • :to - A hash to write the initialized state to instead of writing to the object. Default is to write directly to the object.

# File lib/state_machines/machine_collection.rb, line 22
def initialize_states(object, options = {}, attributes = {})
  options.assert_valid_keys( :static, :dynamic, :to)
  options = {:static => true, :dynamic => true}.merge(options)

  result = yield if block_given?

  each_value do |machine|
    unless machine.dynamic_initial_state?
      force = options[:static] == :force || !attributes.keys.map(&:to_sym).include?(machine.attribute)
      machine.initialize_state(object, force: force, :to => options[:to])
    end
  end if options[:static]

  each_value do |machine|
    machine.initialize_state(object, :force => options[:dynamic] == :force, :to => options[:to]) if machine.dynamic_initial_state?
  end if options[:dynamic]

  result
end
transitions(object, action, options = {}) click to toggle source

Builds the collection of transitions for all event attributes defined on the given object. This will only include events whose machine actions match the one specified.

These should only be fired as a result of the action being run.

# File lib/state_machines/machine_collection.rb, line 76
def transitions(object, action, options = {})
  transitions = map do |name, machine|
    machine.events.attribute_transition_for(object, true) if machine.action == action
  end

  AttributeTransitionCollection.new(transitions.compact, {use_transactions: resolve_use_transactions}.merge(options))
end

Protected Instance Methods

resolve_use_transactions() click to toggle source
# File lib/state_machines/machine_collection.rb, line 86
def resolve_use_transactions
  use_transactions = nil
  each_value do |machine|
    # Determine use_transactions setting for this set of transitions.  If from multiple state_machines, the settings must match.
    raise 'Encountered mismatched use_transactions configurations for multiple state_machines' if !use_transactions.nil? && use_transactions != machine.use_transactions
    use_transactions = machine.use_transactions
  end
  use_transactions
end