Skip to content

Commit 4f5c54d

Browse files
author
LeFnord
committed
refoctors building definitions for body params
- adds base spec
1 parent 756feb5 commit 4f5c54d

File tree

6 files changed

+122
-193
lines changed

6 files changed

+122
-193
lines changed

.rubocop_todo.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Metrics/AbcSize:
2828
# Offense count: 3
2929
# Configuration parameters: CountComments.
3030
Metrics/ClassLength:
31-
Max: 216
31+
Max: 223
3232

3333
# Offense count: 10
3434
Metrics/CyclomaticComplexity:

lib/grape-swagger/doc_methods/move_params.rb

+37-54
Original file line numberDiff line numberDiff line change
@@ -2,54 +2,38 @@ module GrapeSwagger
22
module DocMethods
33
class MoveParams
44
class << self
5-
def to_definition(paths, definitions)
6-
@definitions = definitions
5+
attr_accessor :definitions
76

8-
find_post_put(paths) do |method_definition|
9-
verb = method_definition.keys.first
10-
method_object = method_definition[verb]
7+
def to_definition(params, route, definitions)
8+
@definitions = definitions
119

12-
find_definition_and_params(method_object, verb)
13-
end
10+
parent_definition_of_params(params, route)
1411
end
1512

16-
def find_post_put(paths)
17-
paths.each do |x|
18-
found = x.last.select { |y| move_methods.include?(y) }
19-
yield found unless found.empty?
20-
end
13+
def can_be_moved?(params, http_verb)
14+
move_methods.include?(http_verb) && includes_body_param?(params)
2115
end
2216

23-
def find_definition_and_params(path, verb)
24-
params = path[:parameters]
25-
26-
return if params.nil?
27-
return unless should_move?(params)
28-
17+
def parent_definition_of_params(params, route)
2918
unify!(params)
3019

31-
status_code = GrapeSwagger::DocMethods::StatusCodes.get[verb.to_sym][:code]
32-
response = path[:responses][status_code]
20+
definition_name = GrapeSwagger::DocMethods::OperationId.manipulate(parse_model(route.path))
21+
referenced_definition = build_definition(definition_name, route.request_method.downcase)
22+
definition = @definitions[referenced_definition]
3323

34-
if response[:schema] && response[:schema]['$ref']
35-
referenced_definition = parse_model(response[:schema]['$ref'])
36-
name = build_definition(referenced_definition, verb)
37-
else
38-
referenced_definition = path[:operationId]
39-
name = build_definition(referenced_definition)
40-
end
24+
move_params_to_new(referenced_definition, definition, params)
25+
26+
definition[:description] = route.description if route.respond_to?(:description)
4127

42-
move_params_to_new(name, params)
28+
params << build_body_parameter(referenced_definition, definition_name)
4329

44-
@definitions[name][:description] = path[:description] if path[:description]
45-
path[:parameters] << build_body_parameter(response.dup, name)
30+
params
4631
end
4732

48-
def move_params_to_new(name, params)
33+
def move_params_to_new(definition_name, definition, params)
4934
properties = {}
50-
definition = @definitions[name]
5135

52-
nested_definitions(name, params, properties)
36+
nested_definitions(definition_name, params, properties)
5337

5438
params.dup.each do |param|
5539
next unless movable?(param)
@@ -64,7 +48,6 @@ def move_params_to_new(name, params)
6448
end
6549

6650
params.delete(param) if deletable?(param)
67-
6851
definition[:required] << name if deletable?(param) && param[:required]
6952
end
7053

@@ -90,29 +73,28 @@ def nested_definitions(name, params, properties)
9073
else
9174
properties[nested_name] = { '$ref' => "#/definitions/#{def_name}" }
9275
end
76+
9377
prepare_nested_names(nested)
94-
build_definition(def_name)
95-
@definitions[def_name][:description] = "#{name} - #{nested_name}"
96-
move_params_to_new(def_name, nested)
78+
definition = build_definition(def_name)
79+
@definitions[definition][:description] = "#{name} - #{nested_name}"
80+
move_params_to_new(definition, @definitions[definition], nested)
9781
end
9882
end
9983

10084
private
10185

102-
def build_body_parameter(response, name = false)
103-
entity = response[:schema] ? parse_model(response[:schema]['$ref']) : name
86+
def build_body_parameter(reference, name)
10487
body_param = {}
10588
body_param.tap do |x|
106-
x[:name] = entity
89+
x[:name] = name
10790
x[:in] = 'body'
10891
x[:required] = true
109-
x[:schema] = { '$ref' => response[:schema]['$ref'] } unless name
110-
x[:schema] = { '$ref' => "#/definitions/#{name}" } if name
92+
x[:schema] = { '$ref' => "#/definitions/#{reference}" }
11193
end
11294
end
11395

