heroics 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef1ff049152a681067bf9cd179da754105d8419c
4
- data.tar.gz: 1e98dc4aa35031eefc0734252bc1e650c969073b
3
+ metadata.gz: 57ff3e602b9779ad560f218f14288d8871402d33
4
+ data.tar.gz: 6763bba24c1ccb627963116ee6f43ed341113703
5
5
  SHA512:
6
- metadata.gz: 1b7486964a14891fcbede7250748ffd41e8b44c5f7446f4bac06260365d79b3b1b5801dc14d13706a2a61ed0cc42961ff181aff9063eadf449264cd465babbb6
7
- data.tar.gz: dd2217537e68ae2ab93fd1985c3812edaba6c0a666af6b8202ba3a560a4ac89fa3b9a5f59841e92ecd95c3a9110502383309139bbcc001720a46529924a20230
6
+ metadata.gz: 97435f7696ba084ec24a487ea3a652a880100124981e1ebf7f1e91bebf8baff64c6b281dca44e8480d550d3097ac368e36ddd8a466114841b9811b8dd2f4e072
7
+ data.tar.gz: 05282988882070b71e6cf9c9c6834bb65fc91c783da88c08e0163b54a21e97dedec950d9b187593cbed23b18c379404d0a6acb091800cb37adbdf586386c1fd9
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'heroics'
5
+
6
+ options = {}
7
+ option_parser = OptionParser.new do |opts|
8
+ opts.banner = 'Usage: heroics-generate module_name schema_filename url'
9
+ opts.on( '-h', '--help', 'Display this screen' ) do
10
+ puts opts
11
+ exit
12
+ end
13
+ end
14
+
15
+ option_parser.parse!
16
+ module_name, schema_filename, url = ARGV
17
+ schema = Heroics::Schema.new(MultiJson.decode(File.read(schema_filename)))
18
+ options = {
19
+ default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'},
20
+ cache: 'Moneta.new(:File, dir: "#{Dir.home}/.heroics/platform-api")'
21
+ }
22
+ puts Heroics.generate_client(module_name, schema, url, options)
@@ -25,8 +25,9 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'rake'
26
26
  spec.add_development_dependency 'turn'
27
27
 
28
+ spec.add_dependency 'erubis', '~> 2.7.0'
28
29
  spec.add_dependency 'excon'
29
- spec.add_dependency 'netrc'
30
30
  spec.add_dependency 'moneta'
31
- spec.add_dependency 'multi_json'
31
+ spec.add_dependency 'multi_json', '>= 1.9.2'
32
+ spec.add_dependency 'netrc'
32
33
  end
@@ -1,4 +1,5 @@
1
1
  require 'base64'
2
+ require 'erubis'
2
3
  require 'excon'
3
4
  require 'moneta'
4
5
  require 'multi_json'
@@ -18,3 +19,4 @@ require 'heroics/client'
18
19
  require 'heroics/schema'
19
20
  require 'heroics/command'
20
21
  require 'heroics/cli'
