Class: OmniService::Parallel

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

Overview

Executes all components, collecting errors from all instead of short-circuiting. Useful for validation where you want to report all issues at once. Context merges from all components; params can be distributed or packed.

Examples:

Validate multiple fields, collect all errors

parallel(
  validate_title,    # => Failure([{ path: [:title], code: :blank }])
  validate_body,     # => Failure([{ path: [:body], code: :too_short }])
  validate_author    # => Success(...)
)
# => Result with all errors collected

Pack params from multiple sources into single hash

parallel(
  parse_post_params,     # => Success({ title: 'Hi' }, ...)
  , # => Success({ tags: [...] }, ...)
  pack_params: true
)
# => Result(params: [{ title: 'Hi', tags: [...] }])

Instance Method Summary collapse

Methods included from Strict

#call!

Constructor Details

#initialize(*args) ⇒ Parallel

Returns a new instance of Parallel.



32
33
34
# File 'lib/omni_service/parallel.rb', line 32

def initialize(*args, **)
  super(args.flatten(1), **)
end

Instance Method Details

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

rubocop:disable Metrics/AbcSize



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/omni_service/parallel.rb', line 36

def call(*params, **context) # rubocop:disable Metrics/AbcSize
  leftovers, result = component_wrappers
    .inject([params, OmniService::Result.build(self, context:)]) do |(params_left, result), component|
      break [params_left, result] if result.shortcut?

      component_params = params_left[...component.signature.first]
      component_result = component.call(*component_params, **result.context)
      result_params = if pack_params
        [(result.params.first || {}).merge(component_result.params.first)]
      else
        result.params + component_result.params
      end

      [
        params.one? ? params : params_left[component_params.size..],
        result.merge(component_result, params: result_params)
      ]
    end

  params.one? ? result : result.merge(params: result.params + leftovers)
end

#signatureObject



58
59
60
61
62
63
# File 'lib/omni_service/parallel.rb', line 58

def signature
  @signature ||= begin
    param_counts = component_wrappers.map { |component| component.signature.first }
    [param_counts.all? ? param_counts.sum : nil, true]
  end
end