Class: OmniService::Component

Inherits:
Object
  • Object
show all
Extended by:
Dry::Initializer
Includes:
Strict
Defined in:
lib/omni_service/component.rb

Overview

Wraps any callable (lambda, proc, object responding to #call) and normalizes its execution. Detects callable signature to properly dispatch params and context.

Supported signatures:

- `(**context)` - receives only context
- `(params)` - receives only first param
- `(params, **context)` - receives first param and context
- `(p1, p2, ..., **context)` - receives multiple params and context

Examples:

Lambda with params and context

component = OmniService::Component.new(->(params, **ctx) { Success(post: params) })
component.call({ title: 'Hello' }, author: current_user)
# => Result(context: { author: current_user, post: { title: 'Hello' } })

Context-only callable

component = OmniService::Component.new(->(**ctx) { Success(greeted: ctx[:user].name) })
component.call({}, user: User.new(name: 'John'))
# => Result(context: { user: ..., greeted: 'John' })

Constant Summary collapse

MONADS_DO_WRAPPER_SIGNATURES =
[
  [%i[rest *], %i[block &]],
  [%i[rest], %i[block &]], # Ruby 3.0, 3.1
  [%i[rest *], %i[keyrest **], %i[block &]],
  [%i[rest], %i[keyrest], %i[block &]] # Ruby 3.0, 3.1
].freeze
DEFAULT_NAMES_MAP =

Ruby 3.0, 3.1

{ rest: '*', keyrest: '**' }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Strict

#call!

Class Method Details

.wrap(value) ⇒ Object



39
40
41
42
43
44
45
46
47
# File 'lib/omni_service/component.rb', line 39

def self.wrap(value)
  if value.is_a?(Array)
    value.map { |item| wrap(item) }
  elsif value.respond_to?(:signature)
    value
  else
    new(value)
  end
end

Instance Method Details

#call(*params, **context) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/omni_service/component.rb', line 49

def call(*params, **context)
  callable_result = case signature
  in [0, true]
    callable.call(**context)
  in [n, false]
    callable.call(*params[...n])
  in [n, true]
    callable.call(*params[...n], **context)
  end

  OmniService::Result.build(callable, params:, context:).merge(OmniService::Result.process(callable, callable_result))
end

#signatureObject



62
63
64
65
66
67
# File 'lib/omni_service/component.rb', line 62

def signature
  @signature ||= [
    call_args(%i[rest]).empty? ? call_args(%i[req opt]).size : call_args(%i[rest]).size,
    !call_args(%i[key keyreq keyrest]).empty?
  ]
end