heroics 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/heroics-generate +22 -0
- data/heroics.gemspec +3 -2
- data/lib/heroics.rb +2 -0
- data/lib/heroics/client_generator.rb +106 -0
- data/lib/heroics/schema.rb +150 -14
- data/lib/heroics/version.rb +1 -1
- data/lib/heroics/views/client.erb +102 -0
- data/test/client_generator_test.rb +34 -0
- data/test/schema_test.rb +39 -5
- metadata +26 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57ff3e602b9779ad560f218f14288d8871402d33
|
4
|
+
data.tar.gz: 6763bba24c1ccb627963116ee6f43ed341113703
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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)
|
data/heroics.gemspec
CHANGED
@@ -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
|
data/lib/heroics.rb
CHANGED
@@ -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
|
data/lib/heroics/schema.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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.
|
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
|
data/lib/heroics/version.rb
CHANGED
@@ -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
|
data/test/schema_test.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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.
|
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-
|
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:
|
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:
|
113
|
+
name: multi_json
|
100
114
|
requirement: !ruby/object:Gem::Requirement
|
101
115
|
requirements:
|
102
116
|
- - '>='
|
103
117
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
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:
|
125
|
+
version: 1.9.2
|
112
126
|
- !ruby/object:Gem::Dependency
|
113
|
-
name:
|
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
|