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 aresultclass. - 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 |