Class: Servus::Support::Validator
- Inherits:
-
Object
- Object
- Servus::Support::Validator
- Defined in:
- lib/servus/support/validator.rb
Overview
Handles JSON Schema validation for service arguments and results.
The Validator class provides automatic validation of service inputs and outputs against JSON Schema definitions. Schemas can be defined as inline constants (ARGUMENTS_SCHEMA, RESULT_SCHEMA) or as external JSON files.
Class Method Summary collapse
-
.cache ⇒ Hash
private
Returns the current schema cache.
-
.clear_cache! ⇒ Hash
Clears the schema cache.
-
.enforce_schema_presence!(schema, klass, config_flag) ⇒ Hash?
private
Returns the schema if present.
-
.fetch_schema_from_sources(dsl_schema, inline_schema_constant, schema_path) ⇒ Hash?
private
Fetches schema from DSL, inline constant, or file.
-
.load_schema(service_class, type) ⇒ Hash?
private
Loads and caches a schema for a service.
-
.parse_service_namespace(service_class) ⇒ String
private
Converts service class name to file path namespace.
-
.result_schema_for(service_class, result) ⇒ Array(Hash, String), Array(nil, nil)
private
Resolves the schema and type label for a service result.
-
.validate_arguments!(service_class, args) ⇒ Boolean
private
Validates service arguments against the ARGUMENTS_SCHEMA.
-
.validate_data_against_schema!(data, schema, message_prefix) ⇒ void
private
Serializes data and validates it against a JSON schema.
-
.validate_event_payload!(handler_class, payload) ⇒ Boolean
private
Validates event payload against the handler’s payload schema.
-
.validate_result!(service_class, result) ⇒ Servus::Support::Response
private
Validates service result data against the appropriate schema.
Class Method Details
.cache ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the current schema cache.
190 191 192 |
# File 'lib/servus/support/validator.rb', line 190 def self.cache @schema_cache end |
.clear_cache! ⇒ Hash
Clears the schema cache.
Useful in development when schema files are modified, or in tests to ensure fresh schema loading between test cases.
182 183 184 |
# File 'lib/servus/support/validator.rb', line 182 def self.clear_cache! @schema_cache = {} end |
.enforce_schema_presence!(schema, klass, config_flag) ⇒ Hash?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the schema if present. Raises if absent and the config flag is enabled.
219 220 221 222 223 224 225 226 |
# File 'lib/servus/support/validator.rb', line 219 def self.enforce_schema_presence!(schema, klass, config_flag) return schema if schema return unless Servus.config.public_send(config_flag) raise Servus::Support::Errors::SchemaRequiredError, "#{klass.name} schema missing! #{config_flag} is set to true." end |
.fetch_schema_from_sources(dsl_schema, inline_schema_constant, schema_path) ⇒ Hash?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Fetches schema from DSL, inline constant, or file.
Implements the schema resolution precedence:
-
DSL-defined schema (if provided)
-
Inline constant (if provided)
-
File at schema_path (if exists)
-
nil (no schema found)
242 243 244 245 246 247 248 249 250 |
# File 'lib/servus/support/validator.rb', line 242 def self.fetch_schema_from_sources(dsl_schema, inline_schema_constant, schema_path) if dsl_schema dsl_schema.with_indifferent_access elsif inline_schema_constant inline_schema_constant.with_indifferent_access elsif File.exist?(schema_path) JSON.load_file(schema_path).with_indifferent_access end end |
.load_schema(service_class, type) ⇒ Hash?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Loads and caches a schema for a service.
Implements a three-tier lookup strategy:
-
Check for schema defined via DSL method (service_class.arguments_schema/result_schema)
-
Check for inline constant (ARGUMENTS_SCHEMA or RESULT_SCHEMA)
-
Fall back to JSON file in app/schemas/services/namespace/type.json
Schemas are cached after first load for performance.
rubocop:disable Metrics/MethodLength
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/servus/support/validator.rb', line 146 def self.load_schema(service_class, type) # Get service path based on class name (e.g., "process_payment" from "Servus::ProcessPayment::Service") service_namespace = parse_service_namespace(service_class) schema_path = Servus.config.schema_path_for(service_namespace, type) # Return from cache if available return @schema_cache[schema_path] if @schema_cache.key?(schema_path) # Check for DSL-defined schema first dsl_schema = case type when 'arguments' then service_class.arguments_schema when 'result' then service_class.result_schema when 'failure' then service_class.failure_schema end inline_schema_constant_name = "#{service_class}::#{type.upcase}_SCHEMA" inline_schema_constant = if Object.const_defined?(inline_schema_constant_name) Object.const_get(inline_schema_constant_name) end @schema_cache[schema_path] = fetch_schema_from_sources(dsl_schema, inline_schema_constant, schema_path) @schema_cache[schema_path] end |
.parse_service_namespace(service_class) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Converts service class name to file path namespace.
Transforms a class name like “Services::ProcessPayment::Service” into “services/process_payment” for locating schema files.
265 266 267 268 269 |
# File 'lib/servus/support/validator.rb', line 265 def self.parse_service_namespace(service_class) service_class.name.split('::')[..-2].map do |s| s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase end.join('/') end |
.result_schema_for(service_class, result) ⇒ Array(Hash, String), Array(nil, nil)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Resolves the schema and type label for a service result.
95 96 97 98 99 100 101 102 103 |
# File 'lib/servus/support/validator.rb', line 95 def self.result_schema_for(service_class, result) if result.success? schema = load_schema(service_class, 'result') enforce_schema_presence!(schema, service_class, :require_service_result_schema) [schema, 'result'] elsif result.data [load_schema(service_class, 'failure'), 'failure'] end end |
.validate_arguments!(service_class, args) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Validates service arguments against the ARGUMENTS_SCHEMA.
Checks arguments against either an inline ARGUMENTS_SCHEMA constant or a file-based schema at app/schemas/services/namespace/arguments.json. Validation is skipped if no schema is defined.
46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/servus/support/validator.rb', line 46 def self.validate_arguments!(service_class, args) schema = load_schema(service_class, 'arguments') enforce_schema_presence!(schema, service_class, :require_service_arguments_schema) return true unless schema validate_data_against_schema!( args, schema, "Invalid arguments for #{service_class.name}" ) true end |
.validate_data_against_schema!(data, schema, message_prefix) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Serializes data and validates it against a JSON schema.
203 204 205 206 207 208 |
# File 'lib/servus/support/validator.rb', line 203 def self.validate_data_against_schema!(data, schema, ) errors = JSON::Validator.fully_validate(schema, data.as_json) return if errors.empty? raise Servus::Base::ValidationError, "#{}: #{errors.join(', ')}" end |
.validate_event_payload!(handler_class, payload) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Validates event payload against the handler’s payload schema.
117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/servus/support/validator.rb', line 117 def self.validate_event_payload!(handler_class, payload) schema = handler_class.payload_schema enforce_schema_presence!(schema, handler_class, :require_event_payload_schema) return true unless schema validate_data_against_schema!( payload, schema, "Invalid payload for event :#{handler_class.event_name}" ) true end |
.validate_result!(service_class, result) ⇒ Servus::Support::Response
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Validates service result data against the appropriate schema.
For successful responses, validates against the result schema. For failure responses with data, validates against the failure schema. Failure responses without data are skipped.
75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/servus/support/validator.rb', line 75 def self.validate_result!(service_class, result) schema, schema_type = result_schema_for(service_class, result) return result unless schema validate_data_against_schema!( result.data, schema, "Invalid #{schema_type} structure from #{service_class.name}" ) result end |