Class: Servus::Schema::Ref

Inherits:
Object
  • Object
show all
Defined in:
lib/servus/schema/ref.rb

Overview

A parsed $ref pointing at a registered schema fragment.

Servus supports exactly two ref forms:

#/core                  # the whole fragment registered as "core"
#/core/$defs/amount     # a path walked within it

Segments are literal hash keys, not JSON Pointer tokens — there is no +~0+/+~1+ unescaping and no array indexing. $defs carries no special meaning; it is a conventional place to put definitions, and any key works.

Everything else is rejected by Ref.parse with a message that names what was wrong. That matters most for local refs: #/$defs/amount would otherwise parse as a request for a fragment registered under the key $defs and fail as a confusing lookup miss rather than as the unsupported form it is.

See Also:

Constant Summary collapse

REJECTIONS =

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.

Ref forms Servus does not implement, paired with the reason.

Checked in order; the first match raises InvalidRefError.

[
  [
    ->(value) { !value.start_with?('#/') },
    'Servus resolves refs against registered schema fragments, which always take the form ' \
    '"#/<key>" or "#/<key>/<path>". Remote and file refs are not supported.'
  ],
  [
    ->(value) { value == '#/' },
    'it names no schema fragment key.'
  ],
  [
    ->(value) { value.delete_prefix('#/').start_with?('$') },
    'it looks like a local ref. Refs resolve against registered fragments, not against the ' \
    'enclosing document. Register the shared definition as a fragment and reference it as ' \
    '"#/<key>/...".'
  ]
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value) ⇒ Ref

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 Ref.

Parameters:

  • value (String)

    a ref string already known to be well-formed



81
82
83
84
# File 'lib/servus/schema/ref.rb', line 81

def initialize(value)
  @value = value
  @key, *@segments = value.delete_prefix('#/').split('/')
end

Instance Attribute Details

#keyString (readonly)

The registry key the ref names.

Returns:

  • (String)


54
55
56
# File 'lib/servus/schema/ref.rb', line 54

def key
  @key
end

#segmentsArray<String> (readonly)

Path segments to walk within the fragment. Empty for a whole-fragment ref.

Returns:

  • (Array<String>)


59
60
61
# File 'lib/servus/schema/ref.rb', line 59

def segments
  @segments
end

#valueString (readonly)

The original ref string.

Returns:

  • (String)


49
50
51
# File 'lib/servus/schema/ref.rb', line 49

def value
  @value
end

Class Method Details

.parse(value) ⇒ Ref

Parses a $ref value.

Examples:

Servus::Schema::Ref.parse('#/core/$defs/amount').key  # => "core"

Parameters:

  • value (Object)

    the raw $ref value from a schema

Returns:

Raises:



69
70
71
72
73
74
75
76
77
# File 'lib/servus/schema/ref.rb', line 69

def self.parse(value)
  raise InvalidRefError, "$ref must be a String, got #{value.class}: #{value.inspect}" unless value.is_a?(String)

  _, explanation = REJECTIONS.find { |rejects, _| rejects.call(value) }

  raise InvalidRefError, "#{value.inspect} is not a supported $ref — #{explanation}" if explanation

  new(value)
end