Module: OmniService::Convenience

Defined in:
lib/omni_service/convenience.rb

Overview

DSL module for building operations with composable components. Provides factory methods and includes common dependencies.

Includes: Dry::Initializer, Dry::Monads, Dry::Monads::Do, Dry::Core::Constants

Factory methods: sequence, parallel, transaction, optional, shortcut,

namespace, collection, context, params, noop

Bang methods: Appending ! to any method returns a callable that uses call!

e.g., MyOp.create! returns MyOp.create.method(:call!)

Examples:

Typical operation class

class Posts::Create
  extend OmniService::Convenience

  option :post_repo, default: -> { PostRepository.new }

  def self.system
    @system ||= sequence(
      input,
      transaction(create, on_success: [notify])
    )
  end

  def self.input
    @input ||= parallel(
      params { required(:title).filled(:string) },
      find_author
    )
  end

  def self.create
    ->(params, author:, **) { post_repo.create(params.merge(author:)) }
  end
end

Posts::Create.system.call({ title: 'Hello' }, current_user:)
Posts::Create.system!.call({ title: 'Hello' }, current_user:)  # raises on failure

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name) ⇒ Object



51
52
53
54
55
56
57
58
# File 'lib/omni_service/convenience.rb', line 51

def method_missing(name, ...)
  name_without_suffix = name.to_s.delete_suffix('!').to_sym
  if name.to_s.end_with?('!') && respond_to?(name_without_suffix)
    public_send(name_without_suffix, ...).method(:call!)
  else
    super
  end
end

Class Method Details

.extended(mod) ⇒ Object



43
44
45
46
47
48
49
# File 'lib/omni_service/convenience.rb', line 43

def self.extended(mod)
  mod.extend Dry::Initializer
  mod.include Dry::Monads[:result]
  mod.include Dry::Monads::Do.for(:call)
  mod.include Dry::Core::Constants
  mod.include OmniService::Helpers
end

Instance Method Details

#collectionObject



76
77
78
# File 'lib/omni_service/convenience.rb', line 76

def collection(...)
  OmniService::Collection.new(...)
end

#component(name, from = Object, **options, &block) ⇒ Object

Raises:

  • (ArgumentError)


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/omni_service/convenience.rb', line 104

def component(name, from = Object, **options, &block)
  raise ArgumentError, "Please provide either a superclass or a block for #{name}" unless from || block

  klass = Class.new(from)
  klass.extend(Dry::Initializer) unless klass.include?(Dry::Initializer)
  klass.include(Dry::Monads[:result]) unless klass.is_a?(Dry::Monads[:result])
  klass.class_eval do
    options.each do |name, type|
      option name, type
    end
  end
  klass.define_method(:call, &block) if block

  const_set(name.to_s.camelize, klass)
end

#context(schema) ⇒ Object



100
101
102
# File 'lib/omni_service/convenience.rb', line 100

def context(schema)
  OmniService::Context.new(schema)
end

#namespaceObject



92
93
94
# File 'lib/omni_service/convenience.rb', line 92

def namespace(...)
  OmniService::Namespace.new(...)
end

#noopObject



64
65
66
# File 'lib/omni_service/convenience.rb', line 64

def noop
  ->(_, **) { Dry::Monads::Success({}) }
end

#optionalObject



88
89
90
# File 'lib/omni_service/convenience.rb', line 88

def optional(...)
  OmniService::Optional.new(...)
end

#parallelObject



72
73
74
# File 'lib/omni_service/convenience.rb', line 72

def parallel(...)
  OmniService::Parallel.new(...)
end

#paramsObject



96
97
98
# File 'lib/omni_service/convenience.rb', line 96

def params(**, &)
  OmniService::Params.params(**, &)
end

#respond_to_missing?(name) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/omni_service/convenience.rb', line 60

def respond_to_missing?(name, *)
  (name.to_s.end_with?('!') && respond_to?(name.to_s.delete_suffix('!').to_sym)) || super
end

#sequenceObject



68
69
70
# File 'lib/omni_service/convenience.rb', line 68

def sequence(...)
  OmniService::Sequence.new(...)
end

#shortcutObject



84
85
86
# File 'lib/omni_service/convenience.rb', line 84

def shortcut(...)
  OmniService::Shortcut.new(...)
end

#transactionObject



80
81
82
# File 'lib/omni_service/convenience.rb', line 80

def transaction(...)
  OmniService::Transaction.new(...)
end