class Reynard::Specification

Wraps the YAML representation of an OpenAPI specification.

Public Class Methods

media_type_matches?(media_type, expression) click to toggle source
# File lib/reynard/specification.rb, line 75
def self.media_type_matches?(media_type, expression)
  return true unless media_type
  return true if expression == media_type

  false
end
new(filename:) click to toggle source
# File lib/reynard/specification.rb, line 6
def initialize(filename:)
  @filename = filename
  @data = read
end

Public Instance Methods

build_grouped_params(operation_node, params) click to toggle source

The specification tells us where a parameter should be included, they can be placed in path, query, header, or cookie. In order to get them in the correct place, we group them by their location.

build_grouped_params(operation_node, { 'q' => 'face' }) #=>
  { 'query' => { 'q' => 'face' } }
# File lib/reynard/specification.rb, line 30
def build_grouped_params(operation_node, params)
  return {} unless params

  GroupedParameters.new(dig(*operation_node, 'parameters'), params).to_h
end
default_base_url() click to toggle source
# File lib/reynard/specification.rb, line 20
def default_base_url
  servers.first&.url
end
dig(*path) click to toggle source

Digs a value out of the specification, taking $ref into account.

# File lib/reynard/specification.rb, line 12
def dig(*path)
  dig_into(@data, @data, path.dup)
end
media_type(operation_node, response_code, media_type) click to toggle source
# File lib/reynard/specification.rb, line 45
def media_type(operation_node, response_code, media_type)
  responses = dig(*operation_node, 'responses')
  response_code = responses.key?(response_code) ? response_code : 'default'
  response, media_type = media_type_response(responses, response_code, media_type)
  return unless response

  MediaType.new(
    node: [*operation_node, 'responses', response_code, 'content', media_type],
    schema_name: schema_name(response)
  )
end
media_type_response(responses, response_code, media_type) click to toggle source
# File lib/reynard/specification.rb, line 57
def media_type_response(responses, response_code, media_type)
  responses.dig(response_code, 'content').each do |expression, response|
    return response, expression if self.class.media_type_matches?(media_type, expression)
  end
  nil
end
operation(operation_name) click to toggle source
# File lib/reynard/specification.rb, line 36
def operation(operation_name)
  dig('paths').each do |path, operations|
    operations.each do |verb, operation|
      return Operation.new(node: ['paths', path, verb]) if operation_name == operation['operationId']
    end
  end
  nil
end
schema(media_type_node) click to toggle source
# File lib/reynard/specification.rb, line 64
def schema(media_type_node)
  schema = dig(*media_type_node, 'schema')
  return unless schema

  Schema.new(
    node: [*media_type_node, 'schema'],
    object_type: schema['type'],
    item_schema_name: item_schema_name(schema)
  )
end
servers() click to toggle source
# File lib/reynard/specification.rb, line 16
def servers
  dig('servers').map { |attributes| Server.new(attributes) }
end

Private Instance Methods

dig_into(data, cursor, path) click to toggle source
# File lib/reynard/specification.rb, line 90
def dig_into(data, cursor, path)
  while path.length.positive?
    cursor = cursor[path.first]
    return unless cursor

    path.shift
    next unless cursor.respond_to?(:key?) && cursor&.key?('$ref')

    # We currenly only supply references inside the document starting with #/.
    path = cursor['$ref'][2..].split('/') + path
    cursor = data
  end
  cursor
end
item_schema_name(schema) click to toggle source
# File lib/reynard/specification.rb, line 110
def item_schema_name(schema)
  ref = schema.dig('items', '$ref')
  ref&.split('/')&.last
end
object_name(_schema) click to toggle source
# File lib/reynard/specification.rb, line 115
def object_name(_schema)
  'Book'
end
read() click to toggle source
# File lib/reynard/specification.rb, line 84
def read
  File.open(@filename, encoding: 'UTF-8') do |file|
    YAML.safe_load(file)
  end
end
schema_name(response) click to toggle source
# File lib/reynard/specification.rb, line 105
def schema_name(response)
  ref = response.dig('schema', '$ref')
  ref&.split('/')&.last
end