Module: Heroics

Extended by:
Heroics
Included in:
Heroics
Defined in:
lib/heroics.rb,
lib/heroics/cli.rb,
lib/heroics/link.rb,
lib/heroics/client.rb,
lib/heroics/errors.rb,
lib/heroics/naming.rb,
lib/heroics/schema.rb,
lib/heroics/command.rb,
lib/heroics/version.rb,
lib/heroics/resource.rb,
lib/heroics/configuration.rb,
lib/heroics/client_generator.rb

Overview

Heroics is an HTTP client for an API described by a JSON schema.

Defined Under Namespace

Modules: NullRateLimit Classes: BodyParameter, CLI, Client, Command, Configuration, GeneratorLink, GeneratorResource, Link, LinkSchema, Parameter, ParameterChoice, Resource, ResourceSchema, Schema, SchemaError

Constant Summary collapse

VERSION =
'0.1.4'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.build_context(module_name, schema, base_url, options) ⇒ Object

Process the schema to build up the context needed to render the source template.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/heroics/client_generator.rb', line 19

def self.build_context(module_name, schema, base_url, options)
  resources = []
  schema.resources.each do |resource_schema|
    links = []
    resource_schema.links.each do |link_schema|
      links << GeneratorLink.new(link_schema.name,
                                 link_schema.description,
                                 link_schema.parameter_details,
                                 link_schema.needs_request_body?)
    end
    resources << GeneratorResource.new(resource_schema.name,
                                       resource_schema.description,
                                       links)
  end

  {
    module_name: module_name,
    url: base_url,
    default_headers: options.fetch(:default_headers, {}),
    cache: options.fetch(:cache, {}),
    description: schema.description,
    schema: JSON.pretty_generate(schema.schema),
    resources: resources
  }
end

.camel_case(text) ⇒ Object

Convert a lower_case_name to CamelCase.



88
89
90
91
92
93
94
95
# File 'lib/heroics/client_generator.rb', line 88

def self.camel_case(text)
  return text if text !~ /_/ && text =~ /[A-Z]+.*/
  text = text.split('_').map{ |element| element.capitalize }.join
  [/^Ssl/, /^Http/, /^Xml/].each do |replace|
    text.sub!(replace) { |match| match.upcase }
  end
  text
end

.cli_from_schema(name, output, schema, url, options = {}) ⇒ CLI

Create a CLI from a JSON schema.

Parameters:

  • name (String)

    The name of the CLI.

  • output (IO)

    The stream to write to.

  • schema (Hash)

    The JSON schema to use with the CLI.

  • url (String)

    The URL used by the generated CLI when it makes requests.

  • options (Hash) (defaults to: {})

    Configuration for links. Possible keys include:

    • default_headers: Optionally, a set of headers to include in every request made by the CLI. Default is no custom headers.

    • cache: Optionally, a Moneta-compatible cache to store ETags. Default is no caching.

Returns:

  • (CLI)

    A CLI with commands generated from the JSON schema.



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/heroics/cli.rb', line 78

def self.cli_from_schema(name, output, schema, url, options={})
  client = client_from_schema(schema, url, options)
  commands = {}
  schema.resources.each do |resource_schema|
    resource_schema.links.each do |link_schema|
      command = Command.new(name, link_schema, client, output)
      commands[command.name] = command
    end
  end
  CLI.new(name, commands, output)
end

.client_from_schema(schema, url, options = {}) ⇒ Client

Create an HTTP client from a JSON schema.

Parameters:

  • schema (Schema)

    The JSON schema to build an HTTP client for.

  • url (String)

    The URL the generated client should use when making requests. Include the username and password to use with HTTP basic auth.

  • options (Hash) (defaults to: {})

    Configuration for links. Possible keys include:

    • default_headers: Optionally, a set of headers to include in every request made by the client. Default is no custom headers.

    • cache: Optionally, a Moneta-compatible cache to store ETags. Default is no caching.

Returns:

  • (Client)

    A client with resources and links from the JSON schema.



59
60
61
62
63
64
65
66
67
68
69
# File 'lib/heroics/client.rb', line 59

def self.client_from_schema(schema, url, options={})
  resources = {}
  schema.resources.each do |resource_schema|
    links = {}
    resource_schema.links.each do |link_schema|
      links[link_schema.name] = Link.new(url, link_schema, options)
    end
    resources[resource_schema.name] = Resource.new(links)
  end
  Client.new(resources, url)
end

.download_schema(url, options = {}) ⇒ Schema

Download a JSON schema from a URL.

Parameters:

  • url (String)

    The URL for the schema.

  • options (Hash) (defaults to: {})

    Configuration for links. Possible keys include:

    • default_headers: Optionally, a set of headers to include in every request made by the client. Default is no custom headers.

Returns:

  • (Schema)

    The downloaded JSON schema.



356
357
358
359
360
# File 'lib/heroics/schema.rb', line 356

