Class: Verquest::Version

Inherits:
Object
  • Object
show all
Includes:
HelperMethods::RequiredProperties
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

Methods included from HelperMethods::RequiredProperties

#dependent_required_properties, #required_properties

Constructor Details

#initialize(name:) ⇒ Version

Initialize a new Version instance

Parameters:

  • name (String)

    The name/identifier of the version



57
58
59
60
61
# File 'lib/verquest/version.rb', line 57

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

Instance Attribute Details

#descriptionString

Returns Description of this version.

Returns:

  • (String)

    Description of this version



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

attr_accessor :schema_options, :description

#external_mappingObject (readonly)

Returns the value of attribute external_mapping.



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

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

#mappingHash (readonly)

Returns The mapping from schema property paths to internal paths.

Returns:

  • (Hash)

    The mapping from schema property paths to internal paths



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

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

#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”)



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

def name
  @name
end

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

Returns The properties that define the version’s schema.

Returns:



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

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

#schemaHash (readonly)

Returns The generated JSON schema for this version.

Returns:

  • (Hash)

    The generated JSON schema for this version



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

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

#schema_optionsHash

Returns Additional JSON schema options for this version.

Returns:

  • (Hash)

    Additional JSON schema options for this version



51
52
53
# File 'lib/verquest/version.rb', line 51

def schema_options
  @schema_options
end

#transformerVerquest::Transformer (readonly)

Returns The transformer that applies the mapping.

Returns:



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

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

#validation_schemaHash (readonly)

Returns The schema used for request validation.

Returns:

  • (Hash)

    The schema used for request validation



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

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

Instance Method Details

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

Add a property to this version

Parameters:

Returns:



67
68
69
# File 'lib/verquest/version.rb', line 67

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



94
95
96
97
98
99
100
101
102
# File 'lib/verquest/version.rb', line 94

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.to_sym)

    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



84
85
86
# File 'lib/verquest/version.rb', line 84

def has?(property_name)
  properties.key?(property_name.to_s)
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



195
196
197
# File 'lib/verquest/version.rb', line 195

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:



183
184
185
186
187
188
189
# File 'lib/verquest/version.rb', line 183

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

  {}.tap do |mapping|
    properties[property.to_s].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



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/verquest/version.rb', line 107

def prepare
  return if frozen?

  unless schema_options.key?("additionalProperties")
    schema_options["additionalProperties"] = Verquest.configuration.default_additional_properties
  end

  schema_options.delete_if { |_, v| v.nil? }

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

  freeze
end

#prepare_external_mappingHash (private)

Prepares the inverted parameter mapping for this version

Inverts the standard mapping to create a reverse lookup from internal attribute names back to external parameter names. This is useful when transforming internal data back to the external API representation.

Returns:

  • (Hash)

    The frozen inverted mapping where keys are internal attribute paths and values are the corresponding external schema paths

See Also:



262
263
264
# File 'lib/verquest/version.rb', line 262

def prepare_external_mapping
  @external_mapping = mapping.invert.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:



243
244
245
246
247
248
249
250
251
# File 'lib/verquest/version.rb', line 243

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



208
209
210
211
212
213
214
215
216
217
# File 'lib/verquest/version.rb', line 208

def prepare_schema
  @schema = {
    "type" => "object",
    "description" => description,
    "required" => required_properties,
    "properties" => properties.transform_values { |property| property.to_schema[property.name] }
  }.merge(schema_options).tap do |schema|
    schema["dependentRequired"] = dependent_required_properties if dependent_required_properties.any?
  end.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



225
226
227
228
229
230
231
232
233
234
# File 'lib/verquest/version.rb', line 225

def prepare_validation_schema
  @validation_schema = {
    "type" => "object",
    "description" => description,
    "required" => required_properties,
    "properties" => properties.transform_values { |property| property.to_validation_schema(version: name)[property.name] }
  }.merge(schema_options).tap do |schema|
    schema["dependentRequired"] = dependent_required_properties if dependent_required_properties.any?
  end.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:



76
77
78
# File 'lib/verquest/version.rb', line 76

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

#valid_schema?Boolean

Validate the schema against the metaschema

Returns:

  • (Boolean)

    true if the schema is valid, false otherwise



128
129
130
131
132
133
# File 'lib/verquest/version.rb', line 128

def valid_schema?
  JSONSchemer.valid_schema?(
    validation_schema,
    meta_schema: Verquest.configuration.json_schema_uri
  )
end

#validate_params(params:) ⇒ Array<Hash>

Validate request parameters against the version’s validation schema

Parameters:

  • params (Hash)

    The request parameters to validate

Returns:

  • (Array<Hash>)

    An array of validation error details, or empty if valid



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/verquest/version.rb', line 161

def validate_params(params:)
  schemer = JSONSchemer.schema(
    validation_schema,
    meta_schema: Verquest.configuration.json_schema_uri,
    insert_property_defaults: Verquest.configuration.insert_property_defaults
  )

  schemer.validate(params).map do |error|
    {
      pointer: error["data_pointer"],
      type: error["type"],
      message: error["error"],
      details: error["details"]
    }
  end
end

#validate_schemaArray<Hash>

Validate the schema against the metaschema and return detailed errors

This method validates the schema against the configured JSON Schema metaschema and returns detailed validation errors if any are found. It uses the JSONSchemer library with the schema version specified in the configuration.

Returns:

  • (Array<Hash>)

    An array of validation error details, empty if schema is valid

See Also:



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/verquest/version.rb', line 143

def validate_schema
  JSONSchemer.validate_schema(
    validation_schema,
    meta_schema: Verquest.configuration.json_schema_uri
  ).map do |error|
    {
      pointer: error["data_pointer"],
      type: error["type"],
      message: error["error"],
      details: error["details"]
    }
  end
end