module Teckel::Chain::Config

Constants

REQUIRED_CONFIGS

Public Class Methods

extended(base) click to toggle source

@!visibility private

# File lib/teckel/chain/config.rb, line 252
def self.extended(base)
  base.instance_variable_set(:@config, Teckel::Config.new)
end

Public Instance Methods

around(callable = nil, &block) click to toggle source

Set or get the optional around hook. A Hook might be given as a block or anything callable. The execution of the chain is yielded to this hook. The first argument being the callable chain ({Runner}) and the second argument the input data. The hook also needs to return the result.

@param callable [Proc,{#call}] The hook to pass chain execution control to. (nil)

@return [Proc,{#call}] The configured hook

@example Around hook with block

OUTPUTS = []

class Echo
  include ::Teckel::Operation
  result!

  input Hash
  output input

  def call(hsh)
    success!(hsh)
  end
end

class MyChain
  include Teckel::Chain

  around do |chain, input|
    OUTPUTS << "before start"
    result = chain.call(input)
    OUTPUTS << "after start"
    result
  end

  step :noop, Echo
end

result = MyChain.call(some: 'test')
OUTPUTS #=> ["before start", "after start"]
result.success #=> { some: "test" }
# File lib/teckel/chain/config.rb, line 64
def around(callable = nil, &block)
  @config.for(:around, callable || block)
end
clone() click to toggle source

Produces a clone of this chain. It's {around}, {runner} and {steps} will get dup'ed

@return [self] @!visibility public

Calls superclass method
# File lib/teckel/chain/config.rb, line 238
def clone
  if frozen?
    super
  else
    dup_config(super)
  end
end
default_settings() click to toggle source

Getter for configured default settings @return [nil|#call] The callable constructor

# File lib/teckel/chain/config.rb, line 196
def default_settings
  @config.for(:default_settings)
end
define!() click to toggle source

@!visibility private @return [void]

# File lib/teckel/chain/config.rb, line 204
def define!
  raise MissingConfigError, "Cannot define Chain with no steps" if steps.empty?

  REQUIRED_CONFIGS.each { |e| public_send(e) }
  steps.each(&:finalize!)
  nil
end
dup() click to toggle source

Produces a shallow copy of this chain. It's {around}, {runner} and {steps} will get dup'ed

@return [self] @!visibility public

Calls superclass method
# File lib/teckel/chain/config.rb, line 229
def dup
  dup_config(super)
end
finalize!() click to toggle source

Disallow any further changes to this Chain. @note This also calls finalize! on all Operations defined as steps.

@return [self] Frozen self @!visibility public

# File lib/teckel/chain/config.rb, line 217
def finalize!
  define!
  steps.freeze
  @config.freeze
  self
end
inherited(subclass) click to toggle source

@!visibility private

Calls superclass method
# File lib/teckel/chain/config.rb, line 247
def inherited(subclass)
  super dup_config(subclass)
end
result(klass = nil) click to toggle source

@overload result()

Get the configured result object class wrapping {.error} or {.output}.
@return [Class] The +result+ class, or {Teckel::Chain::Result} as default

@overload result(klass)

Set the result object class wrapping {.error} or {.output}.
@param klass [Class] The +result+ class
@return [Class] The +result+ class configured
# File lib/teckel/chain/config.rb, line 87
def result(klass = nil)
  @config.for(:result, klass) { const_defined?(:Result, false) ? self::Result : Teckel::Chain::Result }
end
result_constructor(sym_or_proc = nil) click to toggle source

@overload result_constructor()

The callable constructor to build an instance of the +result+ class.
Defaults to {Teckel::DEFAULT_CONSTRUCTOR}
@return [Proc] A callable that will return an instance of +result+ class.

@overload result_constructor(sym_or_proc)

Define how to build the +result+.
@param  sym_or_proc [Symbol, #call]
  - Either a +Symbol+ representing the _public_ method to call on the +result+ class.
  - Or anything that response to +#call+ (like a +Proc+).
@return [#call] The callable constructor

@example
  class MyOperation
    include Teckel::Operation
    result!

    settings Struct.new(:say, :other)
    settings_constructor ->(data) { settings.new(*data.values_at(*settings.members)) }

    input none
    output Hash
    error none

    def call(_)
      success!(settings.to_h)
    end
  end

  class Chain
    include Teckel::Chain

    class Result < Teckel::Operation::Result
      def initialize(value, success, step, opts = {})
        super(value, success)
        @step = step
        @opts = opts
      end

      class << self
        alias :[] :new # Alias the default constructor to :new
      end

      attr_reader :opts, :step
    end

    result_constructor ->(value, success, step) {
      result.new(value, success, step, time: Time.now.to_i)
    }

    step :a, MyOperation
  end
# File lib/teckel/chain/config.rb, line 143
def result_constructor(sym_or_proc = nil)
  constructor = build_constructor(result, sym_or_proc) unless sym_or_proc.nil?

  @config.for(:result_constructor, constructor) {
    build_constructor(result, Teckel::DEFAULT_CONSTRUCTOR)
  } || raise(MissingConfigError, "Missing result_constructor config for #{self}")
end
runner(klass = nil) click to toggle source

Overwrite the default runner @param klass [Class] A class like the {Runner} @!visibility protected

# File lib/teckel/chain/config.rb, line 75
def runner(klass = nil)
  @config.for(:runner, klass) { Runner }
end
step(name, operation) click to toggle source

Declare a {Operation} as a named step

@param name [String,Symbol] The name of the operation.

This name is used in an error case to let you know which step failed.

@param operation [Operation] The operation to call, which

must return a {Teckel::Result} object.
# File lib/teckel/chain/config.rb, line 12
def step(name, operation)
  steps << Step.new(name, operation)
end
steps() click to toggle source

Get the list of defined steps

@return [<Step>]

# File lib/teckel/chain/config.rb, line 19
def steps
  @config.for(:steps) { [] }
end

Private Instance Methods

build_constructor(on, sym_or_proc) click to toggle source
# File lib/teckel/chain/config.rb, line 266
def build_constructor(on, sym_or_proc)
  if sym_or_proc.is_a?(Symbol) && on.respond_to?(sym_or_proc)
    on.public_method(sym_or_proc)
  elsif sym_or_proc.respond_to?(:call)
    sym_or_proc
  end
end
dup_config(other_class) click to toggle source
# File lib/teckel/chain/config.rb, line 258
def dup_config(other_class)
  new_config = @config.dup
  new_config.replace(:steps) { steps.dup }

  other_class.instance_variable_set(:@config, new_config)
  other_class
end