Module: Hubbado::Trailblazer::RunOperation

Includes:
TemplateMethod
Defined in:
lib/hubbado/trailblazer/run_operation.rb

Overview

This allows you to run an operation and then respond differently based on the result of the operation.

run_operation MyOperation do |result| result.success do |ctx| ... end

result.policy_failed do |ctx|

This is optional if not used the operation will raise an exception

...

Also optionally you can raise the default exception, it will not be raised

if the block is executed otherwise when the block is finished

result.raise_policy_failed end

result.not_found do |ctx| ... end

result.validation_failed do |ctx| ... end

result.otherwise do |ctx|

This is optional if not used the operation will raise an exception

...

Also optionally you can raise the default exception, it will not be raised

if the block is executed otherwise when the block is finished

result.raise_operation_failed end end

ctx is the context built by the operation.

If there is a policy failure and you have not implemented result.policy_failed then an exception will be raised.

If the operation has not_found terminus and you have not implemented result.not_found then ActiveRecord::RecordNotFound will be raised.

If the operation fails (due to non-policy error) and you have not implemented result.otherwise then an exception will be raised.

Note, it is on purpose that implementing result.otherwise is not enough to stop an exception being raised if the policy fails. This to prevent a result.otherwise block rendering a form when the policy failed.

We also considered TrailblazerEndpoint in place of this, but it seemed to be complicated for what it quite a simple usecase

Tracing operations

Setting the ENV variable TRACE_OPERATION to the class name of an operation (or to "_all") will cause the operation to be run with "wtf?" rather than call, outputting the trace of the operation, and showing which step failed, to stdout (not logging)

This is useful when debugging traces

Defined Under Namespace

Classes: Result

Instance Method Summary collapse

Instance Method Details

#_run_runtime_options(ctx = {}, *dependencies) ⇒ Object



81
82
83
# File 'lib/hubbado/trailblazer/run_operation.rb', line 81

def _run_runtime_options(ctx = {}, *dependencies)
  [_run_options(ctx), *dependencies]
end

#run_operation(operation, params = self.params, *options) {|result| ... } ⇒ Object

Yields:

  • (result)


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/hubbado/trailblazer/run_operation.rb', line 85

def run_operation(operation, params = self.params, *options)
  trace_operation = TraceOperation.(operation)
  operation_method = trace_operation ? 'wtf?' : 'call'

  operation_arguments = { params: _run_params(params) }
  operation_arguments[:request] = request if respond_to?(:request)
  operation_arguments.merge!(*_run_runtime_options(*options))

  ctx = operation.send(operation_method, operation_arguments)

  result = Result.new(
    operation,
    ctx,
    trace_operation: trace_operation,
    policy_unauthorized_message: policy_unauthorized_message(
      ctx,
      operation_name: operation.name
    )
  )

  yield(result) if block_given?

  if ctx['result.policy.default']&.failure?
    result.raise_policy_failed unless result.policy_failed_executed?
  elsif !result.not_found_executed? && ctx.terminus.to_h[:semantic] == :not_found
    result.raise_not_found
  elsif ctx.failure? && !result.validation_failed_executed? && !result.not_found_executed? && !result.otherwise_executed?
    result.raise_operation_failed
  end

  result.returned
end