Class: Gaskit::Operation Abstract
- Inherits:
-
Object
- Object
- Gaskit::Operation
- Includes:
- Hookable
- Defined in:
- lib/gaskit/operation.rb
Overview
Subclass this and define ‘#call` or `#call!` to create a new operation.
The Gaskit::Operation class defines a structured and extensible pattern for building application operations. It enforces consistent behavior across operations while supporting customization via contracts.
# Features
-
Pluggable contracts via ‘use_contract`, allowing you to define or reference a `result` class.
-
Integrated duration tracking, structured logging, and early exits.
-
Supports ‘.call` (non-raising) and `.call!` (raising) styles.
Instance Attribute Summary collapse
-
#context ⇒ Object
readonly
Returns the value of attribute context.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#raise_on_failure ⇒ Object
readonly
Returns the value of attribute raise_on_failure.
Class Method Summary collapse
-
.call(*args, context: {}, **kwargs, &block) ⇒ Gaskit::OperationResult
Executes the operation with soft-failure handling.
-
.call!(*args, context: {}, **kwargs, &block) ⇒ Gaskit::OperationResult
Executes the operation with hard-failure handling (raises on unhandled errors).
-
.error(key, message, code: nil) ⇒ void
Declares a symbolic error and message for use with ‘exit(:key)`.
-
.errors_registry ⇒ void
Returns the error registry for the operation class.
- .result_class ⇒ Object
-
.use_contract(contract = nil, result: nil) ⇒ void
Defines the result class for this operation.
Instance Method Summary collapse
-
#call(*args, **kwargs) ⇒ void
Executes the operation logic.
-
#exit(error_key, message = nil, code: nil) ⇒ Object
(also: #abort)
Terminates the operation early with a symbolic key.
-
#initialize(raise_on_failure, context: {}) ⇒ void
constructor
Initializes a new Gaskit::Operation instance.
- #raise_on_failure? ⇒ Boolean
Methods included from Hookable
#apply_after_hooks, #apply_around_hooks, #apply_before_hooks, #apply_hooks, included
Constructor Details
#initialize(raise_on_failure, context: {}) ⇒ void
Initializes a new Gaskit::Operation instance.
265 266 267 268 269 270 271 272 273 |
# File 'lib/gaskit/operation.rb', line 265 def initialize(raise_on_failure, context: {}) @raise_on_failure = raise_on_failure @context = apply_context(context) @logger = Gaskit::Logger.new(self, context: @context) return unless self.class.result_class.nil? raise Gaskit::Error, "No result_class defined for #{self.class.name} or its ancestors." end |
Instance Attribute Details
#context ⇒ Object (readonly)
Returns the value of attribute context.
258 259 260 |
# File 'lib/gaskit/operation.rb', line 258 def context @context end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
258 259 260 |
# File 'lib/gaskit/operation.rb', line 258 def logger @logger end |
#raise_on_failure ⇒ Object (readonly)
Returns the value of attribute raise_on_failure.
258 259 260 |
# File 'lib/gaskit/operation.rb', line 258 def raise_on_failure @raise_on_failure end |
Class Method Details
.call(*args, context: {}, **kwargs, &block) ⇒ Gaskit::OperationResult
Executes the operation with soft-failure handling
117 118 119 |
# File 'lib/gaskit/operation.rb', line 117 def call(*args, context: {}, **kwargs, &block) invoke(false, context, *args, **kwargs, &block) end |
.call!(*args, context: {}, **kwargs, &block) ⇒ Gaskit::OperationResult
Executes the operation with hard-failure handling (raises on unhandled errors)
127 128 129 |
# File 'lib/gaskit/operation.rb', line 127 def call!(*args, context: {}, **kwargs, &block) invoke(true, context, *args, **kwargs, &block) end |
.error(key, message, code: nil) ⇒ void
This method returns an undefined value.
Declares a symbolic error and message for use with ‘exit(:key)`
96 97 98 99 100 101 102 |
# File 'lib/gaskit/operation.rb', line 96 def error(key, , code: nil) raise ArgumentError, "Error key must be a symbol or a string, received #{key}" unless key.is_a?(Symbol) raise ArgumentError, "Error message must be a string" unless .is_a?(String) raise ArgumentError, "Error key :#{key} is already registered" if errors_registry.key?(key) errors_registry[key.to_sym] = { message: , code: code } end |
.errors_registry ⇒ void
This method returns an undefined value.
Returns the error registry for the operation class
107 108 109 |
# File 'lib/gaskit/operation.rb', line 107 def errors_registry @errors_registry ||= {} end |
.result_class ⇒ Object
54 55 56 57 58 59 |
# File 'lib/gaskit/operation.rb', line 54 def result_class return @result_class if defined?(@result_class) && @result_class return superclass&.result_class if superclass.respond_to?(:result_class) nil end |
.use_contract(contract = nil, result: nil) ⇒ void
This method returns an undefined value.
Defines the result class for this operation. Can reference a named contract registered in ‘Gaskit::Registry`, or define one without using a registered contract.
76 77 78 79 80 81 82 83 84 85 |
# File 'lib/gaskit/operation.rb', line 76 def use_contract(contract = nil, result: nil) if contract raise ArgumentError, "use_contract must be called with a symbol or keyword args" unless contract.is_a?(Symbol) result = Gaskit.contracts.fetch(contract) end Gaskit::ContractRegistry.verify_result_class!(result) @result_class = result end |
Instance Method Details
#call(*args, **kwargs) ⇒ void
This method returns an undefined value.
Executes the operation logic.
285 286 287 |
# File 'lib/gaskit/operation.rb', line 285 def call(*args, **kwargs) raise NotImplementedError, "#{self.class.name} must implement `#call`" end |
#exit(error_key, message = nil, code: nil) ⇒ Object Also known as: abort
Terminates the operation early with a symbolic key.
If the key was previously registered via ‘self.error`, it uses the declared message and code. Otherwise, it uses the key as the message.
298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/gaskit/operation.rb', line 298 def exit(error_key, = nil, code: nil) error_key = error_key.to_sym definition = self.class.errors_registry.fetch(error_key, nil) if definition ||= definition[:message] code ||= definition[:code] end raise OperationExit.new(error_key, , code: code) end |
#raise_on_failure? ⇒ Boolean
275 276 277 |
# File 'lib/gaskit/operation.rb', line 275 def raise_on_failure? @raise_on_failure end |