Class: Verquest::Version

Inherits:
Object
  • Object
show all
Defined in:
lib/verquest/version.rb

Overview

Represents a specific version of an API request schema

The Version class manages the properties, schema generation, and mapping for a specific version of an API request. It holds the collection of properties that define the request structure and handles transforming between different property naming conventions.

Examples:

version = Verquest::Version.new(name: "2023-01")
version.add(Verquest::Properties::Field.new(name: :email, type: :string))
version.prepare

# Generate schema
schema = version.schema

# Get mapping
mapping = version.mapping

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:) ⇒ Version

Initialize a new Version instance

Parameters:

  • name (String)

    The name/identifier of the version



52
53
54
55
56
# File 'lib/verquest/version.rb', line 52

def initialize(name:)
  @name = name
  @schema_options = {}
  @properties = {}
end

Instance Attribute Details

#descriptionString

Returns Description of this version.

Returns:

  • (String)

    Description of this version



46
# File 'lib/verquest/version.rb', line 46

attr_accessor :schema_options, :description

#mappingHash (readonly)

Returns The mapping from schema property paths to internal paths.

Returns:

  • (Hash)

    The mapping from schema property paths to internal paths



39
# File 'lib/verquest/version.rb', line 39

attr_reader :name, :properties, :schema, :validation_schema, :mapping, :transformer

#nameString (readonly)

Returns The name/identifier of the version (e.g., “2023-01”).

Returns:

  • (String)

    The name/identifier of the version (e.g., “2023-01”)



39
40
41
# File 'lib/verquest/version.rb', line 39

def name
  @name
end

#propertiesHash<Symbol, Verquest::Properties::Base> (readonly)

Returns The properties that define the version’s schema.

Returns:



39
# File 'lib/verquest/version.rb', line 39

attr_reader :name, :properties, :schema, :validation_schema, :mapping, :transformer

#schemaHash (readonly)

Returns The generated JSON schema for this version.

Returns:

  • (Hash)

    The generated JSON schema for this version



39
# File 'lib/verquest/version.rb', line 39

attr_reader :name, :properties, :schema, :validation_schema, :mapping, :transformer

#schema_optionsHash

Returns Additional JSON schema options for this version.

Returns:

  • (Hash)

    Additional JSON schema options for this version



46
47
48
# File 'lib/verquest/version.rb', line 46

def schema_options
  @schema_options
end

#transformerObject (readonly)

Returns the value of attribute transformer.



39
# File 'lib/verquest/version.rb', line 39

attr_reader :name, :properties, :schema, :validation_schema, :mapping, :transformer

#validation_schemaHash (readonly)

Returns The schema used for request validation.

Returns:

  • (Hash)

    The schema used for request validation



39
# File 'lib/verquest/version.rb', line 39

attr_reader :name, :properties, :schema, :validation_schema, :mapping, :transformer

Instance Method Details

#add(property) ⇒ Verquest::Properties::Base

Add a property to this version

Parameters:

Returns:



62
63
64
# File 'lib/verquest/version.rb', line 62

def add(property)
  properties[property.name] = property
end

#copy_from(version, exclude_properties: []) ⇒ void

This method returns an undefined value.

Copy properties from another version

Parameters:

  • version (Verquest::Version)

    The version to copy properties from

  • exclude_properties (Array<Symbol>) (defaults to: [])

    Names of properties to not copy

Raises:

  • (ArgumentError)

    If version is not a Verquest::Version instance



89
90
91
92
93
94
95
96
97
# File 'lib/verquest/version.rb', line 89

def copy_from(version, exclude_properties: [])
  raise ArgumentError, "Expected a Verquest::Version instance" unless version.is_a?(Version)

  version.properties.values.each do |property|
    next if exclude_properties.include?(property.name)

    add(property)
  end
end

#has?(property_name) ⇒ Boolean

Check if this version has a property with the given name

Parameters:

  • property_name (Symbol, String)

    The name of the property to check

Returns:

  • (Boolean)

    true if the property exists, false otherwise



79
80
81
# File 'lib/verquest/version.rb', line 79

def has?(property_name)
  properties.key?(property_name)
end

#map_params(params) ⇒ Hash

Map request parameters to internal representation using the transformer

Parameters:

  • params (Hash)

    The request parameters to map

Returns:

  • (Hash)

    The mapped parameters



158
159
160
# File 'lib/verquest/version.rb', line 158

def map_params(params)
  transformer.call(params)
end

#mapping_for(property) ⇒ Hash

Get the mapping for a specific property

Parameters:

  • property (Symbol, String)

    The property name to get the mapping for

