class Heroics::LinkSchema

A wrapper around a bare link element for a resource in a JSON schema to make it easier to use.

Constants

PARAMETER_REGEX

Match parameters in definition strings.

Attributes

description[R]
name[R]
resource_name[R]

Public Class Methods

new(schema, resource_name, link_index) click to toggle source

Instantiate a link schema.

@param schema [Hash] The bare JSON schema to wrap. @param resource_name [String] The name of the resource to identify in

the schema.

@param link_index [Fixnum] The index of the link in the resource schema.

# File lib/heroics/schema.rb, line 112
def initialize(schema, resource_name, link_index)
  @schema = schema
  @resource_name = resource_name
  @link_index = link_index
  @name = Heroics.ruby_name(link_schema['title'])
  @description = link_schema['description']
end

Public Instance Methods

content_type() click to toggle source

Get the Content-Type for this link.

@return [String] The Content-Type value

# File lib/heroics/schema.rb, line 144
def content_type
  link_schema['encType'] || 'application/json'
end
encode(body) click to toggle source
# File lib/heroics/schema.rb, line 148
def encode(body)
  case content_type
  when 'application/x-www-form-urlencoded'
    URI.encode_www_form(body)
  when /application\/.*json/
    MultiJson.dump(body)
  end
end
example_body() click to toggle source

Get an example request body.

@return [Hash] A sample request body.

# File lib/heroics/schema.rb, line 181
def example_body
  if body_schema = link_schema['schema']
    definitions = @schema['definitions'][@resource_name]['definitions']
    Hash[body_schema['properties'].keys.map do |property|
      # FIXME This is wrong! -jkakar
      if definitions.has_key?(property)
        example = definitions[property]['example']
      else
        example = ''
      end
      [property, example]
    end]
  end
end
format_path(parameters) click to toggle source

Inject parameters into the link href and return the body, if it exists.

@param parameters [Array] The list of parameters to inject into the

path.

@raise [ArgumentError] Raised if either too many or too few parameters

were provided.

@return [String,Object] A path and request body pair. The body value is

nil if a payload wasn't included in the list of parameters.
# File lib/heroics/schema.rb, line 204
def format_path(parameters)
  path = link_schema['href']
  parameter_size = path.scan(PARAMETER_REGEX).size
  too_few_parameters = parameter_size > parameters.size
  # FIXME We should use the schema to detect when a request body is
  # permitted and do the calculation correctly here. -jkakar
  too_many_parameters = parameter_size < (parameters.size - 1)
  if too_few_parameters || too_many_parameters
    raise ArgumentError.new("wrong number of arguments " +
                            "(#{parameters.size} for #{parameter_size})")
  end

  (0...parameter_size).each do |i|
    path = path.sub(PARAMETER_REGEX, format_parameter(parameters[i]))
  end
  body = parameters.slice(parameter_size)
  return path, body
end
method() click to toggle source

Get the HTTP method for this link.

@return [Symbol] The HTTP method.

# File lib/heroics/schema.rb, line 137
def method
  link_schema['method'].downcase.to_sym
end
needs_request_body?() click to toggle source
# File lib/heroics/schema.rb, line 174
def needs_request_body?
  return link_schema.has_key?('schema')
end
parameter_details() click to toggle source

Get the names and descriptions of the parameters this link expects.

@return [Hash<String, String>] A list of hashes with `name` and

`description` key/value pairs describing parameters.
# File lib/heroics/schema.rb, line 169
def parameter_details
  parameter_names = link_schema['href'].scan(PARAMETER_REGEX)
  resolve_parameter_details(parameter_names)
end
parameters() click to toggle source

Get the names of the parameters this link expects.

@return [Array<String>] The parameters.

# File lib/heroics/schema.rb, line 160
def parameters
  parameter_names = link_schema['href'].scan(PARAMETER_REGEX)
  resolve_parameters(parameter_names)
end
pretty_name() click to toggle source

Get the link name in pretty form.

@return [String] The pretty link name.

# File lib/heroics/schema.rb, line 130
def pretty_name
  Heroics.pretty_name(name)
end
pretty_resource_name() click to toggle source

Get the resource name in pretty form.

@return [String] The pretty resource name.

# File lib/heroics/schema.rb, line 123
def pretty_resource_name
  Heroics.pretty_name(resource_name)
end

Private Instance Methods

format_parameter(parameter) click to toggle source

