Class: Verquest::Properties::Collection

Inherits:
Base
  • Object
show all
Defined in:
lib/verquest/properties/collection.rb

Overview

Collection property type for arrays of objects

Represents an array of complex objects in the schema. Used for defining collections of structured data objects.

Examples:

Define a collection of items with inline properties

products = Verquest::Properties::Collection.new(name: :products)
products.add(Verquest::Properties::Field.new(name: :id, type: :string, required: true))
products.add(Verquest::Properties::Field.new(name: :name, type: :string))

Define a collection referencing an existing schema

products = Verquest::Properties::Collection.new(
  name: :products,
  item: ProductRequest
)

Instance Attribute Summary collapse

Attributes inherited from Base

#map, #name, #nullable, #required

Instance Method Summary collapse

Methods inherited from Base

#mapping_value_key, #mapping_value_prefix

Methods included from HelperMethods::RequiredProperties

#dependent_required_properties, #required_properties

Constructor Details

#initialize(name:, item: nil, required: false, nullable: false, map: nil, **schema_options) ⇒ Collection

Initialize a new Collection property

Parameters:

  • name (String, Symbol)

    The name of the property

  • item (Verquest::Base, nil) (defaults to: nil)

    Optional reference to an external schema class

  • required (Boolean, Array<Symbol>) (defaults to: false)

    Whether this property is required, or array of dependency names

  • nullable (Boolean) (defaults to: false)

    Whether this property can be null

  • map (String, nil) (defaults to: nil)

    The mapping path for this property

  • schema_options (Hash)

    Additional JSON schema options for this property

Raises:

  • (ArgumentError)

    If attempting to map a collection to the root



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/verquest/properties/collection.rb', line 30

def initialize(name:, item: nil, required: false, nullable: false, map: nil, **schema_options)
  raise ArgumentError, "You can not map collection to the root" if map == "/"

  @properties = {}

  @name = name.to_s
  @item = item
  @required = required
  @nullable = nullable
  @map = map
  @schema_options = schema_options&.transform_keys(&:to_s)

  @type = if nullable
    %w[array null]
  else
    "array"
  end
end

Instance Attribute Details

#itemObject (readonly, private)

Returns the value of attribute item.



197
198
199
# File 'lib/verquest/properties/collection.rb', line 197

def item
  @item
end

#propertiesObject (readonly, private)

Returns the value of attribute properties.



197
198
199
# File 'lib/verquest/properties/collection.rb', line 197

def properties
  @properties
end

#schema_optionsObject (readonly, private)

Returns the value of attribute schema_options.



197
198
199
# File 'lib/verquest/properties/collection.rb', line 197

def schema_options
  @schema_options
end

#typeObject (readonly, private)

Returns the value of attribute type.



197
198
199
# File 'lib/verquest/properties/collection.rb', line 197

def type
  @type
end

Instance Method Details

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

Add a child property to this collection’s item definition

Parameters:

Returns:



53
54
55
# File 'lib/verquest/properties/collection.rb', line 53

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

#has_item?Boolean

Check if this collection references an external item schema

Returns:

  • (Boolean)

    True if the collection uses an external reference



60
61
62
# File 'lib/verquest/properties/collection.rb', line 60

def has_item?
  !item.nil?
end

#has_one_of?Boolean

Check if this collection contains a oneOf property as its item type

Returns:

  • (Boolean)

    True if the collection contains a oneOf property



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

def has_one_of?
  properties.values.size == 1 && properties.values.first.is_a?(Verquest::Properties::OneOf)
end

#mapping(key_prefix:, value_prefix:, mapping:, version:) ⇒ void

This method returns an undefined value.

Create mapping for this collection property and all its children

This method handles three different scenarios:

  1. When the collection references an external item schema (has_item? returns true)

    • Creates mappings by transforming keys from the referenced item schema

    • Adds array notation ([]) to indicate this is a collection

    • Prefixes all keys and values with the appropriate paths

  2. When the collection contains a oneOf property (has_one_of? returns true)

    • Creates variant-keyed mappings for discriminator-less oneOf support

    • Each variant gets array notation applied to its paths

  3. When the collection has inline item properties

    • Creates mappings for each property in the collection items

    • Each property gets mapped with array notation and appropriate prefixes