22
+ require 'heroics/client_generator'
@@ -0,0 +1,106 @@
1
+ module Heroics
2
+ # Generate a static client that uses Heroics under the hood. This is a good
3
+ # option if you want to ship a gem or generate API documentation using Yard.
4
+ #
5
+ # @param module_name [String] The name of the module, as rendered in a Ruby
6
+ # source file, to use for the generated client.
7
+ # @param schema [Schema] The schema instance to generate the client from.
8
+ # @param url [String] The URL for the API service.
9
+ # @param options [Hash] Configuration for links. Possible keys include:
10
+ # - default_headers: Optionally, a set of headers to include in every
11
+ # request made by the client. Default is no custom headers.
12
+ # - cache: Optionally, a Moneta-compatible cache to store ETags. Default
13
+ # is no caching.
14
+ def self.generate_client(module_name, schema, url, options)
15
+ filename = File.dirname(__FILE__) + '/views/client.erb'
16
+ eruby = Erubis::Eruby.new(File.read(filename))
17
+ context = build_context(module_name, schema, url, options)
18
+ eruby.evaluate(context)
19
+ end
20
+
21
+ private
22
+
23
+ # Process the schema to build up the context needed to render the source
24
+ # template.
25
+ def self.build_context(module_name, schema, url, options)
26
+ resources = []
27
+ schema.resources.each do |resource_schema|
28
+ links = []
29
+ resource_schema.links.each do |link_schema|
30
+ links << GeneratorLink.new(link_schema.name.gsub('-', '_'),
31
+ link_schema.description,
32
+ link_schema.parameter_details,
33
+ link_schema.needs_request_body?)
34
+ end
35
+ resources << GeneratorResource.new(resource_schema.name.gsub('-', '_'),
36
+ resource_schema.description,
37
+ links)
38
+ end
39
+
40
+ context = {module_name: module_name,
41
+ url: url,
42
+ default_headers: options.fetch(:default_headers, {}),
43
+ cache: options.fetch(:cache, {}),
44
+ description: schema.description,
45
+ schema: MultiJson.dump(schema.schema),
46
+ resources: resources}
47
+ end
48
+
49
+ # A representation of a resource for use when generating source code in the
50
+ # template.
51
+ class GeneratorResource
52
+ attr_reader :name, :description, :links
53
+
54
+ def initialize(name, description, links)
55
+ @name = name
56
+ @description = description
57
+ @links = links
58
+ end
59
+
60
+ # The name of the resource class in generated code.
61
+ def class_name
62
+ Heroics.camel_case(name)
63
+ end
64
+ end
65
+
66
+ # A representation of a link for use when generating source code in the
67
+ # template.
68
+ class GeneratorLink
69
+ attr_reader :name, :description, :parameters, :takes_body
70
+
71
+ def initialize(name, description, parameters, takes_body)
72
+ @name = name
73
+ @description = description
74
+ @parameters = parameters
75
+ if takes_body
76
+ parameters << BodyParameter.new
77
+ end
78
+ end
79
+
80
+ # The list of parameters to render in generated source code for the method
81
+ # signature for the link.
82
+ def parameter_names
83
+ @parameters.map { |info| info.name }.join(', ')
84
+ end
85
+ end
86
+
87
+ # Convert a lower_case_name to CamelCase.
88
+ def self.camel_case(text)
89
+ return text if text !~ /_/ && text =~ /[A-Z]+.*/
90
+ text = text.split('_').map{ |element| element.capitalize }.join
91
+ [/^Ssl/, /^Http/, /^Xml/].each do |replace|
92
+ text.sub!(replace) { |match| match.upcase }
93
+ end
94
+ text
95
+ end
96
+
97
+ # A representation of a body parameter.
98
+ class BodyParameter
99
+ attr_reader :name, :description
100
+
101
+ def initialize
102
+ @name = 'body'
103
+ @description = 'the object to pass as the request payload'
104
+ end
105
+ end
106
+ end
@@ -14,6 +14,11 @@ module Heroics
14
14
  end
15
15
  end
16
16
 
17
+ # A description of the API.
18
+ def description
19
+ @schema['description']
20
+ end
21
+
17
22
  # Get a schema for a named resource.
18
23
  #
19
24
  # @param name [String] The name of the resource.
@@ -60,6 +65,11 @@ module Heroics
60
65
  end]
61
66
  end
62
67
 
68
+ # A description of the resource.
69
+ def description
70
+ @schema['definitions'][name]['description']
71
+ end
72
+
63
73
  # Get a schema for a named link.
64
74
  #
65
75
  # @param name [String] The name of the link.
@@ -122,7 +132,21 @@ module Heroics
122
132
  #
123
133
  # @return [Array<String>] The parameters.
124
134
  def parameters
