Module: NextStation::Operation::ClassMethods
- Included in:
- NextStation::Operation
- Defined in:
- lib/next_station/operation/class_methods.rb
Overview
The ‘ClassMethods` module provides a set of class-level methods for defining the structure, validation, dependencies, and processing logic of an operation. It introduces a DSL for custom error handling, step management, schema enforcement, and parameter validation.
Error Handling
-
Allows defining custom error types for the operation using a DSL.
Result Management
-
Supports setting and retrieving the key where the operation result is stored.
-
Enables schema enforcement for result values using a Dry::Struct schema.
Steps and Branches
-
Facilitates defining execution steps and branches within an operation.
-
Allows querying the presence of specific steps within the operation.
Validation
-
Provides integration with Dry::Validation for validating operation parameters.
-
Enables enforcing or skipping validation on demand.
Dependencies
-
Supports defining and managing dependencies for the operation.
Methods
-
#errors: Defines custom error types using an error DSL.
-
#error_definitions: Returns all defined error mappings.
-
#result_at: Defines the key in the state for the operation result.
-
#result_key: Retrieves the key where the operation result is stored.
-
#result_schema: Defines a schema for the result using Dry::Struct.
-
#result_class: Retrieves the Dry::Struct class for the result schema.
-
#enforce_result_schema: Enables schema enforcement for the result.
-
#disable_result_schema: Disables schema enforcement for the result.
-
#schema_enforced?: Checks if schema enforcement is enabled.
-
#process: Defines the root execution block for the operation.
-
#step: Adds a single execution step to the operation.
-
#branch: Adds a conditional branch to the operation’s execution path.
-
#steps: Returns the defined execution steps for the operation.
-
#validate_with: Defines validation rules using Dry::Validation.
-
#validation_contract_class: Retrieves the validation contract class.
-
#validation_contract_instance: Returns an instance of the validation contract.
-
#force_validation!: Forces validation to be applied, even if not part of the operation steps.
-
#skip_validation!: Skips validation for the operation.
-
#validation_enforced?: Checks if validation is enforced.
-
#has_step?: Checks the presence of a specific step in the operation.
-
#depends: Defines dependencies required by the operation.
-
#dependencies: Retrieves the defined dependencies.
Instance Method Summary collapse
-
#branch(condition) { ... } ⇒ Object
Adds a branch to the operation.
-
#call(params = {}, context = {}, deps: {}) ⇒ Object
Convenience method to instantiate and call the operation.
-
#dependencies ⇒ Hash
The defined dependencies.
-
#depends(deps) ⇒ Object
Defines dependencies for the operation.
-
#disable_result_schema ⇒ Object
Disables result schema enforcement.
-
#enforce_result_schema ⇒ Object
Enables result schema enforcement.
-
#error_definitions ⇒ Hash
The registered error definitions.
-
#errors(external_source = nil) { ... } ⇒ Object
Defines error types for the operation.
-
#force_validation! ⇒ Object
Forces validation even if not explicitly defined in steps.
-
#has_step?(name, nodes = steps) ⇒ Boolean
Checks if a step exists in the operation.
-
#loaded_plugins ⇒ Array<Module>
The plugins loaded into this operation.
-
#plugin(name) ⇒ Object
Enables a plugin for the operation.
-
#process { ... } ⇒ Object
Defines the root execution block for the operation.
-
#result_at(key) ⇒ Object
Defines the key in the state where the final result is stored.
-
#result_class ⇒ Class?
The Dry::Struct class for the result.
-
#result_key ⇒ Symbol?
The key where the result is stored.
-
#result_schema(struct_class = nil) { ... } ⇒ Object
Defines a Dry::Struct schema for the result value.
-
#schema_enforced? ⇒ Boolean
Whether schema enforcement is enabled.
-
#skip_validation! ⇒ Object
Skips validation even if defined.
-
#step(method_name, options = {}) ⇒ Object
Adds a step to the operation.
-
#steps ⇒ Array<Node>
The steps defined for the operation.
-
#validate_with(contract_or_block = nil) { ... } ⇒ Object
Defines a Dry::Validation::Contract to validate the params.
-
#validation_contract_class ⇒ Class?
The validation contract class.
-
#validation_contract_instance ⇒ Dry::Validation::Contract?
An instance of the validation contract.
-
#validation_enforced? ⇒ Boolean
Whether validation is enforced.
Instance Method Details
#branch(condition) { ... } ⇒ Object
Adds a branch to the operation.
174 175 176 177 |
# File 'lib/next_station/operation/class_methods.rb', line 174 def branch(condition, &block) @root ||= Node.new(:root) @root.branch(condition, &block) end |
#call(params = {}, context = {}, deps: {}) ⇒ Object
Convenience method to instantiate and call the operation.
271 272 273 |
# File 'lib/next_station/operation/class_methods.rb', line 271 def call(params = {}, context = {}, deps: {}) new(deps: deps).call(params, context) end |
#dependencies ⇒ Hash
Returns The defined dependencies.
266 267 268 |
# File 'lib/next_station/operation/class_methods.rb', line 266 def dependencies @dependencies || (superclass.respond_to?(:dependencies) ? superclass.dependencies : {}) end |
#depends(deps) ⇒ Object
Defines dependencies for the operation.
261 262 263 |
# File 'lib/next_station/operation/class_methods.rb', line 261 def depends(deps) @dependencies = dependencies.merge(deps) end |
#disable_result_schema ⇒ Object
Disables result schema enforcement.
145 146 147 |
# File 'lib/next_station/operation/class_methods.rb', line 145 def disable_result_schema @schema_enforced = false end |
#enforce_result_schema ⇒ Object
Enables result schema enforcement.
140 141 142 |
# File 'lib/next_station/operation/class_methods.rb', line 140 def enforce_result_schema @schema_enforced = true end |
#error_definitions ⇒ Hash
Returns The registered error definitions.
84 85 86 87 88 89 90 91 |
# File 'lib/next_station/operation/class_methods.rb', line 84 def error_definitions parent_defs = if superclass.respond_to?(:error_definitions) superclass.error_definitions else {} end parent_defs.merge(@error_definitions || {}) end |
#errors(external_source = nil) { ... } ⇒ Object
Defines error types for the operation.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/next_station/operation/class_methods.rb', line 59 def errors(external_source = nil, &block) @error_definitions ||= {} # 1. Handle external source (e.g., SharedErrors < NextStation::Errors) if external_source.respond_to?(:definitions) @error_definitions.merge!(external_source.definitions) elsif external_source.is_a?(Hash) external_source.each do |type, config| definition = ErrorDefinition.new(type) definition.(config[:message]) if config[:message] definition.help_url(config[:help_url]) if config[:help_url] definition.validate! @error_definitions[type] = definition end end # 2. Handle inline block if block_given? dsl = ErrorsDSL.new dsl.instance_eval(&block) @error_definitions.merge!(dsl.definitions) end end |
#force_validation! ⇒ Object
Forces validation even if not explicitly defined in steps.
220 221 222 |
# File 'lib/next_station/operation/class_methods.rb', line 220 def force_validation! @validation_enforced = true end |
#has_step?(name, nodes = steps) ⇒ Boolean
Checks if a step exists in the operation.
240 241 242 243 244 |
# File 'lib/next_station/operation/class_methods.rb', line 240 def has_step?(name, nodes = steps) nodes.any? do |node| node.name == name || (node.type == :branch && has_step?(name, node.children)) end end |
#loaded_plugins ⇒ Array<Module>
Returns The plugins loaded into this operation.
294 295 296 |
# File 'lib/next_station/operation/class_methods.rb', line 294 def loaded_plugins @loaded_plugins ||= (superclass.respond_to?(:loaded_plugins) ? superclass.loaded_plugins.dup : []) end |
#plugin(name) ⇒ Object
Enables a plugin for the operation.
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/next_station/operation/class_methods.rb', line 277 def plugin(name) require 'dry-configurable' mod = NextStation::Plugins.load_plugin(name) loaded_plugins << mod extend mod::ClassMethods if mod.const_defined?(:ClassMethods) include mod::InstanceMethods if mod.const_defined?(:InstanceMethods) NextStation::Operation::Node.include mod::DSL if mod.const_defined?(:DSL) if mod.const_defined?(:Errors) && mod::Errors.respond_to?(:definitions) errors(mod::Errors.definitions) end mod.configure(self) if mod.respond_to?(:configure) end |
#process { ... } ⇒ Object
Defines the root execution block for the operation.
159 160 161 |
# File 'lib/next_station/operation/class_methods.rb', line 159 def process(&block) @root = Node.new(:root, &block) end |
#result_at(key) ⇒ Object
Defines the key in the state where the final result is stored.
95 96 97 |
# File 'lib/next_station/operation/class_methods.rb', line 95 def result_at(key) @result_key = key end |
#result_class ⇒ Class?
Returns The Dry::Struct class for the result.
135 136 137 |
# File 'lib/next_station/operation/class_methods.rb', line 135 def result_class @result_class || (superclass.result_class if superclass.respond_to?(:result_class)) end |
#result_key ⇒ Symbol?
Returns The key where the result is stored.
100 101 102 |
# File 'lib/next_station/operation/class_methods.rb', line 100 def result_key @result_key || (superclass.result_key if superclass.respond_to?(:result_key)) end |
#result_schema(struct_class = nil) { ... } ⇒ Object
Defines a Dry::Struct schema for the result value.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/next_station/operation/class_methods.rb', line 107 def result_schema(struct_class = nil, &block) require 'dry-struct' if @result_class raise NextStation::DoubleResultSchemaError, 'result_schema has already been defined' end if struct_class && block_given? raise NextStation::DoubleResultSchemaError, 'result_schema accepts either a Dry::Struct class OR a block, but not both.' end if struct_class if struct_class.is_a?(Class) && struct_class < Dry::Struct @result_class = struct_class else raise ArgumentError, 'result_schema requires a subclass of Dry::Struct' end elsif block_given? @result_class = Class.new(Dry::Struct, &block) const_set(:ResultSchema, @result_class) unless const_defined?(:ResultSchema, false) else raise ArgumentError, 'result_schema requires either a Dry::Struct class or a block' end @schema_enforced = true end |
#schema_enforced? ⇒ Boolean
Returns Whether schema enforcement is enabled.
150 151 152 153 154 155 |
# File 'lib/next_station/operation/class_methods.rb', line 150 def schema_enforced? return @schema_enforced unless @schema_enforced.nil? return superclass.schema_enforced? if superclass.respond_to?(:schema_enforced?) false end |
#skip_validation! ⇒ Object
Skips validation even if defined.
225 226 227 |
# File 'lib/next_station/operation/class_methods.rb', line 225 def skip_validation! @validation_enforced = false end |
#step(method_name, options = {}) ⇒ Object
Adds a step to the operation.
166 167 168 169 |
# File 'lib/next_station/operation/class_methods.rb', line 166 def step(method_name, = {}) @root ||= Node.new(:root) @root.step(method_name, ) end |
#steps ⇒ Array<Node>
Returns The steps defined for the operation.
180 181 182 |
# File 'lib/next_station/operation/class_methods.rb', line 180 def steps @root&.children || (superclass.steps if superclass.respond_to?(:steps)) || [] end |
#validate_with(contract_or_block = nil) { ... } ⇒ Object
Defines a Dry::Validation::Contract to validate the params.
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/next_station/operation/class_methods.rb', line 188 def validate_with(contract_or_block = nil, &block) require 'dry-validation' @validation_contract_class = if block_given? Class.new(Dry::Validation::Contract) do config..backend = :yaml config..top_namespace = 'next_station_validations' config..load_paths << File.('../../config/errors.yml', __FILE__) instance_eval(&block) end elsif contract_or_block.is_a?(Class) && contract_or_block < Dry::Validation::Contract contract_or_block else raise ValidationError, 'validate_with requires a block or a Dry::Validation::Contract class' end @validation_enforced = true end |
#validation_contract_class ⇒ Class?
Returns The validation contract class.
208 209 210 211 212 |
# File 'lib/next_station/operation/class_methods.rb', line 208 def validation_contract_class @validation_contract_class || (if superclass.respond_to?(:validation_contract_class) superclass.validation_contract_class end) end |
#validation_contract_instance ⇒ Dry::Validation::Contract?
Returns An instance of the validation contract.
215 216 217 |
# File 'lib/next_station/operation/class_methods.rb', line 215 def validation_contract_instance @validation_contract_instance ||= validation_contract_class&.new end |
#validation_enforced? ⇒ Boolean
Returns Whether validation is enforced.
230 231 232 233 234 |
# File 'lib/next_station/operation/class_methods.rb', line 230 def validation_enforced? return @validation_enforced unless @validation_enforced.nil? superclass.respond_to?(:validation_enforced?) ? superclass.validation_enforced? : false end |