Class: Aikido::Zen::Request::Schema::Definition Private

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/aikido/zen/request/schema/definition.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

The “JSON Schema”-like implementation that we extract from looking at the request body and/or query string.

Instance Method Summary collapse

Constructor Details

#initialize(definition) ⇒ Definition

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 new instance of Definition.



16
17
18
# File 'lib/aikido/zen/request/schema/definition.rb', line 16

def initialize(definition)
  @definition = definition
end

Instance Method Details

#==(other) ⇒ Object

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.



83
84
85
# File 'lib/aikido/zen/request/schema/definition.rb', line 83

def ==(other)
  as_json == other.as_json
end

#as_jsonObject

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.



87
88
89
90
91
92
93
# File 'lib/aikido/zen/request/schema/definition.rb', line 87

def as_json
  definition
    .transform_keys(&:to_s)
    .transform_values do |val|
      val.respond_to?(:as_json) ? val.as_json : val
    end
end

#inspectObject

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.



95
96
97
# File 'lib/aikido/zen/request/schema/definition.rb', line 95

def inspect
  format("#<%s %p>", self.class, definition)
end

#merge(other) ⇒ Aikido::Zen::Request::Schema::Definition Also known as: |

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.

Recursively merges this schema definition with another one.

  • Properties missing in one or the other schemas are treated as optional.

  • Merging any property with a null schema results in an optional schema.

  • Number and Integer schemas are merged into Number schemas, since it’s the more permissive of the types.

Other than that, everything else just results in additive merging, resulting in combining types together.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/aikido/zen/request/schema/definition.rb', line 34

def merge(other)
  case [self, other]

  # Merging with itself or with nil results in just a copy
  in [obj, ^obj | nil | EMPTY_SCHEMA]
    dup

  # objects where at least one of them has properties
  in [{type: "object", properties: _}, {type: "object", properties: _}] |
     [{type: "object", properties: _}, {type: "object"}] |
     [{type: "object"}, {type: "object", properties: _}]
    left, right = definition[:properties], other.definition[:properties]
    merged_props = (left.keys.to_a | right.keys.to_a)
      .map { |key| [key, left.fetch(key, NULL).merge(right.fetch(key, NULL))] }
      .to_h
    new(definition.merge(other.definition).merge(properties: merged_props))

  # arrays where at least one of them has items
  in [{type: "array", items: _}, {type: "array", items: _}] |
     [{type: "array", items: _}, {type: "array"}] |
     [{type: "array"}, {type: "array", items: _}]
    items = [definition[:items], other.definition[:items]].compact.reduce(:merge)
    new(definition.merge(other.definition).merge({items: items}.compact))

  # x | x => x
  in {type: type}, {type: ^type}
    new(definition.merge(other.definition))

  # any | null => any?
  in {type: "null"}, {type: _}
    new(other.definition.merge(optional: true))
  in {type: _}, {type: "null"}
    new(definition.merge(optional: true))

  # number | integer => number
  in [{type: "integer"}, {type: "number"}] |
     [{type: "number"}, {type: "integer"}]
    new(definition.merge(other.definition).merge(type: "number"))

  # x | y => [x, y] if x != y
  else
    left_type, right_type = definition[:type], other.definition[:type]
    types = [left_type, right_type].flatten.uniq.sort
    new(definition.merge(other.definition).merge(type: types))

  end
end