125
- resolve_parameters(link_schema['href'].scan(PARAMETER_REGEX))
135
+ parameter_names = link_schema['href'].scan(PARAMETER_REGEX)
136
+ resolve_parameters(parameter_names)
137
+ end
138
+
139
+ # Get the names and descriptions of the parameters this link expects.
140
+ #
141
+ # @return [Hash<String, String>] A list of hashes with `name` and
142
+ # `description` key/value pairs describing parameters.
143
+ def parameter_details
144
+ parameter_names = link_schema['href'].scan(PARAMETER_REGEX)
145
+ resolve_parameter_details(parameter_names)
146
+ end
147
+
148
+ def needs_request_body?
149
+ return link_schema.has_key?('schema')
126
150
  end
127
151
 
128
152
  # Get an example request body.
@@ -132,14 +156,14 @@ module Heroics
132
156
  if body_schema = link_schema['schema']
133
157
  definitions = @schema['definitions'][@resource_name]['definitions']
134
158
  Hash[body_schema['properties'].keys.map do |property|
135
- # FIXME This is wrong! -jkakar
136
- if definitions.has_key?(property)
137
- example = definitions[property]['example']
138
- else
139
- example = ''
140
- end
141
- [property, example]
142
- end]
159
+ # FIXME This is wrong! -jkakar
160
+ if definitions.has_key?(property)
161
+ example = definitions[property]['example']
162
+ else
163
+ example = ''
164
+ end
165
+ [property, example]
166
+ end]
143
167
  end
144
168
  end
145
169
 
@@ -173,7 +197,7 @@ module Heroics
173
197
  private
174
198
 
175
199
  # Match parameters in definition strings.
176
- PARAMETER_REGEX = /\{\([%\/a-zA-Z0-9_]*\)\}/
200
+ PARAMETER_REGEX = /\{\([%\/a-zA-Z0-9_-]*\)\}/
177
201
 
178
202
  # Get the raw link schema.
179
203
  #
@@ -188,10 +212,8 @@ module Heroics
188
212
  # convert to parameter names.
189
213
  # @return [Array<String>] The parameters.
190
214
  def resolve_parameters(parameters)
191
- # FIXME This is all pretty terrible. It'd be much better to
192
- # automatically resolve $ref's based on the path instead of special
193
- # casing everything. -jkakar
194
215
  properties = @schema['definitions'][@resource_name]['properties']
216
+ return [''] if properties.nil?
195
217
  definitions = Hash[properties.each_pair.map do |key, value|
196
218
  [value['$ref'], key]
197
219
  end]
@@ -216,6 +238,72 @@ module Heroics
216
238
  end
217
239
  end
218
240
 