Convert a path parameter to a format suitable for use in a path.

@param [Fixnum,String,TrueClass,FalseClass,Time] The parameter to format. @return [String] The formatted parameter.

# File lib/heroics/schema.rb, line 335
def format_parameter(parameter)
  formatted_parameter = parameter.instance_of?(Time) ? iso_format(parameter) : parameter.to_s
  WEBrick::HTTPUtils.escape formatted_parameter
end
iso_format(time) click to toggle source

Convert a time to an ISO 8601 combined data and time format.

@param time [Time] The time to convert to ISO 8601 format. @return [String] An ISO 8601 date in `YYYY-MM-DDTHH:MM:SSZ` format.

# File lib/heroics/schema.rb, line 344
def iso_format(time)
  time.getutc.strftime('%Y-%m-%dT%H:%M:%SZ')
end
lookup_parameter(path, schema) click to toggle source

Recursively walk the object hierarchy in the schema to resolve a given path. This is used to find property information related to definitions in link hrefs.

@param path [Array<String>] An array of paths to walk, such as

['definitions', 'resource', 'definitions', 'property'].

@param schema [Hash] The schema to walk.

# File lib/heroics/schema.rb, line 321
def lookup_parameter(path, schema)
  key = path[0]
  remaining = path[1..-1]
  if remaining.empty?
    return schema[key]
  else
    lookup_parameter(remaining, schema[key])
  end
end
resolve_parameter_details(parameters) click to toggle source

Get the parameters this link expects.

@param parameters [Array] The names of the parameter definitions to

convert to parameter names.

@return [Array<Parameter|ParameterChoice>] A list of parameter instances

that represent parameters to be injected into the link URL.
# File lib/heroics/schema.rb, line 273
def resolve_parameter_details(parameters)
  parameters.map do |parameter|
    # URI decode parameters and strip the leading '{(' and trailing ')}'.
    parameter = ::URI::DEFAULT_PARSER.unescape(parameter[2..-3])

    # Split the path into components and discard the leading '#' that
    # represents the root of the schema.
    path = parameter.split('/')[1..-1]
    info = lookup_parameter(path, @schema)
    # The reference can be one of several values.
    resource_name = path[1].gsub('-', '_')
    if info.has_key?('anyOf')
      ParameterChoice.new(resource_name,
                          unpack_multiple_parameters(info['anyOf']))
    elsif info.has_key?('oneOf')
      ParameterChoice.new(resource_name,
                          unpack_multiple_parameters(info['oneOf']))
    else
      name = path[-1]
      Parameter.new(resource_name, name, info['description'])
    end
  end
end
resolve_parameters(parameters) click to toggle source

Get the names of the parameters this link expects.

@param parameters [Array] The names of the parameter definitions to

convert to parameter names.

@return [Array<String>] The parameters.

# File lib/heroics/schema.rb, line 240
def resolve_parameters(parameters)
  properties = @schema['definitions'][@resource_name]['properties']
  return [''] if properties.nil?
  definitions = Hash[properties.each_pair.map do |key, value|
                       [value['$ref'], key]
                     end]
  parameters.map do |parameter|
    definition_name = ::URI::DEFAULT_PARSER.unescape(parameter[2..-3])
    if definitions.has_key?(definition_name)
      definitions[definition_name]
    else
      definition_name = definition_name.split('/')[-1]
      resource_definitions = @schema[
        'definitions'][@resource_name]['definitions'][definition_name]
      if resource_definitions.has_key?('anyOf')
        resource_definitions['anyOf'].map do |property|
          definitions[property['$ref']]
        end.join('|')
      else
        resource_definitions['oneOf'].map do |property|
          definitions[property['$ref']]
        end.join('|')
      end
    end
  end
end
unpack_multiple_parameters(parameters) click to toggle source

Unpack an 'anyOf' or 'oneOf' multi-parameter blob.

@param parameters [Array<Hash>] An array of hashes containing '$ref'

keys and definition values.

@return [Array<Parameter>] An array of parameters extracted from the

blob.
# File lib/heroics/schema.rb, line 303
def unpack_multiple_parameters(parameters)
  parameters.map do |info|
    parameter = info['$ref']
    path = parameter.split('/')[1..-1]
    info = lookup_parameter(path, @schema)
    resource_name = path.size > 2 ? path[1].gsub('-', '_') : nil
    name = path[-1]
    Parameter.new(resource_name, name, info['description'])
  end
end