Class: Servus::Support::Validator
- Inherits:
-
Object
- Object
- Servus::Support::Validator
- Defined in:
- lib/servus/support/validator.rb
Overview
Validates service arguments and results, and event payloads, against the
JSON schemas declared with the schema DSL.
Arguments are validated before call runs, so a service body can trust
the shape of its inputs. Result data is validated after it returns, so a
service that stops honouring its own contract fails loudly rather than
passing the wrong shape to its callers. Both raise
Errors::ValidationError, which signals a bug — in the
caller for arguments, in the service itself for results — and is not
meant to be rescued.
Schemas come from the schema DSL and nowhere else. The class-level
readers resolve any +$ref+s against Servus::Schema, so what arrives
here is always a self-contained schema.
Constant Summary collapse
- SCHEMA_TYPES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Schema kinds that may be requested from load_schema.
%w[arguments result failure payload].freeze
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
Raises if a schema is absent and the corresponding config flag is on.
-
.load_schema(klass, type) ⇒ Hash?
private
Returns a class's compiled schema of the given kind.
-
.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 service's 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 an event payload against the event'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.
175 176 177 |
# File 'lib/servus/support/validator.rb', line 175 def self.cache @schema_cache end |
.clear_cache! ⇒ Hash
Clears the schema cache.
Useful in tests, and in development after changing a schema. Registry changes invalidate compiled schemas on their own, so this is rarely needed in application code.
167 168 169 |
# File 'lib/servus/support/validator.rb', line 167 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.
Raises if a schema is absent and the corresponding config flag is on.
204 205 206 207 208 209 210 211 |
# File 'lib/servus/support/validator.rb', line 204 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 |
.load_schema(klass, 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.
Returns a class's compiled schema of the given kind.
Cached per class and kind. The underlying compilation is also memoized on the class itself and rebuilds when Servus::Schema changes, so this cache exists to skip the lookup, not to hold compilation results.
142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/servus/support/validator.rb', line 142 def self.load_schema(klass, type) type = type.to_s unless SCHEMA_TYPES.include?(type) raise ArgumentError, "unknown schema type #{type.inspect}. Valid: #{SCHEMA_TYPES.join(', ')}." end key = [klass, type] return @schema_cache[key] if @schema_cache.key?(key) @schema_cache[key] = klass.public_send(:"#{type}_schema") 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 service's arguments schema.
50 51 52 53 54 55 56 57 58 |
# File 'lib/servus/support/validator.rb', line 50 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.
188 189 190 191 192 193 |
# File 'lib/servus/support/validator.rb', line 188 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 an event payload against the event'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 = load_schema(event_class, 'payload') 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 |