Parameters:

  • key_prefix (Array<String>)

    Prefix for the source key

  • value_prefix (Array<String>)

    Prefix for the target value

  • mapping (Hash)

    The mapping hash to be updated

  • version (String, nil)

    The version to create mapping for



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/verquest/properties/collection.rb', line 175

def mapping(key_prefix:, value_prefix:, mapping:, version:)
  if has_item?
    value_key_prefix = mapping_value_key(value_prefix: value_prefix, collection: true)

    reference_mapping = item.mapping(version:).dup
    reference_mapping.transform_keys! { |k| "#{(key_prefix + [name]).join("/")}[]/#{k}" }
    reference_mapping.transform_values! { |v| "#{value_key_prefix}/#{v}" }

    mapping.merge!(reference_mapping)
  elsif has_one_of?
    one_of_mapping = {}
    one_of_property.mapping(key_prefix: key_prefix + ["#{name}[]"], value_prefix: mapping_value_prefix(value_prefix: value_prefix, collection: true), mapping: one_of_mapping, version:)
    mapping.merge!(one_of_mapping)
  else
    properties.values.each do |property|
      property.mapping(key_prefix: key_prefix + ["#{name}[]"], value_prefix: mapping_value_prefix(value_prefix: value_prefix, collection: true), mapping:, version:)
    end
  end
end

#one_of_propertyVerquest::Properties::OneOf?

Returns the oneOf property if this collection contains one

Returns:



74
75
76
77
78
# File 'lib/verquest/properties/collection.rb', line 74

def one_of_property
  return nil unless has_one_of?

  properties.values.first
end

#to_schemaHash

Generate JSON schema definition for this collection property

Returns:

  • (Hash)

    The schema definition for this collection property



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/verquest/properties/collection.rb', line 83

def to_schema
  if has_item?
    {
      name => {
        "type" => type,
        "items" => {
          "$ref" => item.to_ref
        }
      }.merge(schema_options)
    }
  elsif has_one_of?
    {
      name => {
        "type" => type,
        "items" => one_of_property.to_schema[one_of_property.name] || one_of_property.to_schema
      }.merge(schema_options)
    }
  else
    {
      name => {
        "type" => type,
        "items" => {
          "type" => "object",
          "required" => required_properties,
          "properties" => properties.transform_values { |property| property.to_schema[property.name] },
          "additionalProperties" => Verquest.configuration.default_additional_properties
        }.tap do |schema|
          schema["dependentRequired"] = dependent_required_properties if dependent_required_properties.any?
        end
      }.merge(schema_options)
    }
  end
end

#to_validation_schema(version: nil) ⇒ Hash

Generate validation schema for this collection property

Parameters:

  • version (String, nil) (defaults to: nil)

    The version to generate validation schema for

Returns:

  • (Hash)

    The validation schema for this collection property



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/verquest/properties/collection.rb', line 121

def to_validation_schema(version: nil)
  if has_item?
    {
      name => {
        "type" => type,
        "items" => item.to_validation_schema(version: version)
      }.merge(schema_options)
    }
  elsif has_one_of?
    one_of_schema = one_of_property.to_validation_schema(version: version)
    {
      name => {
        "type" => type,
        "items" => one_of_schema[one_of_property.name] || one_of_schema
      }.merge(schema_options)
    }
  else
    {
      name => {
        "type" => type,
        "items" => {
          "type" => "object",
          "required" => required_properties,
          "properties" => properties.transform_values { |property| property.to_validation_schema(version: version)[property.name] },
          "additionalProperties" => Verquest.configuration.default_additional_properties
        }.tap do |schema|
          schema["dependentRequired"] = dependent_required_properties if dependent_required_properties.any?
        end
      }.merge(schema_options)
    }
  end
end