module Teckel::Operation

The main operation Mixin

Each operation is expected to declare input. output and error classes.

There are two ways of declaring those classes. The first way is to define the constants Input, Output and Error, the second way is to use the input. output and error methods to point them to anonymous classes.

If you like “traditional” result objects to ask successful? or failure? on, use {Teckel::Operation::Config#result! result!} and get {Teckel::Operation::Result}

By default, input. output and error classes are build using :[] (eg: +Input[some: :param]+).

Use {Teckel::Operation::Config#input_constructor input_constructor}, {Teckel::Operation::Config#output_constructor output_constructor} and {Teckel::Operation::Config#error_constructor error_constructor} to change them.

@example class definitions via methods

class CreateUserViaMethods
  include Teckel::Operation

  input  Types::Hash.schema(name: Types::String, age: Types::Coercible::Integer)
  output Types.Instance(User)
  error  Types::Hash.schema(message: Types::String, errors: Types::Array.of(Types::Hash))

  # @param [Hash<name: String, age: Integer>]
  # @return [User,Hash<message: String, errors: [Hash]>]
  def call(input)
    user = User.new(name: input[:name], age: input[:age])
    if user.save
      success!(user) # exits early with success, prevents any further execution
    else
      fail!(message: "Could not save User", errors: user.errors)
    end
  end
end

# A success call:
CreateUserViaMethods.call(name: "Bob", age: 23).is_a?(User) #=> true

# A failure call:
CreateUserViaMethods.call(name: "Bob", age: 10).eql?(message: "Could not save User", errors: [{age: "underage"}]) #=> true

# Build your Input, Output and Error classes in a way that let you know:
begin; CreateUserViaMethods.call(unwanted: "input"); rescue => e; e end.is_a?(::Dry::Types::MissingKeyError) #=> true

# Feed an instance of the input class directly to call:
CreateUserViaMethods.call(CreateUserViaMethods.input[name: "Bob", age: 23]).is_a?(User) #=> true

@!visibility public

Public Class Methods

included(receiver) click to toggle source
# File lib/teckel/operation.rb, line 189
def self.included(receiver)
  receiver.extend         Config
  receiver.extend         ClassMethods
  receiver.send :include, InstanceMethods
end