module Teckel::Operation::Config

Constants

REQUIRED_CONFIGS

@!visibility private

Public Class Methods

extended(base) click to toggle source

@!visibility private

# File lib/teckel/operation/config.rb, line 369
def self.extended(base)
  base.instance_exec do
    @config = Teckel::Config.new
    attr_accessor :runner
    attr_accessor :settings
  end
end

Public Instance Methods

clone() click to toggle source

Produces a clone of this operation and all it's configuration

@return [self] @!visibility public

Calls superclass method
# File lib/teckel/operation/config.rb, line 352
def clone
  if frozen?
    super
  else
    super.tap do |copy|
      copy.instance_variable_set(:@config, @config.dup)
    end
  end
end
default_settings() click to toggle source

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

# File lib/teckel/operation/config.rb, line 236
def default_settings
  @config.for(:default_settings)
end
default_settings!(*args) click to toggle source

Declare default settings this operation should use when called without {Teckel::Operation::ClassMethods#with with}. When executing a Operation, settings will no longer be nil, but whatever you define here.

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

@overload default_settings!()

When this operation is called without {Teckel::Operation::ClassMethods#with #with},
+settings+ will be an instance of the +settings+ class, initialized with no arguments.

@overload default_settings!(sym_or_proc)

When this operation is called without {Teckel::Operation::ClassMethods#with #with},
+settings+ will be an instance of this callable constructor.

@param sym_or_proc [Symbol, #call]
  - Either a +Symbol+ representing the _public_ method to call on the +settings+ class.
  - Or anything that responds to +#call+ (like a +Proc+).

@overload default_settings!(arg1, arg2, …)

When this operation is called without {Teckel::Operation::ClassMethods#with #with},
+settings+ will be an instance of the +settings+ class, initialized with those arguments.

(Like calling +MyOperation.with(arg1, arg2, ...)+)
# File lib/teckel/operation/config.rb, line 221
def default_settings!(*args)
  callable =
    if args.empty?
      -> { settings_constructor.call }
    elsif args.length == 1
      build_constructor(settings, args.first)
    end

  callable ||= -> { settings_constructor.call(*args) }

  @config.for(:default_settings, callable)
end
define!() click to toggle source

@!visibility private @return [void]

# File lib/teckel/operation/config.rb, line 321
def define!
  REQUIRED_CONFIGS.each { |e| public_send(e) }
  nil
end
dup() click to toggle source

Produces a shallow copy of this operation and all it's configuration.

@return [self] @!visibility public

Calls superclass method
# File lib/teckel/operation/config.rb, line 342
def dup
  super.tap do |copy|
    copy.instance_variable_set(:@config, @config.dup)
  end
end
error(klass = nil) click to toggle source

@overload error()

Get the configured class wrapping the error data structure.
@return [Class] The +error+ class

@overload error(klass)

Set the class wrapping the error data structure.
@param klass [Class] The +error+ class
@return [Class,nil] The +error+ class or +nil+ if it does not error
# File lib/teckel/operation/config.rb, line 118
def error(klass = nil)
  @config.for(:error, klass) { self::Error if const_defined?(:Error) } ||
    raise(Teckel::MissingConfigError, "Missing error config for #{self}")
end
error_constructor(sym_or_proc = nil) click to toggle source

@overload error_constructor()

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

@overload error_constructor(sym_or_proc)

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

@example
  class MyOperation
    include Teckel::Operation

    class Error
      def initialize(*args, **opts); end
    end

    # MyOperation.call("foo", "bar") # -> Error.new("foo", "bar")
    error_constructor :new

    # If you need more control over how to build a new +Error+ instance
    # MyOperation.call("foo", opt: "bar") # -> Error.new(name: "foo", opt: "bar")
    error_constructor ->(name, options) { Error.new(name: name, **options) }
  end
# File lib/teckel/operation/config.rb, line 150
def error_constructor(sym_or_proc = nil)
  get_set_constructor(:error_constructor, error, sym_or_proc) ||
    raise(MissingConfigError, "Missing error_constructor config for #{self}")
end
finalize!() click to toggle source

Disallow any further changes to this Operation. Make sure all configurations are set.

@raise [MissingConfigError] @return [self] Frozen self @!visibility public

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

@!visibility private

Calls superclass method
# File lib/teckel/operation/config.rb, line 363
def inherited(subclass)
  subclass.instance_variable_set(:@config, @config.dup)
  super subclass
end
input(klass = nil) click to toggle source

@overload input()

Get the configured class wrapping the input data structure.
@return [Class] The +input+ class

@overload input(klass)

Set the class wrapping the input data structure.
@param  klass [Class] The +input+ class
@return [Class] The +input+ class
# File lib/teckel/operation/config.rb, line 13
def input(klass = nil)
  @config.for(:input, klass) { self::Input if const_defined?(:Input) } ||
    raise(Teckel::MissingConfigError, "Missing input config for #{self}")
end
input_constructor(sym_or_proc = nil) click to toggle source

@overload input_constructor()

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

@overload input_constructor(sym_or_proc)

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

@example simple symbol to method constructor
  class MyOperation
    include Teckel::Operation

    class Input
      def initialize(name:, age:); end
    end

    # If you need more control over how to build a new +Input+ instance
    # MyOperation.call(name: "Bob", age: 23) # -> Input.new(name: "Bob", age: 23)
    input_constructor :new
  end

  MyOperation.input_constructor.is_a?(Method) #=> true

@example Custom Proc constructor
  class MyOperation
    include Teckel::Operation

    class Input
      def initialize(*args, **opts); end
    end

    # If you need more control over how to build a new +Input+ instance
    # MyOperation.call("foo", opt: "bar") # -> Input.new(name: "foo", opt: "bar")
    input_constructor ->(name, options) { Input.new(name: name, **options) }
  end

  MyOperation.input_constructor.is_a?(Proc) #=> true
# File lib/teckel/operation/config.rb, line 59
def input_constructor(sym_or_proc = nil)
  get_set_constructor(:input_constructor, input, sym_or_proc) ||
    raise(MissingConfigError, "Missing input_constructor config for #{self}")
end
output(klass = nil) click to toggle source

@overload output()

Get the configured class wrapping the output data structure.
Defaults to {Teckel::DEFAULT_CONSTRUCTOR}
@return [Class] The +output+ class

@overload output(klass)

Set the class wrapping the output data structure.
@param  klass [Class] The +output+ class
@return [Class] The +output+ class
# File lib/teckel/operation/config.rb, line 73
def output(klass = nil)
  @config.for(:output, klass) { self::Output if const_defined?(:Output) } ||
    raise(Teckel::MissingConfigError, "Missing output config for #{self}")
end
output_constructor(sym_or_proc = nil) click to toggle source

@overload output_constructor()

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

@overload output_constructor(sym_or_proc)

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

@example
  class MyOperation
    include Teckel::Operation

    class Output
      def initialize(*args, **opts); end
    end

    # MyOperation.call("foo", "bar") # -> Output.new("foo", "bar")
    output_constructor :new

    # If you need more control over how to build a new +Output+ instance
    # MyOperation.call("foo", opt: "bar") # -> Output.new(name: "foo", opt: "bar")
    output_constructor ->(name, options) { Output.new(name: name, **options) }
  end
# File lib/teckel/operation/config.rb, line 105
def output_constructor(sym_or_proc = nil)
  get_set_constructor(:output_constructor, output, sym_or_proc) ||
    raise(MissingConfigError, "Missing output_constructor config for #{self}")
end
result(klass = nil) click to toggle source

@overload result()

Get the configured result object class wrapping {error} or {output}.
The {ValueResult} default will act as a pass-through and does. Any error
or output will just returned as-is.
@return [Class] The +result+ class, or {ValueResult} 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/operation/config.rb, line 262
def result(klass = nil)
  @config.for(:result, klass) { const_defined?(:Result, false) ? self::Result : ValueResult }
end
result!() click to toggle source

Shortcut to use {Teckel::Operation::Result} as a result object, wrapping any {error} or {output}.

@!visibility protected @note Don't use in conjunction with {result} or {result_constructor} @return [nil]

# File lib/teckel/operation/config.rb, line 303
def result!
  @config.for(:result, Teckel::Operation::Result)
  @config.for(:result_constructor, Teckel::Operation::Result.method(:new))
  nil
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

    class Result
      include Teckel::Result
      def initialize(value, success, opts = {}); end
    end

    # If you need more control over how to build a new +Result+ instance
    result_constructor ->(value, success) { result.new(value, success, {foo: :bar}) }
  end
# File lib/teckel/operation/config.rb, line 290
def result_constructor(sym_or_proc = nil)
  get_set_constructor(:result_constructor, result, sym_or_proc) ||
    raise(MissingConfigError, "Missing result_constructor config for #{self}")
end
runner(klass = nil) click to toggle source

@overload runner()

@return [Class] The Runner class
@!visibility protected

@overload runner(klass)

Overwrite the default runner
@param klass [Class] A class like the {Runner}
@!visibility protected
# File lib/teckel/operation/config.rb, line 248
def runner(klass = nil)
  @config.for(:runner, klass) { Teckel::Operation::Runner }
end
settings(klass = nil) click to toggle source

@overload settings()

Get the configured class wrapping the settings data structure.
@return [Class] The +settings+ class, or {Teckel::Contracts::None} as default

@overload settings(klass)

Set the class wrapping the settings data structure.
@param klass [Class] The +settings+ class
@return [Class] The +settings+ class configured
# File lib/teckel/operation/config.rb, line 165
def settings(klass = nil)
  @config.for(:settings, klass) { const_defined?(:Settings) ? self::Settings : none }
end
settings_constructor(sym_or_proc = nil) click to toggle source

@overload settings_constructor()

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

@overload settings_constructor(sym_or_proc)

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

@example
  class MyOperation
    include Teckel::Operation

    class Settings
      def initialize(*args); end
    end

    # MyOperation.with("foo", "bar") # -> Settings.new("foo", "bar")
    settings_constructor :new
  end
# File lib/teckel/operation/config.rb, line 192
def settings_constructor(sym_or_proc = nil)
  get_set_constructor(:settings_constructor, settings, sym_or_proc) ||
    raise(MissingConfigError, "Missing settings_constructor config for #{self}")
end

Private Instance Methods

build_constructor(on, sym_or_proc) click to toggle source
# File lib/teckel/operation/config.rb, line 387
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
get_set_constructor(name, on, sym_or_proc) click to toggle source
# File lib/teckel/operation/config.rb, line 379
def get_set_constructor(name, on, sym_or_proc)
  constructor = build_constructor(on, sym_or_proc) unless sym_or_proc.nil?

  @config.for(name, constructor) {
    build_constructor(on, Teckel::DEFAULT_CONSTRUCTOR)
  }
end