class Transflow::Transaction

Transaction encapsulates calling individual steps registered within a transflow constructor.

It's responsible for calling steps in the right order and optionally currying arguments for specific steps.

Furthermore you can subscribe event listeners to individual steps within a transaction.

@api public

Attributes

step_names[R]

@attr_reader [Array<Symbol>] step_names The names of registered steps

@api private

steps[R]

@attr_reader [Hash<Symbol => Proc,#call>] steps The step map

@api private

Public Class Methods

new(steps) click to toggle source

@api private

# File lib/transflow/transaction.rb, line 43
def initialize(steps)
  @steps = steps
  @step_names = steps.keys.reverse
end

Public Instance Methods

[](input, options = {})
Alias for: call
call(input, options = {}) click to toggle source

Call the transaction

Once transaction is called it will call the first step and its result will be passed to the second step and so on.

@example

my_container = {
  add_one: -> i { i + 1 },
  add_two: -> j { j + 2 }
}

transaction = Transflow(container: my_container) {
  step(:one, with: :add_one) { step(:two, with: :add_two) }
}

transaction.call(1) # 4

@param [Object] input The input for the first step

@param [Hash] options The curry-args map, optional

@return [Object]

@raises TransactionFailedError

@api public

# File lib/transflow/transaction.rb, line 109
def call(input, options = {})
  handler = handler_steps(options).map(&method(:step)).reduce(:>>)
  handler.call(input)
rescue StepError => err
  raise TransactionFailedError.new(self, err)
end
Also aliased as: []
subscribe(listeners) click to toggle source

Subscribe event listeners to specific steps

@example

transaction = Transflow(container: my_container) {
  step(:one) { step(:two, publish: true }
}

class MyListener
  def self.two_success(*args)
    puts 'yes!'
  end

  def self.two_failure(*args)
    puts 'oh noez!'
  end
end

transaction.subscribe(two: my_listener)

transaction.call(some_input)

@param [Hash<Symbol => Object>] listeners The step=>listener map

@return [self]

@api public

# File lib/transflow/transaction.rb, line 74
def subscribe(listeners)
  if listeners.is_a?(Hash)
    listeners.each { |step, listener| steps[step].subscribe(listener) }
  else
    steps.each { |(_, step)| step.subscribe(listeners) }
  end
  self
end
to_s() click to toggle source

Coerce a transaction into string representation

@return [String]

@api public

# File lib/transflow/transaction.rb, line 122
def to_s
  "Transaction(#{step_names.join(' => ')})"
end

Private Instance Methods

assert_valid_options(options) click to toggle source

@api private

# File lib/transflow/transaction.rb, line 148
def assert_valid_options(options)
  options.each_key do |name|
    unless step_names.include?(name)
      raise ArgumentError, "+#{name}+ is not a valid step name"
    end
  end
end
handler_steps(options) click to toggle source

@api private

# File lib/transflow/transaction.rb, line 129
def handler_steps(options)
  if options.any?
    assert_valid_options(options)

    steps.map { |(name, op)|
      args = options[name]

      if args
        op.curry.call(args)
      else
        op
      end
    }
  else
    steps.values
  end.reverse
end
step(obj) click to toggle source

Wrap a proc into composable transproc function

@param [#call]

@api private

# File lib/transflow/transaction.rb, line 161
def step(obj)
  Step[obj]
end