def self.download_schema(url, options={})
  default_headers = options.fetch(:default_headers, {})
  response = Excon.get(url, headers: default_headers, expects: [200, 201])
  Schema.new(JSON.parse(response.body))
end

.generate_clientObject

Generate a static client that uses Heroics under the hood. This is a good option if you want to ship a gem or generate API documentation using Yard.



5
6
7
8
9
10
11
12
13
# File 'lib/heroics/client_generator.rb', line 5

def self.generate_client
  filename = File.dirname(__FILE__) + '/views/client.erb'
  eruby = ERB.new(File.read(filename))
  context = build_context(Heroics::Configuration.defaults.module_name,
    Heroics::Configuration.defaults.schema,
    Heroics::Configuration.defaults.base_url,
    Heroics::Configuration.defaults.options)
  eruby.result_with_hash(context)
end

.oauth_client_from_schema(oauth_token, schema, url, options = {}) ⇒ Client

Create an HTTP client with OAuth credentials from a JSON schema.

Parameters:

  • oauth_token (String)

    The OAuth token to pass using the ‘Bearer` authorization mechanism.

  • schema (Schema)

    The JSON schema to build an HTTP client for.

  • url (String)

    The URL the generated client should use when making requests.

  • options (Hash) (defaults to: {})

    Configuration for links. Possible keys include:

    • default_headers: Optionally, a set of headers to include in every request made by the client. Default is no custom headers.

    • cache: Optionally, a Moneta-compatible cache to store ETags. Default is no caching.

Returns:

  • (Client)

    A client with resources and links from the JSON schema.



84
85
86
87
88
89
90
91
92
93
# File 'lib/heroics/client.rb', line 84

def self.oauth_client_from_schema(oauth_token, schema, url, options={})
  authorization = "Bearer #{oauth_token}"
  # Don't mutate user-supplied data.
  options = Marshal.load(Marshal.dump(options))
  if !options.has_key?(:default_headers)
    options[:default_headers] = {}
  end
  options[:default_headers].merge!({"Authorization" => authorization})
  client_from_schema(schema, url, options)
end

.pretty_name(name) ⇒ String

Process a name to make it suitable for use as a pretty command name.

Parameters:

  • name (String)

    The name to process.

Returns:

  • (String)

    The new name with capitals converted to lowercase, and underscores and spaces converted to dashes.



26
27
28
# File 'lib/heroics/naming.rb', line 26

def self.pretty_name(name)
  name.downcase.gsub(/[_ ]/, '-')
end

.ruby_name(name) ⇒ String

Process a name to make it suitable for use as a Ruby method name.

Parameters:

  • name (String)

    The name to process.

Returns:

  • (String)

    The new name with capitals converted to lowercase, and characters replaced or removed based on the Configuration.ruby_names_replacement_patterns rules

Raises:

  • (SchemaError)

    Raised if the name contains invalid characters.



10
11
12
13
14
15
16
17
18
19
# File 'lib/heroics/naming.rb', line 10

def self.ruby_name(name)
  patterns = Heroics::Configuration.defaults.ruby_name_replacement_patterns

  ruby_name = patterns.reduce(name.downcase) do |memo, (regex, replacement)|
    memo.gsub(regex, replacement)
  end

  raise SchemaError.new("Name '#{name}' converts to invalid Ruby name '#{ruby_name}'.") if ruby_name =~ /\W/
  ruby_name
end

.token_client_from_schema(token, schema, url, options = {}) ⇒ Client

Create an HTTP client with Token credentials from a JSON schema.

Parameters:

  • oauth_token (String)

    The token to pass using the ‘Bearer` authorization mechanism.

  • schema (Schema)

    The JSON schema to build an HTTP client for.

  • url (String)

    The URL the generated client should use when making requests.

  • options (Hash) (defaults to: {})

    Configuration for links. Possible keys include:

    • default_headers: Optionally, a set of headers to include in every request made by the client. Default is no custom headers.

    • cache: Optionally, a Moneta-compatible cache to store ETags. Default is no caching.

Returns:

  • (Client)

    A client with resources and links from the JSON schema.



108
109
110
111
112
113
114
115
116
117
# File 'lib/heroics/client.rb', line 108

def self.token_client_from_schema(token, schema, url, options={})
  authorization = "Token token=#{token}"
  # Don't mutate user-supplied data.
  options = Marshal.load(Marshal.dump(options))
  if !options.has_key?(:default_headers)
    options[:default_headers] = {}
  end
  options[:default_headers].merge!({"Authorization" => authorization})
  client_from_schema(schema, url, options)
end

Instance Method Details

#default_configuration(&block) ⇒ Object



14
15
16
17
# File 'lib/heroics.rb', line 14

def default_configuration(&block)
  block ||= lambda { |c| }
  Heroics::Configuration.defaults.tap(&block)
end