241
+ # Get the parameters this link expects.
242
+ #
243
+ # @param parameters [Array] The names of the parameter definitions to
244
+ # convert to parameter names.
245
+ # @return [Array<Parameter|ParameterChoice>] A list of parameter instances
246
+ # that represent parameters to be injected into the link URL.
247
+ def resolve_parameter_details(parameters)
248
+ properties = @schema['definitions'][@resource_name]['properties']
249
+ return [] if properties.nil?
250
+
251
+ # URI decode parameters and strip the leading '{(' and trailing ')}'.
252
+ parameters = parameters.map { |parameter| URI.unescape(parameter[2..-3]) }
253
+ parameters.map do |parameter|
254
+ # Split the path into components and discard the leading '#' that
255
+ # represents the root of the schema.
256
+ path = parameter.split('/')[1..-1]
257
+ info = lookup_parameter(path, @schema)
258
+ # The reference can be one of several values.
259
+ resource_name = path[1].gsub('-', '_')
260
+ if info.has_key?('anyOf')
261
+ ParameterChoice.new(resource_name,
262
+ unpack_multiple_parameters(info['anyOf']))
263
+ elsif info.has_key?('oneOf')
264
+ ParameterChoice.new(resource_name,
265
+ unpack_multiple_parameters(info['oneOf']))
266
+ else
267
+ name = path[-1]
268
+ Parameter.new(resource_name, name, info['description'])
269
+ end
270
+ end
271
+ end
272
+
273
+ # Unpack an 'anyOf' or 'oneOf' multi-parameter blob.
274
+ #
275
+ # @param parameters [Array<Hash>] An array of hashes containing '$ref'
276
+ # keys and definition values.
277
+ # @return [Array<Parameter>] An array of parameters extracted from the
278
+ # blob.
279
+ def unpack_multiple_parameters(parameters)
280
+ parameters.map do |info|
281
+ parameter = info['$ref']
282
+ path = parameter.split('/')[1..-1]
283
+ info = lookup_parameter(path, @schema)
284
+ resource_name = path[1].gsub('-', '_')
285
+ name = path[-1]
286
+ Parameter.new(resource_name, name, info['description'])
287
+ end
288
+ end
289
+
290
+ # Recursively walk the object hierarchy in the schema to resolve a given
291
+ # path. This is used to find property information related to definitions
292
+ # in link hrefs.
293
+ #
294
+ # @param path [Array<String>] An array of paths to walk, such as
295
+ # ['definitions', 'resource', 'definitions', 'property'].
296
+ # @param schema [Hash] The schema to walk.
297
+ def lookup_parameter(path, schema)
298
+ key = path[0]
299
+ remaining = path[1..-1]
300
+ if remaining.empty?
301
+ return schema[key]
302
+ else
303
+ lookup_parameter(remaining, schema[key])
304
+ end
305
+ end
306
+
219
307
  # Convert a path parameter to a format suitable for use in a path.
220
308
  #
221
309
  # @param [Fixnum,String,TrueClass,FalseClass,Time] The parameter to format.
@@ -243,6 +331,54 @@ module Heroics
243
331
  def self.download_schema(url, options={})
244
332
  default_headers = options.fetch(:default_headers, {})
245
333
  response = Excon.get(url, headers: default_headers, expects: [200, 201])
246
- Schema.new(MultiJson.decode(response.body))
334
+ Schema.new(MultiJson.load(response.body))
335
+ end
336
+
337
+ # A representation of a parameter.
338
+ class Parameter
339
+ attr_reader :resource_name, :description
340
+
341
+ def initialize(resource_name, name, description)
342
+ @resource_name = resource_name
343
+ @name = name
344
+ @description = description
345
+ end
346
+
347
+ # The name of the parameter, with the resource included, suitable for use
348
+ # in a function signature.
349
+ def name
350
+ "#{@resource_name}_#{@name}"
351
+ end
352
+
353
+ # A pretty representation of this instance.
354
+ def inspect
355
+ "Parameter(name=#{@name}, description=#{@description})"
356
+ end
357
+ end
358
+
359
+ # A representation of a set of parameters.
360
+ class ParameterChoice
361
+ attr_reader :resource_name, :parameters
362
+
363
+ def initialize(resource_name, parameters)
364
+ @resource_name = resource_name
365
+ @parameters = parameters
366
+ end
367
+
368
+ # A name created by merging individual parameter descriptions, suitable
369
+ # for use in a function signature.
370
+ def name
371
+ @parameters.map { |parameter| parameter.name }.join('_or_')
372
+ end
373
+
374
+ # A description created by merging individual parameter descriptions.
375
+ def description
376
+ @parameters.map { |parameter| parameter.description }.join(' or ')
377
+ end
378
+
379
+ # A pretty representation of this instance.
380
+ def inspect
381
+ "ParameterChoice(parameters=#{@parameters})"
382
+ end
247
383
  end
248
384
  end
@@ -1,3 +1,3 @@
1
1
  module Heroics
