Skip to content

Commit 611572f

Browse files
aschuster3dblock
authored andcommitted
Include documented Hashes (#454)
* Fix logic for mapping Hash and Array objects to refs * Add tests to account for documented Hashes and Arrays * Do not include readOnly params in request definitions * Test for new documentation behavior * Update changelog [ci skip] * Use respond_to? instead of try for earlier compliance * Use proper url for changelog
1 parent 6ef800c commit 611572f

12 files changed

+97
-18
lines changed

CHANGELOG.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
#### Features
44

55
* [#448](https://github.com/ruby-grape/grape-swagger/pull/448): Header parameters are now prepended to the parameter list - [@anakinj](https://github.com/anakinj).
6-
* [#444](https://github.com/ruby-grape/grape-swagger/pull/444): With multi types parameter the first type is use as the documentation type [@scauglog](https://github.com/scauglog)
6+
* [#444](https://github.com/ruby-grape/grape-swagger/pull/444): With multi types parameter the first type is use as the documentation type [@scauglog](https://github.com/scauglog).
7+
* Your contribution here.
78

89
#### Fixes
910

1011
* [#450](https://github.com/ruby-grape/grape-swagger/pull/438): Do not add :description to definitions if :description is missing on path - [@texpert](https://github.com/texpert).
1112
* [#447](https://github.com/ruby-grape/grape-swagger/pull/447): Version part of the url is now ignored when generating tags for endpoint - [@anakinj](https://github.com/anakinj).
12-
* [#444](https://github.com/ruby-grape/grape-swagger//pull/444): Default value provided in the documentation hash, override the grape default [@scauglog](https://github.com/scauglog)
13-
* [#443](https://github.com/ruby-grape/grape-swagger/issues/443): Type provided in the documentation hash, override the grape type [@scauglog](https://github.com/scauglog)
13+
* [#444](https://github.com/ruby-grape/grape-swagger//pull/444): Default value provided in the documentation hash, override the grape default [@scauglog](https://github.com/scauglog).
14+
* [#443](https://github.com/ruby-grape/grape-swagger/issues/443): Type provided in the documentation hash, override the grape type [@scauglog](https://github.com/scauglog).
15+
* [#454](https://github.com/ruby-grape/grape-swagger/pull/454): Include documented Hashes in documentation output - [@aschuster3](https://github.com/aschuster3).
16+
* Your contribution here.
1417

1518
### 0.21.0 (June 1, 2016)
1619

lib/grape-swagger/doc_methods/move_params.rb

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ def move_params_to_new(name, params)
6363
end
6464
end
6565

66-
properties[name][:readOnly] = true unless deletable?(param)
6766
params.delete(param) if deletable?(param)
6867

6968
definition[:required] << name if deletable?(param) && param[:required]
@@ -144,13 +143,11 @@ def property_keys
144143
end
145144

146145
def movable?(param)
147-
return true if param[:in] == 'body' || param[:in] == 'path'
148-
false
146+
param[:in] == 'body'
149147
end
150148

151149
def deletable?(param)
152-
return true if movable?(param) && param[:in] == 'body'
153-
false
150+
param[:in] == 'body'
154151
end
155152

156153
def should_move?(params)

lib/grape-swagger/endpoint.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ def parse_request_params(required)
231231
else
232232
key = param.first
233233
end
234-
memo[key] = param.last unless param.last[:type] == 'Hash' || param.last[:type] == 'Array' && !param.last.key?(:documentation)
234+
memo[key] = param.last unless (param.last[:type] == 'Hash' || param.last[:type] == 'Array') && !param.last.key?(:documentation)
235235
end
236236
end
237237

spec/lib/move_params_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@
184184
describe 'movable' do
185185
describe 'path' do
186186
let(:param) { { in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true } }
187-
it { expect(subject.send(:movable?, param)).to be true }
187+
it { expect(subject.send(:movable?, param)).to be false }
188188
end
189189

190190
describe 'body' do

spec/support/model_parsers/entity_parser.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ class RecursiveModel < Grape::Entity
116116
expose :name, documentation: { type: String, desc: 'The name.' }
117117
expose :children, using: self, documentation: { type: 'RecursiveModel', is_array: true, desc: 'The child nodes.' }
118118
end
119+
120+
class DocumentedHashAndArrayModel < Grape::Entity
121+
expose :raw_hash, documentation: { type: Hash, desc: 'Example Hash.', documentation: { in: 'body' } }
122+
expose :raw_array, documentation: { type: Array, desc: 'Example Array', documentation: { in: 'body' } }
123+
end
119124
end
120125
end
121126

@@ -124,7 +129,8 @@ class RecursiveModel < Grape::Entity
124129
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'status code' }, 'message' => { 'type' => 'string', 'description' => 'error message' } } },
125130
'ResponseItem' => { 'type' => 'object', 'properties' => { 'id' => { 'type' => 'integer', 'format' => 'int32' }, 'name' => { 'type' => 'string' } } },
126131
'UseResponse' => { 'type' => 'object', 'properties' => { 'description' => { 'type' => 'string' }, '$responses' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/ResponseItem' } } } },
127-
'RecursiveModel' => { 'type' => 'object', 'properties' => { 'name' => { 'type' => 'string', 'description' => 'The name.' }, 'children' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/RecursiveModel' }, 'description' => 'The child nodes.' } } }
132+
'RecursiveModel' => { 'type' => 'object', 'properties' => { 'name' => { 'type' => 'string', 'description' => 'The name.' }, 'children' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/RecursiveModel' }, 'description' => 'The child nodes.' } } },
133+
'DocumentedHashAndArrayModel' => { 'type' => 'object', 'properties' => { 'raw_hash' => { 'type' => 'object', 'description' => 'Example Hash.' }, 'raw_array' => { 'type' => 'array', 'description' => 'Example Array' } } }
128134
}
129135
end
130136

spec/support/model_parsers/mock_parser.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class QueryInput < OpenStruct; end
5252
class ApiError < OpenStruct; end
5353
class SecondApiError < OpenStruct; end
5454
class RecursiveModel < OpenStruct; end
55+
class DocumentedHashAndArrayModel < OpenStruct; end
5556
end
5657
end
5758

@@ -83,6 +84,15 @@ class RecursiveModel < OpenStruct; end
8384
'description' => "it's a mock"
8485
}
8586
}
87+
},
88+
'DocumentedHashAndArrayModel' => {
89+
'type' => 'object',
90+
'properties' => {
91+
'mock_data' => {
92+
'type' => 'string',
93+
'description' => "it's a mock"
94+
}
95+
}
8696
}
8797
}
8898
end

spec/support/model_parsers/representable_parser.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ class RecursiveModel < Representable::Decorator
186186
property :name, documentation: { type: String, desc: 'The name.' }
187187
property :children, decorator: self, documentation: { type: 'RecursiveModel', is_array: true, desc: 'The child nodes.' }
188188
end
189+
190+
class DocumentedHashAndArrayModel < Representable::Decorator
191+
include Representable::JSON
192+
193+
property :raw_hash, documentation: { type: Hash, desc: 'Example Hash.' }
194+
property :raw_array, documentation: { type: Array, desc: 'Example Array' }
195+
end
189196
end
190197
end
191198

spec/support/the_paths_definitions.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@
9797
properties: {
9898
in_body_1: { type: 'integer', format: 'int32', description: 'in_body_1' },
9999
in_body_2: { type: 'string', description: 'in_body_2' },
100-
in_body_3: { type: 'string', description: 'in_body_3' },
101-
key: { type: 'integer', format: 'int32', readOnly: true }
100+
in_body_3: { type: 'string', description: 'in_body_3' }
102101
},
103102
required: [:in_body_1]
104103
}

spec/swagger_v2/api_swagger_v2_definitions-models_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ class ModelApi < Grape::API
1111
add_swagger_documentation models: [
1212
::Entities::UseResponse,
1313
::Entities::ApiError,
14-
::Entities::RecursiveModel
14+
::Entities::RecursiveModel,
15+
::Entities::DocumentedHashAndArrayModel
1516
]
1617
end
1718
end
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
require 'spec_helper'
2+
3+
describe 'document hash and array' do
4+
include_context "#{MODEL_PARSER} swagger example"
5+
6+
before :all do
7+
module TheApi
8+
class TestApi < Grape::API
9+
format :json
10+
11+
documentation = ::Entities::DocumentedHashAndArrayModel.documentation if ::Entities::DocumentedHashAndArrayModel.respond_to?(:documentation)
12+
13+
desc 'This returns something'
14+
namespace :arbitrary do
15+
params do
16+
requires :id, type: Integer
17+
end
18+
route_param :id do
19+
desc 'Timeless treasure'
20+
params do
21+
requires :body, using: documentation unless documentation.nil?
22+
requires :raw_hash, type: Hash, documentation: { param_type: 'body' } if documentation.nil?
23+
requires :raw_array, type: Array, documentation: { param_type: 'body' } if documentation.nil?
24+
end
25+
put '/id_and_hash' do
26+
{}
27+
end
28+
end
29+
end
30+
31+
add_swagger_documentation
32+
end
33+
end
34+
end
35+
36+
def app
37+
TheApi::TestApi
38+
end
39+
40+
subject do
41+
get '/swagger_doc'
42+
JSON.parse(last_response.body)
43+
end
44+
describe 'generated request definition' do
45+
it 'has hash' do
46+
expect(subject['definitions'].keys).to include('putArbitraryIdIdAndHash')
47+
expect(subject['definitions']['putArbitraryIdIdAndHash']['properties'].keys).to include('raw_hash')
48+
end
49+
50+
it 'has array' do
51+
expect(subject['definitions'].keys).to include('putArbitraryIdIdAndHash')
52+
expect(subject['definitions']['putArbitraryIdIdAndHash']['properties'].keys).to include('raw_array')
53+
end
54+
55+
it 'does not have the path parameter' do
56+
expect(subject['definitions'].keys).to include('putArbitraryIdIdAndHash')
57+
expect(subject['definitions']['putArbitraryIdIdAndHash']).to_not include('id')
58+
end
59+
end
60+
end

spec/swagger_v2/api_swagger_v2_param_type_body_nested_spec.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ def app
137137
'type' => 'object',
138138
'properties' => {
139139
'address' => { '$ref' => '#/definitions/putRequestUseNestedWithAddressAddress' },
140-
'id' => { 'type' => 'integer', 'format' => 'int32', 'readOnly' => true },
141140
'name' => { 'type' => 'string', 'description' => 'name' }
142141
}
143142
)
@@ -176,7 +175,6 @@ def app
176175
'properties' => {
177176
'address' => { '$ref' => '#/definitions/putRequestUseNestedWithAddressAddress' },
178177
'delivery_address' => { '$ref' => '#/definitions/putRequestUseNestedWithAddressDeliveryAddress' },
179-
'id' => { 'type' => 'integer', 'format' => 'int32', 'readOnly' => true },
180178
'name' => { 'type' => 'string', 'description' => 'name' }
181179
}
182180
)

spec/swagger_v2/api_swagger_v2_param_type_body_spec.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ def app
104104
'description' => 'put in body /wo entity',
105105
'type' => 'object',
106106
'properties' => {
107-
'key' => { 'type' => 'integer', 'format' => 'int32', 'readOnly' => true },
108107
'in_body_1' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'in_body_1' },
109108
'in_body_2' => { 'type' => 'string', 'description' => 'in_body_2' },
110109
'in_body_3' => { 'type' => 'string', 'description' => 'in_body_3' }
@@ -152,7 +151,6 @@ def app
152151
'description' => 'put in body with entity',
153152
'type' => 'object',
154153
'properties' => {
155-
'id' => { 'type' => 'integer', 'format' => 'int32', 'readOnly' => true },
156154
'name' => { 'type' => 'string', 'description' => 'name' }
157155
}
158156
)

0 commit comments

Comments
 (0)