aws-sdk-code-generator 0.1.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/aws-sdk-code-generator.rb +91 -0
- data/lib/aws-sdk-code-generator/apply_docs.rb +37 -0
- data/lib/aws-sdk-code-generator/code_builder.rb +201 -0
- data/lib/aws-sdk-code-generator/dsl/access_control_statement.rb +23 -0
- data/lib/aws-sdk-code-generator/dsl/attribute_accessor.rb +43 -0
- data/lib/aws-sdk-code-generator/dsl/attribute_reader.rb +11 -0
- data/lib/aws-sdk-code-generator/dsl/attribute_writer.rb +11 -0
- data/lib/aws-sdk-code-generator/dsl/autoload_statement.rb +15 -0
- data/lib/aws-sdk-code-generator/dsl/block_param.rb +11 -0
- data/lib/aws-sdk-code-generator/dsl/class.rb +27 -0
- data/lib/aws-sdk-code-generator/dsl/code_literal.rb +66 -0
- data/lib/aws-sdk-code-generator/dsl/code_object.rb +33 -0
- data/lib/aws-sdk-code-generator/dsl/docstring.rb +36 -0
- data/lib/aws-sdk-code-generator/dsl/eigenclass.rb +15 -0
- data/lib/aws-sdk-code-generator/dsl/extend_statement.rb +12 -0
- data/lib/aws-sdk-code-generator/dsl/formatter.rb +25 -0
- data/lib/aws-sdk-code-generator/dsl/include_statement.rb +17 -0
- data/lib/aws-sdk-code-generator/dsl/main.rb +105 -0
- data/lib/aws-sdk-code-generator/dsl/method.rb +108 -0
- data/lib/aws-sdk-code-generator/dsl/module.rb +167 -0
- data/lib/aws-sdk-code-generator/dsl/option_tag.rb +36 -0
- data/lib/aws-sdk-code-generator/dsl/param.rb +43 -0
- data/lib/aws-sdk-code-generator/dsl/param_list.rb +38 -0
- data/lib/aws-sdk-code-generator/dsl/return_tag.rb +19 -0
- data/lib/aws-sdk-code-generator/dsl/tag_default.rb +20 -0
- data/lib/aws-sdk-code-generator/dsl/tag_docstring.rb +27 -0
- data/lib/aws-sdk-code-generator/dsl/tag_type.rb +18 -0
- data/lib/aws-sdk-code-generator/errors.rb +30 -0
- data/lib/aws-sdk-code-generator/gem_builder.rb +71 -0
- data/lib/aws-sdk-code-generator/generators/client_api_module.rb +334 -0
- data/lib/aws-sdk-code-generator/generators/client_class.rb +389 -0
- data/lib/aws-sdk-code-generator/generators/client_operation_documentation.rb +166 -0
- data/lib/aws-sdk-code-generator/generators/errors_module.rb +25 -0
- data/lib/aws-sdk-code-generator/generators/resource/action.rb +88 -0
- data/lib/aws-sdk-code-generator/generators/resource/batch_builder.rb +211 -0
- data/lib/aws-sdk-code-generator/generators/resource/builder.rb +50 -0
- data/lib/aws-sdk-code-generator/generators/resource/client_getter.rb +15 -0
- data/lib/aws-sdk-code-generator/generators/resource/client_request.rb +49 -0
- data/lib/aws-sdk-code-generator/generators/resource/client_request_docs.rb +97 -0
- data/lib/aws-sdk-code-generator/generators/resource/client_request_params.rb +88 -0
- data/lib/aws-sdk-code-generator/generators/resource/collection_class.rb +180 -0
- data/lib/aws-sdk-code-generator/generators/resource/data_attribute_getter.rb +24 -0
- data/lib/aws-sdk-code-generator/generators/resource/data_loaded_method.rb +18 -0
- data/lib/aws-sdk-code-generator/generators/resource/data_method.rb +49 -0
- data/lib/aws-sdk-code-generator/generators/resource/exists_method.rb +29 -0
- data/lib/aws-sdk-code-generator/generators/resource/extract_identifier_method.rb +32 -0
- data/lib/aws-sdk-code-generator/generators/resource/has_association.rb +101 -0
- data/lib/aws-sdk-code-generator/generators/resource/has_many_association.rb +108 -0
- data/lib/aws-sdk-code-generator/generators/resource/identifier_getter.rb +26 -0
- data/lib/aws-sdk-code-generator/generators/resource/identifiers_method.rb +28 -0
- data/lib/aws-sdk-code-generator/generators/resource/initialize_method.rb +67 -0
- data/lib/aws-sdk-code-generator/generators/resource/load_method.rb +65 -0
- data/lib/aws-sdk-code-generator/generators/resource/value_source.rb +68 -0
- data/lib/aws-sdk-code-generator/generators/resource/waiter_method.rb +61 -0
- data/lib/aws-sdk-code-generator/generators/resource_class.rb +325 -0
- data/lib/aws-sdk-code-generator/generators/response_structure_example.rb +83 -0
- data/lib/aws-sdk-code-generator/generators/root_resource_class.rb +42 -0
- data/lib/aws-sdk-code-generator/generators/service_documentation.rb +64 -0
- data/lib/aws-sdk-code-generator/generators/shared_example.rb +132 -0
- data/lib/aws-sdk-code-generator/generators/structure_type_class.rb +95 -0
- data/lib/aws-sdk-code-generator/generators/syntax_example.rb +169 -0
- data/lib/aws-sdk-code-generator/generators/types_module.rb +52 -0
- data/lib/aws-sdk-code-generator/generators/waiter_class.rb +62 -0
- data/lib/aws-sdk-code-generator/generators/waiters_module.rb +20 -0
- data/lib/aws-sdk-code-generator/hash_formatter.rb +122 -0
- data/lib/aws-sdk-code-generator/helper.rb +215 -0
- data/lib/aws-sdk-code-generator/service.rb +126 -0
- data/lib/aws-sdk-code-generator/underscore.rb +45 -0
- data/lib/aws-sdk-code-generator/view.rb +23 -0
- data/lib/aws-sdk-code-generator/views.rb +3 -0
- data/lib/aws-sdk-code-generator/views/features/env.rb +24 -0
- data/lib/aws-sdk-code-generator/views/features/step_definitions.rb +20 -0
- data/lib/aws-sdk-code-generator/views/gemspec.rb +41 -0
- data/lib/aws-sdk-code-generator/views/service_module.rb +85 -0
- data/lib/aws-sdk-code-generator/views/spec/spec_helper.rb +24 -0
- data/lib/aws-sdk-code-generator/views/version.rb +16 -0
- metadata +120 -0
@@ -0,0 +1,166 @@
|
|
1
|
+
module AwsSdkCodeGenerator
|
2
|
+
module Generators
|
3
|
+
class ClientOperationDocumentation
|
4
|
+
|
5
|
+
include Helper
|
6
|
+
|
7
|
+
def self.apply(options)
|
8
|
+
new(options).apply(options)
|
9
|
+
end
|
10
|
+
|
11
|
+
# @option options [required, Hash] :api
|
12
|
+
# @option options [required, String] :service_identifier
|
13
|
+
# @option options [required, String] :operation_name
|
14
|
+
# @option options [required, Hash] :operation
|
15
|
+
# @option options [Hash] :examples
|
16
|
+
def initialize(options)
|
17
|
+
@api = options.fetch(:api)
|
18
|
+
@service_id = options.fetch(:service_identifier)
|
19
|
+
@operation_name = options.fetch(:operation_name)
|
20
|
+
@method_name = underscore(@operation_name)
|
21
|
+
@operation = options.fetch(:operation)
|
22
|
+
@examples = options.fetch(:examples, nil) || { 'examples' => {} }
|
23
|
+
end
|
24
|
+
|
25
|
+
def apply(options)
|
26
|
+
method = options.fetch(:method)
|
27
|
+
method.docstring do |docstring|
|
28
|
+
apply_operation_docs(docstring)
|
29
|
+
apply_option_tags(docstring)
|
30
|
+
apply_return_tags(docstring)
|
31
|
+
apply_shared_examples(docstring)
|
32
|
+
apply_examples_from_disk(docstring)
|
33
|
+
apply_request_syntax_example(docstring)
|
34
|
+
apply_response_struture_example(docstring)
|
35
|
+
apply_overload_tag(docstring)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def apply_operation_docs(docstring)
|
42
|
+
docstring.append(markdown(@operation['documentation']))
|
43
|
+
end
|
44
|
+
|
45
|
+
def apply_option_tags(docstring)
|
46
|
+
# document the `:response_target` option if the response is streaming
|
47
|
+
if output = shape(@operation['output'])
|
48
|
+
if output['payload'] && output['members'][output['payload']]['streaming']
|
49
|
+
docstring.lines.concat(Dsl::OptionTag.new(
|
50
|
+
name: 'response_target',
|
51
|
+
type: 'String, IO',
|
52
|
+
param: 'params',
|
53
|
+
required: false,
|
54
|
+
docstring: 'Where to write response data, file path, or IO object.'
|
55
|
+
).lines)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if input_shape = shape(@operation['input'])
|
60
|
+
required = input_shape['required'] || []
|
61
|
+
input_shape['members'].each_pair do |member_name, member_ref|
|
62
|
+
docstring.lines.concat(Dsl::OptionTag.new(
|
63
|
+
name: underscore(member_name),
|
64
|
+
type: ruby_input_type(member_ref),
|
65
|
+
param: 'params',
|
66
|
+
required: required.include?(member_name),
|
67
|
+
docstring: documentation(member_ref),
|
68
|
+
).lines)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def apply_return_tags(docstring)
|
74
|
+
output_shape = shape(@operation['output'])
|
75
|
+
resp = '{Seahorse::Client::Response response}'
|
76
|
+
if output_shape && output_shape['members'].size > 0
|
77
|
+
type = ruby_type(@operation['output'])
|
78
|
+
returns = "@return [#{type}] Returns a #{resp} object which responds to "
|
79
|
+
returns << "the following methods:\n\n"
|
80
|
+
output_shape['members'].each_pair do |mname, mref|
|
81
|
+
mtype = ruby_type(mref).gsub(/</, '<').gsub(/>/, '>')
|
82
|
+
returns << " * {#{type}##{underscore(mname)} ##{mname}} => #{mtype}\n"
|
83
|
+
end
|
84
|
+
docstring.append(returns)
|
85
|
+
else
|
86
|
+
docstring.append("@return [Struct] Returns an empty #{resp}.")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def apply_shared_examples(docstring)
|
91
|
+
(@examples[@operation_name] || []).size.times do |n|
|
92
|
+
begin
|
93
|
+
# TODO : known issue with an ec2 shared example that
|
94
|
+
# attempts to document a member that is not
|
95
|
+
# present in the model any longer (intentionally
|
96
|
+
# removed in customizations) - raises runtime
|
97
|
+
# error. This should be cleaned up.
|
98
|
+
docstring.append(
|
99
|
+
SharedExample.new(
|
100
|
+
operation_name: @operation_name,
|
101
|
+
api: @api,
|
102
|
+
examples: @examples,
|
103
|
+
example: n
|
104
|
+
).to_s
|
105
|
+
)
|
106
|
+
rescue
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def apply_shared_example(docstring, example)
|
112
|
+
return
|
113
|
+
|
114
|
+
input_comments = json_ex['comments']['input']
|
115
|
+
input = SharedExample.new(json_ex['input'], method_name, operation, input_comments).to_str_input
|
116
|
+
parts = []
|
117
|
+
parts << "@example Example: #{json_ex['title']}\n\n"
|
118
|
+
parts << " # #{json_ex['description']}\n\n"
|
119
|
+
parts += input.lines.map { |line| " " + line }
|
120
|
+
if json_ex['output']
|
121
|
+
output_comments = json_ex['comments']['output']
|
122
|
+
output = SharedExample.new(json_ex['output'], method_name, operation, output_comments).to_str_output
|
123
|
+
parts << "\n\n # resp.to_h outputs the following:\n"
|
124
|
+
parts += output.lines.map { |line| " " + line }
|
125
|
+
end
|
126
|
+
tag(parts.join)
|
127
|
+
end
|
128
|
+
|
129
|
+
def apply_examples_from_disk(docstring)
|
130
|
+
examples = File.expand_path('../../../../../../doc-src/examples', __FILE__)
|
131
|
+
glob = "#{examples}/#{@service_id}/client/#{@method_name}/*.rb"
|
132
|
+
Dir.glob(glob).map do |path|
|
133
|
+
title = File.basename(path).split(/\./).first
|
134
|
+
title = title.sub(/^\d+_/, '').gsub(/_/, ' ')
|
135
|
+
title = title[0].upcase + title[1..-1]
|
136
|
+
docstring.append("\n@example #{title}")
|
137
|
+
docstring.append(" " + File.read(path).lines.join(' '))
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def apply_request_syntax_example(docstring)
|
142
|
+
if @operation['input']
|
143
|
+
syntax = SyntaxExample.new(
|
144
|
+
struct_shape: shape(@operation['input']),
|
145
|
+
api: @api,
|
146
|
+
indent: ' '
|
147
|
+
).format.strip
|
148
|
+
docstring.append("\n@example Request syntax with placeholder values")
|
149
|
+
docstring.append(" resp = client.#{@method_name}(#{syntax})")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def apply_response_struture_example(docstring)
|
154
|
+
output = @operation['output']
|
155
|
+
if output && shape(output)['members'].size > 0
|
156
|
+
docstring.append(ResponseStructureExample.new(shape_ref:output, api:@api).to_s)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def apply_overload_tag(docstring)
|
161
|
+
docstring.append("@overload #{@method_name}(params = {})")
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module AwsSdkCodeGenerator
|
2
|
+
module Generators
|
3
|
+
class ErrorsModule < Dsl::Module
|
4
|
+
|
5
|
+
include Helper
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@api = options.fetch(:api)
|
9
|
+
super('Errors')
|
10
|
+
self.extend('Aws::Errors::DynamicErrors')
|
11
|
+
self.class('ResourceNotLoadable', extends: 'RuntimeError') do |c|
|
12
|
+
c.docstring(<<-DOCSTRING)
|
13
|
+
Raised when calling #load or #data on a resource class that can not be
|
14
|
+
loaded. This can happen when:
|
15
|
+
|
16
|
+
* A resource class has identifiers, but no data attributes.
|
17
|
+
* Resource data is only available when making an API call that
|
18
|
+
enumerates all resources of that type.
|
19
|
+
DOCSTRING
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module AwsSdkCodeGenerator
|
2
|
+
module Generators
|
3
|
+
module Resource
|
4
|
+
class Action < Dsl::Method
|
5
|
+
|
6
|
+
include Helper
|
7
|
+
|
8
|
+
# @option options [required, String] :name
|
9
|
+
# @option options [required, Hash] :action
|
10
|
+
# @option options [required, Hash] :api
|
11
|
+
# @option options [String] :var_name ('')
|
12
|
+
def initialize(options = {})
|
13
|
+
@api = options.fetch(:api)
|
14
|
+
@request = options.fetch(:action).fetch('request')
|
15
|
+
@resource = options.fetch(:action).fetch('resource', nil)
|
16
|
+
@var_name = options.fetch(:var_name, '')
|
17
|
+
super(underscore(options.fetch(:name)))
|
18
|
+
param('options', type:Hash, default:{})
|
19
|
+
apply_client_request_docs
|
20
|
+
apply_response
|
21
|
+
apply_return_tag
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def apply_client_request_docs
|
27
|
+
ClientRequestDocs.new(
|
28
|
+
request: @request,
|
29
|
+
api: @api,
|
30
|
+
var_name: @var_name,
|
31
|
+
returns: @resource ? @resource['type'].downcase : nil
|
32
|
+
).apply(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
def apply_response
|
36
|
+
if @resource && batch?(@resource)
|
37
|
+
code('batch = []')
|
38
|
+
add(client_request)
|
39
|
+
code(BatchBuilder.new(resource: @resource))
|
40
|
+
code("#{resource_type}::Collection.new([batch], size: batch.size)")
|
41
|
+
elsif @resource
|
42
|
+
add(client_request)
|
43
|
+
code(Builder.new(resource: @resource, request_made: true))
|
44
|
+
else
|
45
|
+
add(client_request)
|
46
|
+
code('resp.data')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def client_request
|
51
|
+
ClientRequest.new(
|
52
|
+
request: @request,
|
53
|
+
resp: true
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
def apply_return_tag
|
58
|
+
if @resource && batch?(@resource)
|
59
|
+
returns("#{resource_type}::Collection")
|
60
|
+
elsif @resource
|
61
|
+
returns(resource_type)
|
62
|
+
else
|
63
|
+
returns(request_return_type)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def resource_type
|
68
|
+
@resource['type']
|
69
|
+
end
|
70
|
+
|
71
|
+
def request_return_type
|
72
|
+
operation = @api['operations'][@request['operation']]
|
73
|
+
if operation['output']
|
74
|
+
"Types::#{operation['output']['shape']}"
|
75
|
+
else
|
76
|
+
'EmptyStructure'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def batch?(resource)
|
81
|
+
paths = (@resource['identifiers'] || []).map {|i| i['path'] }
|
82
|
+
paths << @resource['path']
|
83
|
+
paths.compact.any? { |path| path.match(/\[/) }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module AwsSdkCodeGenerator
|
4
|
+
module Generators
|
5
|
+
module Resource
|
6
|
+
class BatchBuilder < Dsl::CodeLiteral
|
7
|
+
|
8
|
+
include Helper
|
9
|
+
|
10
|
+
# @option options [required, Hash] :resource
|
11
|
+
# @option options [String] :resp_var_name ('resp')
|
12
|
+
def initialize(options)
|
13
|
+
@resource = options.fetch(:resource)
|
14
|
+
@resp_var_name = options.fetch(:resp_var_name, 'resp')
|
15
|
+
verify_resource!
|
16
|
+
@context = loop_context
|
17
|
+
super()
|
18
|
+
|
19
|
+
# create nested blocks from each loop expression
|
20
|
+
stack = [self]
|
21
|
+
loops.each do |loop_expression|
|
22
|
+
stack.last.append(loop_expression)
|
23
|
+
stack << stack.last.indent
|
24
|
+
end
|
25
|
+
|
26
|
+
# add resource to the batch
|
27
|
+
stack.last.append("batch << #{resource_class}.new(#{constructor_args})")
|
28
|
+
|
29
|
+
# add closing end tags
|
30
|
+
stack.pop
|
31
|
+
stack.each { |c| c.append('end') }
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def resource_class
|
37
|
+
@resource['type']
|
38
|
+
end
|
39
|
+
|
40
|
+
def constructor_args
|
41
|
+
hash = {}
|
42
|
+
hash.update(identifiers)
|
43
|
+
hash[:data] = data_path if @resource['path']
|
44
|
+
hash[:client] = "@client"
|
45
|
+
HashFormatter.new(wrap:false, inline:true).format(hash)
|
46
|
+
end
|
47
|
+
|
48
|
+
def identifiers
|
49
|
+
(@resource['identifiers'] || []).inject({}) do |hash, identifier|
|
50
|
+
value = relative_identifier_path(identifier)
|
51
|
+
hash[underscore(identifier['target']).to_sym] = value
|
52
|
+
hash
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def data_path
|
57
|
+
relative_identifier_path({
|
58
|
+
'source' => 'data',
|
59
|
+
'path' => @resource['path'],
|
60
|
+
})
|
61
|
+
end
|
62
|
+
|
63
|
+
def relative_identifier_path(identifier)
|
64
|
+
path = identifier['path']
|
65
|
+
if path && path.include?('[]')
|
66
|
+
prefix = loops.last.match(/\|(.+)\|/)[1]
|
67
|
+
suffix = underscore(path[common_prefix.length..-1])
|
68
|
+
if @context == :options
|
69
|
+
suffix = suffix.gsub(/\.\w+/) { |word| "[:#{word[1..-1]}]" }
|
70
|
+
end
|
71
|
+
suffix.length == 0 ? prefix : prefix + suffix
|
72
|
+
else
|
73
|
+
ValueSource.new(identifier).to_s
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def common_prefix
|
78
|
+
paths = plural_paths
|
79
|
+
if paths.empty?
|
80
|
+
''
|
81
|
+
elsif paths.size == 1
|
82
|
+
# grab everything upto and including the final []
|
83
|
+
paths.first.match(/(.+\[\]).*?$/)[1]
|
84
|
+
else
|
85
|
+
prefix = find_prefix(paths)
|
86
|
+
prefix = prefix.sub(/\[\].+?$/, '[]')
|
87
|
+
if prefix[-2..-1] != '[]'
|
88
|
+
msg = 'response paths must have a common prefix ending in [], got :'
|
89
|
+
msg << paths.inspect
|
90
|
+
raise ArgumentError, msg
|
91
|
+
else
|
92
|
+
prefix
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def find_prefix(paths)
|
98
|
+
prefix = ''
|
99
|
+
loop.with_index do |_, n|
|
100
|
+
return prefix if paths.empty?
|
101
|
+
letter = paths[0][n]
|
102
|
+
paths.each do |path|
|
103
|
+
return prefix if path[n].nil?
|
104
|
+
return prefix if path[n] != letter
|
105
|
+
end
|
106
|
+
prefix += letter
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def loops
|
111
|
+
loop_var =
|
112
|
+
case @context
|
113
|
+
when :data then 'data.'
|
114
|
+
when :options then 'options'
|
115
|
+
when :response then "#{@resp_var_name}.data."
|
116
|
+
end
|
117
|
+
|
118
|
+
used_vars = Set.new
|
119
|
+
used_vars << loop_var
|
120
|
+
|
121
|
+
parts = common_prefix.split('[]')
|
122
|
+
parts = parts.map.with_index do |part,n|
|
123
|
+
part = underscore(part)
|
124
|
+
if @context == :options
|
125
|
+
part = part.gsub(/\w+/) { |word| "[:#{word}]" }
|
126
|
+
part = part.gsub(/\./, '')
|
127
|
+
end
|
128
|
+
part = "#{loop_var}#{part}"
|
129
|
+
loop_var = loop_letter(part, used_vars)
|
130
|
+
part = part + ".each do |#{loop_var}|"
|
131
|
+
part
|
132
|
+
end
|
133
|
+
parts
|
134
|
+
end
|
135
|
+
|
136
|
+
def loop_letter(str, used_vars)
|
137
|
+
letter = if @context == :options
|
138
|
+
str.scan(/:\w/).last[1]
|
139
|
+
else
|
140
|
+
str.split('.').last[0]
|
141
|
+
end
|
142
|
+
n = 1
|
143
|
+
var = letter
|
144
|
+
while used_vars.include?(var)
|
145
|
+
n += 1
|
146
|
+
var = "#{letter}#{n}"
|
147
|
+
end
|
148
|
+
used_vars << var
|
149
|
+
var
|
150
|
+
end
|
151
|
+
|
152
|
+
def all_plural_paths
|
153
|
+
paths = {}
|
154
|
+
@resource['identifiers'].each do |i|
|
155
|
+
if i['path'] && i['path'].include?('[]')
|
156
|
+
paths[i['source']] ||= []
|
157
|
+
paths[i['source']] << i['path']
|
158
|
+
end
|
159
|
+
end
|
160
|
+
#if @resource['path'] && @resource['path'].include?('[]')
|
161
|
+
# type = @context == :data ? 'data' : 'response'
|
162
|
+
# paths[type] ||= []
|
163
|
+
# paths[type] << @resource['path']
|
164
|
+
#end
|
165
|
+
paths
|
166
|
+
end
|
167
|
+
|
168
|
+
def plural_paths
|
169
|
+
all_plural_paths.values.first
|
170
|
+
end
|
171
|
+
|
172
|
+
def verify_resource!
|
173
|
+
verify_plural_paths!
|
174
|
+
end
|
175
|
+
|
176
|
+
def verify_plural_paths!
|
177
|
+
paths = all_plural_paths
|
178
|
+
case paths.size
|
179
|
+
when 0
|
180
|
+
msg = 'expected at least one plural identifier path, got none'
|
181
|
+
raise ArgumentError, msg
|
182
|
+
when 1
|
183
|
+
case paths.keys.first
|
184
|
+
when 'requestParameter'
|
185
|
+
when 'response'
|
186
|
+
when 'data'
|
187
|
+
else
|
188
|
+
msg = "unsupported identifier source #{paths.keys.first.inspect}"
|
189
|
+
raise ArgumentError, msg
|
190
|
+
end
|
191
|
+
else
|
192
|
+
msg = 'mixing plural source types is not supported'
|
193
|
+
raise ArgumentError, msg
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def loop_context
|
198
|
+
case all_plural_paths.keys
|
199
|
+
when ['response'] then :response
|
200
|
+
when ['data'] then :data
|
201
|
+
when ['requestParameter'] then :options
|
202
|
+
else
|
203
|
+
msg = "unable to determine loop context: #{@resource.inspect}"
|
204
|
+
raise msg
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|