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
Public Class Methods
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
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
# 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
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
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
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
# File lib/heroics/schema.rb, line 174 def needs_request_body? return link_schema.has_key?('schema') end
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
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
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
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
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
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
Get the raw link schema.
@param [Hash] The raw link schema.
# File lib/heroics/schema.rb, line 231 def link_schema @schema['definitions'][@resource_name]['links'][@link_index] end
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
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
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 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