Returns:

  • (Hash)

    The mapping for the property

Raises:



146
147
148
149
150
151
152
# File 'lib/verquest/version.rb', line 146

def mapping_for(property)
  raise PropertyNotFoundError.new("Property '#{property}' is not defined on '#{name}'") unless has?(property)

  {}.tap do |mapping|
    properties[property].mapping(key_prefix: [], value_prefix: [], mapping: mapping, version: name)
  end
end

#preparevoid

This method returns an undefined value.

Prepare this version by generating schema and creating transformer



102
103
104
105
106
107
108
109
110
111
# File 'lib/verquest/version.rb', line 102

def prepare
  return if frozen?

  prepare_schema
  prepare_validation_schema
  prepare_mapping
  @transformer = Transformer.new(mapping: mapping)

  freeze
end

#prepare_mappingHash (private)

Prepares the parameter mapping for this version

Collects mappings from all properties in this version and checks for duplicate mappings, which would cause conflicts during transformation.

Returns:

  • (Hash)

    The mapping from schema property paths to internal paths

Raises:



202
203
204
205
206
207
208
209
210
# File 'lib/verquest/version.rb', line 202

def prepare_mapping
  @mapping = properties.values.each_with_object({}) do |property, mapping|
    property.mapping(key_prefix: [], value_prefix: [], mapping: mapping, version: name)
  end

  if (duplicates = mapping.keys.select { |k| mapping.values.count(k) > 1 }).any?
    raise MappingError.new("Mapping must be unique. Found duplicates in version '#{name}': #{duplicates.join(", ")}")
  end
end

#prepare_schemaHash (private)

Generates the JSON schema for this version

Creates a schema object with type, description, required properties, and property definitions based on the properties in this version. The schema is frozen to prevent modification after preparation.

Returns:

  • (Hash)

    The frozen schema hash



171
172
173
174
175
176
177
178
# File 'lib/verquest/version.rb', line 171

def prepare_schema
  @schema = {
    type: :object,
    description: description,
    required: properties.values.select(&:required).map(&:name),
    properties: properties.transform_values { |property| property.to_schema[property.name] }
  }.merge(schema_options).freeze
end

#prepare_validation_schemaHash (private)

Generates the validation schema for this version

Similar to prepare_schema but specifically for validation purposes. The validation schema will include all referenced components and properties.

Returns:

  • (Hash)

    The frozen validation schema hash



186
187
188
189
190
191
192
193
# File 'lib/verquest/version.rb', line 186

def prepare_validation_schema
  @validation_schema = {
    type: :object,
    description: description,
    required: properties.values.select(&:required).map(&:name),
    properties: properties.transform_values { |property| property.to_validation_schema(version: name)[property.name] }
  }.merge(schema_options).freeze
end

#remove(property_name) ⇒ Verquest::Properties::Base

Remove a property from this version by name

Parameters:

  • property_name (Symbol, String)

    The name of the property to remove

Returns:

Raises:



71
72
73
# File 'lib/verquest/version.rb', line 71

def remove(property_name)
  properties.delete(property_name) || raise(PropertyNotFoundError.new("Property '#{property_name}' is not defined on '#{name}"))
end

#validate_params(params:, component_reference:, remove_extra_root_keys:) ⇒ Array<Hash>

Validate request parameters against the version’s validation schema

Parameters:

  • params (Hash)

    The request parameters to validate

  • component_reference (String)

    A reference string for components in the schema

  • remove_extra_root_keys (Boolean)

    Whether to remove extra keys not in the schema

Returns:

  • (Array<Hash>)

    An array of validation error details, or empty if valid



129
130
131
132
133
134
135
136
137
138
139
# File 'lib/verquest/version.rb', line 129

def validate_params(params:, component_reference:, remove_extra_root_keys:)
  schema_name = Verquest.configuration.json_schema_version

  result = JSON::Validator.fully_validate(validation_schema, params, version: schema_name, errors_as_objects: true)
  return result if result.empty?

  result.map do |error|
    schema = error.delete(:schema)
    error[:message].gsub!(schema.to_s, component_reference)
  end
end

#validate_schemaBoolean

Validate the schema against the metaschema

Returns:

  • (Boolean)

    true if the schema is valid, false otherwise



116
117
118
119
120
121
# File 'lib/verquest/version.rb', line 116

def validate_schema
  schema_name = Verquest.configuration.json_schema_version

  metaschema = JSON::Validator.validator_for_name(schema_name).metaschema
  JSON::Validator.validate(metaschema, validation_schema)
end