2
- VERSION = '0.0.6'
2
+ VERSION = '0.0.7'
3
3
  end
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # WARNING: Do not edit by hand, this file was generated by Heroics:
5
+ #
6
+ # https://github.com/heroku/heroics
7
+ #
8
+
9
+ require 'uri'
10
+
11
+ module <%= @module_name %>
12
+ # Get a Client configured to use HTTP Basic authentication.
13
+ #
14
+ # @param username [String] The username to use with the API.
15
+ # @param password [String] The password to use with the API.
16
+ # @param headers [Hash<String,String>] Optionally, custom to headers to
17
+ # include with every response.
18
+ # @return [Client] A client configured to use the API with HTTP Basic
19
+ # authentication.
20
+ def self.connect(username, password, headers=nil)
21
+ url = URI.parse("<%= @url %>")
22
+ url.user = username
23
+ url.password = password
24
+ default_headers = <%= @default_headers %>
25
+ unless headers.nil?
26
+ default_headers.merge!(headers)
27
+ end
28
+ cache = <%= @cache %>
29
+ options = {
30
+ options: {default_headers: default_headers,
31
+ cache: cache}
32
+ }
33
+ client = Heroics.client_from_schema(SCHEMA, url.to_s, options)
34
+ Client.new(client)
35
+ end
36
+
37
+ # Get a Client configured to use OAuth authentication.
38
+ #
39
+ # @param oauth_token [String] The OAuth token to use with the API.
40
+ # @param headers [Hash<String,String>] Optionally, custom to headers to
41
+ # include with every response.
42
+ # @return [Client] A client configured to use the API with OAuth
43
+ # authentication.
44
+ def self.connect_oauth(oauth_token, headers=nil)
45
+ url = "<%= @url %>"
46
+ default_headers = <%= @default_headers %>
47
+ unless headers.nil?
48
+ default_headers.merge!(headers)
49
+ end
50
+ cache = <%= @cache %>
51
+ options = {
52
+ options: {default_headers: default_headers,
53
+ cache: cache}
54
+ }
55
+ client = Heroics.client_from_schema(oauth_token, SCHEMA, url, options)
56
+ Client.new(client)
57
+ end
58
+
59
+ # <%= @description %>
60
+ class Client
61
+ def initialize(client)
62
+ @client = client
63
+ end
64
+ <% for resource in @resources %>
65
+
66
+ # <%= resource.description %>
67
+ #
68
+ # @return [<%= resource.class_name %>]
69
+ def <%= resource.name %>
70
+ @<%= resource.name %>_resource ||= <%= resource.class_name %>.new(@client)
71
+ end
72
+ <% end %>
73
+ end
74
+
75
+ private
76
+ <% for resource in @resources %>
77
+
78
+ # <%= resource.description %>
79
+ class <%= resource.class_name %>
80
+ def initialize(client)
81
+ @client = client
82
+ end
83
+ <% for link in resource.links %>
84
+
85
+ # <%= link.description %>
86
+ <% unless link.parameters.empty? %>
87
+ #
88
+ <% for parameter in link.parameters %>
89
+ # @param <%= parameter.name %>: <%= parameter.description %>
90
+ <% end %>
91
+ <% end %>
92
+ def <%= link.name %>(<%= link.parameter_names %>)
93
+ @client.<%= resource.name %>.<%= link.name %>(<%= link.parameter_names %>)
94
+ end
95
+ <% end %>
96
+ end
97
+ <% end %>
98
+
99
+ SCHEMA = Heroics::Schema.new(MultiJson.load(<<-'HEROICS_SCHEMA'))
100
+ <%= @schema %>
101
+ HEROICS_SCHEMA
102
+ end
@@ -0,0 +1,34 @@
1
+ require 'helper'
2
+ require 'netrc'
3
+ require 'stringio'
4
+
5
+ class GenerateClientTest < MiniTest::Unit::TestCase
6
+ include ExconHelper
7
+
8
+ # generate_client takes a module, schema, API URL and options and returns a
9
+ # string containing generated Ruby client code.
10
+ def test_generate_client
11
+ Excon.stub(method: :get) do |request|
12
+ assert_equal('example.com', request[:host])
13
+ assert_equal('/schema', request[:path])
14
+ assert_equal('application/vnd.example+json; version=3',
15
+ request[:headers]['Accept'])
16
+ Excon.stubs.pop
17
+ {status: 200, headers: {'Content-Type' => 'application/json'},
18
+ body: MultiJson.dump(SAMPLE_SCHEMA)}
19
+ end
20
+
21
+ netrc = Netrc.read
22
+ username, token = netrc['example.com']
23
+ schema_url = "https://example.com/schema"
24
+ options = {
25
+ default_headers: {'Accept' => 'application/vnd.example+json; version=3'},
26
+ cache: 'Moneta.new(:File, dir: "#{Dir.home}/.heroics/example")'
27
+ }
28
+ schema = Heroics.download_schema(schema_url, options)
29
+ client_source = Heroics.generate_client("ExampleAPI", schema,
30
+ "api.example.com", options)
31
+ # Ensure the generated code is syntactically valid.
32
+ eval(client_source)
33
+ end
34
+ end
@@ -50,7 +50,7 @@ class ResourceSchemaTest < MiniTest::Unit::TestCase
50
50
  assert_equal("Unknown link 'unknown-link'.", error.message)
