Class: Trailblazer::Operation

Inherits:
Object
  • Object
show all
Defined in:
lib/trailblazer/operation/contract.rb,
lib/trailblazer/operation/wrap.rb,
lib/trailblazer/operation/guard.rb,
lib/trailblazer/operation/model.rb,
lib/trailblazer/operation/nested.rb,
lib/trailblazer/operation/policy.rb,
lib/trailblazer/operation/pundit.rb,
lib/trailblazer/operation/rescue.rb,
lib/trailblazer/operation/persist.rb,
lib/trailblazer/operation/callback.rb,
lib/trailblazer/operation/validate.rb,
lib/trailblazer/operation/auto_inject.rb,
lib/trailblazer/operation/representer.rb

Overview

Best practices for using contract.

  • inject contract instance via constructor to #contract

  • allow contract setup and memo via #contract(model, options)

  • allow implicit automatic setup via #contract and class.contract_class

Needs Operation#model. Needs #[], #[]= skill dependency.

Defined Under Namespace

Modules: AutoInject, Callback, Contract, Element, Model, Module, Nested, Policy, Procedural, Representer, Wrap

Constant Summary collapse

Base =

TODO: we won’t need this with 2.1.

self

Class Method Summary collapse

Class Method Details

.AutoInject(container) ⇒ Object



44
45
46
# File 'lib/trailblazer/operation/auto_inject.rb', line 44

def self.AutoInject(container)
  Dry::AutoInject(container, strategies: {default: AutoInject::InjectStrategy})
end

.Callback(group) ⇒ Object



4
5
6
7
8
# File 'lib/trailblazer/operation/callback.rb', line 4

def self.Callback(group)
  step = ->(input, options) { Callback.(group, input, options) }

  [ step, name: "callback.#{group}" ]
end

.Model(model_class, action = nil) ⇒ Object



2
3
4
5
6
7
8
# File 'lib/trailblazer/operation/model.rb', line 2

def self.Model(model_class, action=nil)
  step = Model.for(model_class, action)

  step = Pipetree::Step.new(step, "model.class" => model_class, "model.action" => action)

  [ step, name: "model.build" ]
end

.Nested(callable, input: nil, output: nil) ⇒ Object



2
3
4
5
6
# File 'lib/trailblazer/operation/nested.rb', line 2

def self.Nested(callable, input:nil, output:nil)
  step = Nested.for(callable, input, output)

  [ step, { name: "Nested(#{callable})" } ]
end

.Rescue(*exceptions, handler: lambda { |*| }, &block) ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/trailblazer/operation/rescue.rb', line 2

def self.Rescue(*exceptions, handler: lambda { |*| }, &block)
  exceptions = [StandardError] unless exceptions.any?
  handler    = Option.(handler)

  rescue_block = ->(options, operation, *, &nested_pipe) {
    begin
      res = nested_pipe.call
      res.first == ::Pipetree::Railway::Right # FIXME.
    rescue *exceptions => exception
      handler.call(operation, exception, options)
      false
    end
  }

  step, _ = Wrap(rescue_block, &block)

  [ step, name: "Rescue:#{block.source_location.last}" ]
end

.Wrap(wrap, &block) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
# File 'lib/trailblazer/operation/wrap.rb', line 4

def self.Wrap(wrap, &block)
  operation = Class.new(Base)
  # DISCUSS: don't instance_exec when |pipe| given?
  operation.instance_exec(&block) # evaluate the nested pipe.

  pipe = operation["pipetree"]
  pipe.add(nil, nil, {delete: "operation.new"}) # TODO: make this a bit more elegant.

  step = Wrap.for(wrap, pipe)

  [ step, {} ]
end