Module: Teckel::Chain::Config

Defined in:
lib/teckel/chain/config.rb

Constant Summary collapse

REQUIRED_CONFIGS =
%i[around runner result result_constructor].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#runner()Class (readonly, protected)

Returns The Runner class.

Returns:

  • (Class)

    The Runner class



# File 'lib/teckel/chain/config.rb', line 68

Instance Method Details

#around(callable = nil, &block) ⇒ Proc, {#call}

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.

Examples:

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" }

Parameters:

  • callable (Proc, {#call}) (defaults to: nil)

    The hook to pass chain execution control to. (nil)

Returns:

  • (Proc, {#call})

    The configured hook



64
65
66
# File 'lib/teckel/chain/config.rb', line 64

def around(callable = nil, &block)
  @config.for(:around, callable || block)
end

#cloneself

Produces a clone of this chain. It’s #around, #runner and #steps will get dup‘ed

Returns:

  • (self)


238
239
240
241
242
243
244
# File 'lib/teckel/chain/config.rb', line 238

def clone
  if frozen?
    super
  else
    dup_config(super)
  end
end

#default_settingsnil|#call

Getter for configured default settings

Returns:

  • (nil|#call)

    The callable constructor



196
197
198
# File 'lib/teckel/chain/config.rb', line 196

def default_settings
  @config.for(:default_settings)
end

#default_settings!(settings) ⇒ Object

Declare default settings operation iin this chain should use when called without #with.

Explicit call-time settings will not get merged with declared default setting.

Examples:

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

  default_settings!(a: { say: "Chain Default" })

  step :a, MyOperation
end

# Using the chains default settings
result = Chain.call
result.success #=> {say: "Chain Default", other: nil}

# explicit settings passed via `with` will overwrite all defaults
result = Chain.with(a: { other: "What" }).call
result.success #=> {say: nil, other: "What"}

Parameters:

  • settings (Hash{String,Symbol => Object})

    Set settings for a step by it’s name



190
191
192
# File 'lib/teckel/chain/config.rb', line 190

def default_settings!(settings) # :nodoc: The bang is for consistency with the Operation class
  @config.for(:default_settings, settings)
end

#dupself

Produces a shallow copy of this chain. It’s #around, #runner and #steps will get dup‘ed

Returns:

  • (self)


229
230
231
# File 'lib/teckel/chain/config.rb', line 229

def dup
  dup_config(super)
end

#finalize!self

Note:

This also calls finalize! on all Operations defined as steps.

Disallow any further changes to this Chain.

Returns:

  • (self)

    Frozen self



217
218
219
220
221
222
# File 'lib/teckel/chain/config.rb', line 217

def finalize!
  define!
  steps.freeze
  @config.freeze
  self
end

#resultClass #result(klass) ⇒ Class

Overloads:

  • #resultClass

    Get the configured result object class wrapping error or output.

    Returns:

    • (Class)

      The result class, or Result as default

  • #result(klass) ⇒ Class

    Set the result object class wrapping error or output.

    Parameters:

    • klass (Class)

      The result class

    Returns:

    • (Class)

      The result class configured



87
88
89
# 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_constructorProc #result_constructor(sym_or_proc) ⇒ #call

Overloads:

  • #result_constructorProc

    The callable constructor to build an instance of the result class. Defaults to DEFAULT_CONSTRUCTOR

    Returns:

    • (Proc)

      A callable that will return an instance of result class.

  • #result_constructor(sym_or_proc) ⇒ #call

    Define how to build the result.

    Examples:

    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

    Parameters:

    • 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).

    Returns:

    • (#call)

      The callable constructor



143
144
145
146
147
148
149
# 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) ⇒ Object (protected)

Overwrite the default runner

Parameters:

  • klass (Class) (defaults to: nil)

    A class like the Runner



75
76
77
# File 'lib/teckel/chain/config.rb', line 75

def runner(klass = nil)
  @config.for(:runner, klass) { Runner }
end

#step(name, operation) ⇒ Object

Declare a Operation as a named step

Parameters:

  • name (String, Symbol)

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

  • operation (Operation)

    The operation to call, which must return a Result object.



12
13
14
# File 'lib/teckel/chain/config.rb', line 12

def step(name, operation)
  steps << Step.new(name, operation)
end

#steps<Step>

Get the list of defined steps

Returns:



19
20
21
# File 'lib/teckel/chain/config.rb', line 19

def steps
  @config.for(:steps) { [] }
end