51
51
  end
52
52
 
53
- # ResourceSchema.links returns a list of LinkSchema children.
53
+ # ResourceSchema.links returns an array of LinkSchema children.
54
54
  def test_links
55
55
  schema = Heroics::Schema.new(SAMPLE_SCHEMA)
56
56
  assert_equal(
@@ -80,7 +80,7 @@ class LinkSchemaTest < MiniTest::Unit::TestCase
80
80
  schema.resource('resource').link('list').description)
81
81
  end
82
82
 
83
- # LinkSchema.parameters returns an empty list if the link doesn't require
83
+ # LinkSchema.parameters returns an empty array if the link doesn't require
84
84
  # parameters.
85
85
  def test_parameters_without_parameters
86
86
  schema = Heroics::Schema.new(SAMPLE_SCHEMA)
@@ -88,8 +88,8 @@ class LinkSchemaTest < MiniTest::Unit::TestCase
88
88
  assert_equal([], link.parameters)
89
89
  end
90
90
 
91
- # LinkSchema.parameters returns a list of named parameter required to invoke
92
- # the link correctly.
91
+ # LinkSchema.parameters returns an array of named parameter required to
92
+ # invoke the link correctly.
93
93
  def test_parameters
94
94
  schema = Heroics::Schema.new(SAMPLE_SCHEMA)
95
95
  link = schema.resource('resource').link('info')
@@ -105,6 +105,40 @@ class LinkSchemaTest < MiniTest::Unit::TestCase
105
105
  assert_equal(['uuid_field|email_field'], link.parameters)
106
106
  end
107
107
 
108
+ # LinkSchema.parameter_details returns an empty array if the link doesn't
109
+ # require parameters.
110
+ def test_parameter_details_without_parameters
111
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
112
+ link = schema.resource('resource').link('list')
113
+ assert_equal([], link.parameter_details)
114
+ end
115
+
116
+ # LinkSchema.parameter_details returns an array of Parameter with information
117
+ # about the parameters accepted by the link.
118
+ def test_parameter_details
119
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
120
+ link = schema.resource('resource').link('info')
121
+ parameters = link.parameter_details
122
+ assert_equal(1, parameters.length)
123
+ parameter = parameters[0]
124
+ assert_equal('resource_uuid_field', parameter.name)
125
+ assert_equal('A sample UUID field', parameter.description)
126
+ end
127
+
128
+ # LinkSchema.parameter_details returns an array of ParameterChoices, when
129
+ # more than one value may be used with a property, with information about
130
+ # the parameters accepted by the link.
131
+ def test_parameter_details_with_one_of_field
132
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
133
+ link = schema.resource('resource').link('identify_resource')
134
+ parameters = link.parameter_details
135
+ assert_equal(1, parameters.length)
136
+ parameter = parameters[0]
137
+ assert_equal('resource_uuid_field_or_resource_email_field', parameter.name)
138
+ assert_equal('A sample UUID field or A sample email address field',
139
+ parameter.description)
140
+ end
141
+
108
142
  # LinkSchema.body returns nil if the link doesn't accept a request body.
