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!(event_class, payload) ⇒ Boolean
private
Validates event payload against the Event class’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.
189 190 191 |
# File 'lib/servus/support/validator.rb', line 189 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.
181 182 183 |
# File 'lib/servus/support/validator.rb', line 181 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.
218 219 220 221 222 223 224 225 |
# File 'lib/servus/support/validator.rb', line 218 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)
241 242 243 244 245 246 247 248 249 |
# File 'lib/servus/support/validator.rb', line 241 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
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/servus/support/validator.rb', line 145 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.
264 265 266 267 268 |
# File 'lib/servus/support/validator.rb', line 264 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.
202 203 204 205 206 207 |
# File 'lib/servus/support/validator.rb', line 202 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!(event_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 Event class’s payload schema.
116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/servus/support/validator.rb', line 116 def self.validate_event_payload!(event_class, payload) schema = event_class.payload_schema enforce_schema_presence!(schema, event_class, :require_event_payload_schema) return true unless schema validate_data_against_schema!( payload, schema, "Invalid payload for event :#{event_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 |