11496
def build_definition(name, verb = nil)
115-
name = "#{verb}Request#{name}" if verb
97+
name = "#{verb}#{name}" if verb
11698
@definitions[name] = { type: 'object', properties: {}, required: [] }
11799

118100
name
@@ -136,18 +118,13 @@ def prepare_nested_names(params)
136118
end
137119

138120
def unify!(params)
139-
params.each do |param|
140-
param[:in] = param.delete(:param_type) if param.key?(:param_type)
141-
param[:in] = 'body' if param[:in] == 'formData'
142-
end
121+
params.each { |x| x[:in] = x.delete(:param_type) if x[:param_type] }
122+
params.each { |x| x[:in] = 'body' if x[:in] == 'formData' } if includes_body_param?(params)
143123
end
144124

145125
def parse_model(ref)
146-
ref.split('/').last
147-
end
148-
149-
def move_methods
150-
[:post, :put, :patch]
126+
parts = ref.split('/')
127+
parts.last.include?('{') ? parts[0..-2].join('/') : parts[0..-1].join('/')
151128
end
152129

153130
def property_keys
@@ -157,10 +134,16 @@ def property_keys
157134
def movable?(param)
158135
param[:in] == 'body'
159136
end
137+
160138
alias deletable? movable?
161139

162-
def should_move?(params)
163-
!params.select { |x| x[:in] == 'body' || x[:param_type] == 'body' }.empty?
140+
def move_methods
141+
[:post, :put, :patch, 'POST', 'PUT', 'PATCH']
142+
end
143+
144+
def includes_body_param?(params)
145+
params.map { |x| return true if x[:in] == 'body' }
146+
false
164147
end
165148
end
166149
end

lib/grape-swagger/endpoint.rb

+7-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ def path_and_definition_objects(namespace_routes, options)
7171
end
7272

7373
add_definitions_from options[:models]
74-
GrapeSwagger::DocMethods::MoveParams.to_definition(@paths, @definitions)
7574
[@paths, @definitions]
7675
end
7776

@@ -154,11 +153,17 @@ def consumes_object(route, format)
154153
end
155154

156155
def params_object(route)
157-
partition_params(route).map do |param, value|
156+
parameters = partition_params(route).map do |param, value|
158157
value = { required: false }.merge(value) if value.is_a?(Hash)
159158
_, value = default_type([[param, value]]).first if value == ''
160159
GrapeSwagger::DocMethods::ParseParams.call(param, value, route)
161160
end
161+
162+
if GrapeSwagger::DocMethods::MoveParams.can_be_moved?(parameters, route.request_method)
163+
parameters = GrapeSwagger::DocMethods::MoveParams.to_definition(parameters, route, @definitions)
164+
end
165+
166+
parameters
162167
end
163168

164169
def response_object(route, markdown)

spec/lib/move_params_spec.rb

+36-87
Original file line numberDiff line numberDiff line change
@@ -7,47 +7,22 @@
77

88
it { expect(subject.to_s).to eql 'GrapeSwagger::DocMethods::MoveParams' }
99

10-
describe 'find_post_put' do
11-
let(:paths) { {} }
12-
13-
describe 'paths empty' do
14-
specify { expect { |b| subject.find_post_put(paths, &b) }.not_to yield_control }
15-
end
16-
17-
describe 'no post/put given' do
18-
let(:paths) do
19-
{
20-
:'/foo' => { get: {}, delete: {} },
21-
:'/bar/{key}' => { get: {}, delete: {} }
22-
}
23-
end
24-
specify { expect { |b| subject.find_post_put(paths, &b) }.not_to yield_control }
10+
describe 'parent_definition_of_params' do
11+
let(:params) { paths['/in_body'][:post][:parameters] }
12+
let(:options) do
13+
{
14+
method: 'POST'
15+
}
2516
end
17+
let(:env) { Rack::MockRequest.env_for('/in_body', options) }
18+
let(:request) { Grape::Request.new(env) }
2619

27-
describe 'no post/put given' do
28-
let(:paths) do
29-
{
30-
:'/foo' => { get: {}, delete: {}, post: {}, put: {}, patch: {} },
31-
:'/bar/{key}' => { get: {}, delete: {}, post: {}, put: {}, patch: {} }
32-
}
33-
end
34-
let(:expected) do
35-
[
36-
{ post: {}, put: {}, patch: {} },
37-
{ post: {}, put: {}, patch: {} }
38-
]
39-
end
40-
specify { expect { |b| subject.find_post_put(paths, &b) }.to yield_control.twice }
41-
specify { expect { |b| subject.find_post_put(paths, &b) }.to yield_successive_args *expected }
42-
end
43-
end
44-
45-
describe 'find_definition_and_params' do
4620
specify do
4721
subject.instance_variable_set(:@definitions, definitions)
48-
subject.find_definition_and_params(found_path[:post], :post)
49-
expect(definitions.keys).to include 'InBody'
50-
expect(definitions['postRequestInBody'].keys).to_not include :description
22+
body_definition = subject.parent_definition_of_params(params, request).first
23+
24+
expect(body_definition[:schema]['$ref']).to eql '#/definitions/postInBody'
25+
expect(subject.definitions['postInBody']).not_to include :description
5126
end
5227
end
5328