109
143
  def test_example_body_without_body
110
144
  schema = Heroics::Schema.new(SAMPLE_SCHEMA)
@@ -125,7 +159,7 @@ class LinkSchemaTest < MiniTest::Unit::TestCase
125
159
  link.example_body)
126
160
  end
127
161
 
128
- # LinkSchema.format_path converts a list of parameters into a path.
162
+ # LinkSchema.format_path converts an array of parameters into a path.
129
163
  def test_format_path
130
164
  schema = Heroics::Schema.new(SAMPLE_SCHEMA)
131
165
  link = schema.resource('resource').link('info')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heroics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - geemus
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-09 00:00:00.000000000 Z
12
+ date: 2014-04-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -67,6 +67,20 @@ dependencies:
67
67
  - - '>='
68
68
  - !ruby/object:Gem::Version
69
69
  version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: erubis
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 2.7.0
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ version: 2.7.0
70
84
  - !ruby/object:Gem::Dependency
71
85
  name: excon
72
86
  requirement: !ruby/object:Gem::Requirement
@@ -82,7 +96,7 @@ dependencies:
82
96
  - !ruby/object:Gem::Version
83
97
  version: '0'
84
98
  - !ruby/object:Gem::Dependency
85
- name: netrc
99
+ name: moneta
86
100
  requirement: !ruby/object:Gem::Requirement
87
101
  requirements:
88
102
  - - '>='
@@ -96,21 +110,21 @@ dependencies:
96
110
  - !ruby/object:Gem::Version
97
111
  version: '0'
98
112
  - !ruby/object:Gem::Dependency
99
- name: moneta
113
+ name: multi_json
100
114
  requirement: !ruby/object:Gem::Requirement
101
115
  requirements:
102
116
  - - '>='
103
117
  - !ruby/object:Gem::Version
104
- version: '0'
118
+ version: 1.9.2
105
119
  type: :runtime
106
120
  prerelease: false
107
121
  version_requirements: !ruby/object:Gem::Requirement
108
122
  requirements:
109
123
  - - '>='
110
124
  - !ruby/object:Gem::Version
111
- version: '0'
125
+ version: 1.9.2
112
126
  - !ruby/object:Gem::Dependency
113
- name: multi_json
127
+ name: netrc
114
128
  requirement: !ruby/object:Gem::Requirement
115
129
  requirements:
116
130
  - - '>='
@@ -128,6 +142,7 @@ email:
128
142
  - geemus@gmail.com
129
143
  - jkakar@kakar.ca
130
144
  executables:
145
+ - heroics-generate
131
146
  - heroku-api
132
147
  extensions: []
133
148
  extra_rdoc_files: []
@@ -139,11 +154,13 @@ files:
139
154
  - README.md
140
155
  - Rakefile
141
156
  - TODO
157
+ - bin/heroics-generate
142
158
  - bin/heroku-api
143
159
  - heroics.gemspec
144
160
  - lib/heroics.rb
145
161
  - lib/heroics/cli.rb
146
162
  - lib/heroics/client.rb
163
+ - lib/heroics/client_generator.rb
147
164
  - lib/heroics/command.rb
148
165
  - lib/heroics/errors.rb
149
166
  - lib/heroics/link.rb
@@ -151,8 +168,10 @@ files:
151
168
  - lib/heroics/resource.rb
152
169
  - lib/heroics/schema.rb
153
170
  - lib/heroics/version.rb
171
+ - lib/heroics/views/client.erb
154
172
  - test.rb
155
173
  - test/cli_test.rb
174
+ - test/client_generator_test.rb
156
175
  - test/client_test.rb
157
176
  - test/command_test.rb
158
177
  - test/helper.rb