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



77
78
79
# File 'lib/hubbado/trailblazer/run_operation.rb', line 77

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

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

Yields:

  • (result)


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/hubbado/trailblazer/run_operation.rb', line 81

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)

  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