@@ -61,10 +36,9 @@
6136

6237
specify do
6338
subject.instance_variable_set(:@definitions, definitions)
64-
name = subject.send(:build_definition, name, verb)
65-
subject.move_params_to_new(name, params)
66-
67-
expect(definitions[name]).to eql expected_post_defs
39+
def_name = subject.send(:build_definition, name, verb)
40+
subject.move_params_to_new(def_name, definitions[def_name], params)
41+
expect(definitions[def_name]).to eql expected_post_defs
6842
expect(params).to be_empty
6943
end
7044
end
@@ -75,10 +49,11 @@
7549

7650
specify do
7751
subject.instance_variable_set(:@definitions, definitions)
78-
name, definition = subject.send(:build_definition, name, verb)
79-
subject.move_params_to_new(name, params)
8052

81-
expect(definitions[name]).to eql expected_put_defs
53+
def_name = subject.send(:build_definition, name, verb)
54+
subject.move_params_to_new(def_name, definitions[def_name], params)
55+
56+
expect(definitions[def_name]).to eql expected_put_defs
8257
expect(params.length).to be 1
8358
end
8459
end
@@ -130,7 +105,7 @@
130105

131106
specify do
132107
definition = definitions.to_a.first
133-
expect(definition.first).to eql 'postRequestFoo'
108+
expect(definition.first).to eql 'postFoo'
134109
expect(definition.last).to eql(type: 'object', properties: {}, required: [])
135110
end
136111
end
@@ -149,36 +124,33 @@
149124
end
150125

151126
describe 'build_body_parameter' do
152-
let(:response) { { schema: { '$ref' => '#/definitions/Somewhere' } } }
153-
154-
describe 'no name given' do
155-
let(:name) { nil }
156-
let(:expected_param) do
157-
{ name: 'Somewhere', in: 'body', required: true, schema: { '$ref' => '#/definitions/Somewhere' } }
158-
end
159-
specify do
160-
parameter = subject.send(:build_body_parameter, response)
161-
expect(parameter).to eql expected_param
162-
end
163-
end
164-
165127
describe 'name given' do
166128
let(:name) { 'Foo' }
129+
let(:reference) { 'Bar' }
167130
let(:expected_param) do
168-
{ name: 'Somewhere', in: 'body', required: true, schema: { '$ref' => "#/definitions/#{name}" } }
131+
{ name: name, in: 'body', required: true, schema: { '$ref' => "#/definitions/#{reference}" } }
169132
end
170133
specify do
171-
parameter = subject.send(:build_body_parameter, response, name)
134+
parameter = subject.send(:build_body_parameter, reference, name)
172135
expect(parameter).to eql expected_param
173136
end
174137
end
175138
end
176139

177140
describe 'parse_model' do
178141
let(:ref) { '#/definitions/InBody' }
179-
subject(:object) { described_class.send(:parse_model, ref) }
142+
describe 'post request' do
143+
subject(:object) { described_class.send(:parse_model, ref) }
144+
145+
specify { expect(object).to eql ref }
146+
end
147+
148+
describe 'post request' do
149+
let(:put_ref) { '#/definitions/InBody/{id}' }
150+
subject(:object) { described_class.send(:parse_model, put_ref) }
180151

181-
specify { expect(object).to eql 'InBody' }
152+
specify { expect(object).to eql ref }
153+
end
182154
end
183155

184156
describe 'movable' do
@@ -225,32 +197,9 @@
225197
end
226198
end
227199

228-
describe 'should move' do
229-
describe 'no move' do
230-
let(:params) do
231-
[
232-
{ in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
233-
{ in: 'formData', name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true }
234-
]
235-
end
236-
it { expect(subject.send(:should_move?, params)).to be false }
237-
end
238-
239-
describe 'move' do
240-
let(:params) do
241-
[
242-
{ in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
243-
{ in: 'body', name: 'in_bosy', description: 'in_bosy', type: 'integer', format: 'int32', required: true },
244-
{ in: 'formData', name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true }
245-
]
246-
end
247-
it { expect(subject.send(:should_move?, params)).to be true }
248-
end
249-
end
250-
251200
describe 'unify' do
252-
before do
253-
subject.send(:unify!, params) if subject.send(:should_move?, params)
201+
before :each do
202+
subject.send(:unify!, params)
254203
end
255204
describe 'param type with `:in` given' do
256205
let(:params) do

0 commit comments

Comments
 (0)