Skip to content

Commit 62ec685

Browse files
committed
build global tag set from route tags
- adds changelog entry - adds note in UPGRADING
1 parent 787dfe0 commit 62ec685

11 files changed

+113
-112
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
#### Features
44

5+
* [#524](https://github.com/ruby-grape/grape-swagger/pull/524): Use route tags for global tag set - [@LeFnord](https://github.com/LeFnord).
6+
* [#523](https://github.com/ruby-grape/grape-swagger/pull/523): Allow specifying custom tags at the route level - [@jordanfbrown](https://github.com/jordanfbrown).
57
* [#520](https://github.com/ruby-grape/grape-swagger/pull/520): Response model can have required attributes - [@WojciechKo](https://github.com/WojciechKo).
68
* [#510](https://github.com/ruby-grape/grape-swagger/pull/510): Use 'token_owner' instead of 'oauth_token' on Swagger UI endpoint authorization. - [@texpert](https://github.com/texpert).
7-
* [#523](https://github.com/ruby-grape/grape-swagger/pull/523): Allow specifying custom tags at the route level. - [@jordanfbrown](https://github.com/jordanfbrown).
89
* Your contribution here.
910

1011
#### Fixes

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ add_swagger_documentation \
394394
* [Overriding the tags](#tags)
395395
* [Defining an endpoint as an array](#array)
396396
* [Using an options hash](#options)
397-
* [Overriding param type](#overriding-param-type)
397+
* [Overriding parameter type](#overriding-param-type)
398398
* [Overriding data type of the parameter](#overriding-type-of-param)
399399
* [Multiple types](#multiple-types)
400400
* [Array of data type](#array-type)

UPGRADING.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
Upgrading Grape-swagger
22
=======================
33

4+
### Upgrading to >= 0.25.0
5+
6+
The global tag set now only includes tags for documented routes. This behaviour has impact in particular for calling the documtation of a specific route.
7+
48
### Upgrading to >= 0.21.0
59

610
With grape >= 0.21.0, `grape-entity` support moved to separate gem `grape-swagger-entity`, if you use grape entity, update your Gemfile:

lib/grape-swagger/doc_methods.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ def setup(options)
5050
options
5151
)
5252

53-
paths, definitions = endpoint.path_and_definition_objects(combi_routes, options)
53+
paths, definitions = endpoint.path_and_definition_objects(combi_routes, options)
54+
tags = GrapeSwagger::DocMethods::TagNameDescription.build(paths)
55+
output[:tags] = tags unless tags.empty? || paths.blank?
5456
output[:paths] = paths unless paths.blank?
5557
output[:definitions] = definitions unless definitions.blank?
5658

lib/grape-swagger/doc_methods/tag_name_description.rb

+9-17
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,15 @@ module GrapeSwagger
22
module DocMethods
33
class TagNameDescription
44
class << self
5-
def build(options = {})
6-
target_class = options[:target_class]
7-
namespaces = target_class.combined_namespaces
8-
namespace_routes = target_class.combined_namespace_routes
9-
10-
namespace_routes.keys.map do |local_route|
11-
next if namespace_routes[local_route].map { |route| route.options[:hidden] }.all? { |value| value.respond_to?(:call) ? value.call : value }
12-
13-
original_namespace_name = target_class.combined_namespace_identifiers.key?(local_route) ? target_class.combined_namespace_identifiers[local_route] : local_route
14-
description = namespaces[original_namespace_name] && namespaces[original_namespace_name].options[:desc]
15-
description ||= "Operations about #{original_namespace_name.pluralize}"
16-
17-
{
18-
name: local_route,
19-
description: description
20-
}
21-
end.compact
5+
def build(paths)
6+
paths.values.each_with_object([]) do |path, memo|
7+
path.values.first[:tags].each do |tag|
8+
memo << {
9+
name: tag,
10+
description: "Operations about #{tag.pluralize}"
11+
}
12+
end
13+
end.uniq
2214
end
2315
end
2416
end

lib/grape-swagger/endpoint.rb

-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ def swagger_object(target_class, request, options)
2929
securityDefinitions: options[:security_definitions],
3030
host: GrapeSwagger::DocMethods::OptionalObject.build(:host, options, request),
3131
basePath: GrapeSwagger::DocMethods::OptionalObject.build(:base_path, options, request),
32-
tags: GrapeSwagger::DocMethods::TagNameDescription.build(options),
3332
schemes: options[:schemes].is_a?(String) ? [options[:schemes]] : options[:schemes]
3433
}.delete_if { |_, value| value.blank? }
3534
end

spec/swagger_v2/api_swagger_v2_spec.rb

+87-61
Original file line numberDiff line numberDiff line change
@@ -118,91 +118,117 @@ def app
118118
end
119119
end
120120

121-
before do
122-
get '/v3/swagger_doc'
123-
end
121+
describe 'whole documentation' do
122+
subject do
123+
get '/v3/swagger_doc'
124+
JSON.parse(last_response.body)
125+
end
124126

125-
let(:json) { JSON.parse(last_response.body) }
127+
describe 'swagger object' do
128+
describe 'required keys' do
129+
it { expect(subject.keys).to include 'swagger' }
130+
it { expect(subject['swagger']).to eql '2.0' }
131+
it { expect(subject.keys).to include 'info' }
132+
it { expect(subject['info']).to be_a Hash }
133+
it { expect(subject.keys).to include 'paths' }
134+
it { expect(subject['paths']).to be_a Hash }
135+
end
126136

127-
describe 'swagger object' do
128-
describe 'required keys' do
129-
it { expect(json.keys).to include 'swagger' }
130-
it { expect(json['swagger']).to eql '2.0' }
131-
it { expect(json.keys).to include 'info' }
132-
it { expect(json['info']).to be_a Hash }
133-
it { expect(json.keys).to include 'paths' }
134-
it { expect(json['paths']).to be_a Hash }
135-
end
137+
describe 'info object required keys' do
138+
let(:info) { subject['info'] }
139+
140+
it { expect(info.keys).to include 'title' }
141+
it { expect(info['title']).to be_a String }
142+
it { expect(info.keys).to include 'version' }
143+
it { expect(info['version']).to be_a String }
136144

137-
describe 'info object required keys' do
138-
let(:info) { json['info'] }
145+
describe 'license object' do
146+
let(:license) { subject['info']['license'] }
139147

140-
it { expect(info.keys).to include 'title' }
141-
it { expect(info['title']).to be_a String }
142-
it { expect(info.keys).to include 'version' }
143-
it { expect(info['version']).to be_a String }
148+
it { expect(license.keys).to include 'name' }
149+
it { expect(license['name']).to be_a String }
150+
it { expect(license.keys).to include 'url' }
151+
it { expect(license['url']).to be_a String }
152+
end
144153

145-
describe 'license object' do
146-
let(:license) { json['info']['license'] }
154+
describe 'contact object' do
155+
let(:contact) { subject['info']['contact'] }
147156

148-
it { expect(license.keys).to include 'name' }
149-
it { expect(license['name']).to be_a String }
150-
it { expect(license.keys).to include 'url' }
151-
it { expect(license['url']).to be_a String }
152-
end
157+
it { expect(contact.keys).to include 'name' }
158+
it { expect(contact['name']).to be_a String }
159+
it { expect(contact.keys).to include 'email' }
160+
it { expect(contact['email']).to be_a String }
161+
it { expect(contact.keys).to include 'url' }
162+
it { expect(contact['url']).to be_a String }
163+
end
153164

154-
describe 'contact object' do
155-
let(:contact) { json['info']['contact'] }
165+
describe 'global tags' do
166+
let(:tags) { subject['tags'] }
156167

157-
it { expect(contact.keys).to include 'name' }
158-
it { expect(contact['name']).to be_a String }
159-
it { expect(contact.keys).to include 'email' }
160-
it { expect(contact['email']).to be_a String }
161-
it { expect(contact.keys).to include 'url' }
162-
it { expect(contact['url']).to be_a String }
168+
it { expect(tags).to be_a Array }
169+
it { expect(tags).not_to be_empty }
170+
end
163171
end
164-
end
165172

166-
describe 'path object' do
167-
let(:paths) { json['paths'] }
173+
describe 'path object' do
174+
let(:paths) { subject['paths'] }
168175

169-
it 'hides documentation paths per default' do
170-
expect(paths.keys).not_to include '/swagger_doc', '/swagger_doc/{name}'
171-
end
176+
it 'hides documentation paths per default' do
177+
expect(paths.keys).not_to include '/swagger_doc', '/swagger_doc/{name}'
178+
end
172179

173-
specify do
174-
paths.each_pair do |path, value|
175-
expect(path).to start_with('/')
176-
expect(value).to be_a Hash
177-
expect(value).not_to be_empty
180+
specify do
181+
paths.each_pair do |path, value|
182+
expect(path).to start_with('/')
183+
expect(value).to be_a Hash
184+
expect(value).not_to be_empty
178185

179-
value.each do |method, declaration|
180-
expect(http_verbs).to include method
181-
expect(declaration).to have_key('responses')
186+
value.each do |method, declaration|
187+
expect(http_verbs).to include method
188+
expect(declaration).to have_key('responses')
182189

183-
declaration['responses'].each do |status_code, response|
184-
expect(status_code).to match(/\d{3}/)
185-
expect(response).to have_key('description')
190+
declaration['responses'].each do |status_code, response|
191+
expect(status_code).to match(/\d{3}/)
192+
expect(response).to have_key('description')
193+
end
186194
end
187195
end
188196
end
189197
end
190-
end
191198

192-
describe 'definitions object' do
193-
let(:definitions) { json['definitions'] }
194-
specify do
195-
definitions.each do |model, properties|
196-
expect(model).to match(/\w+/)
197-
expect(properties).to have_key('properties')
199+
describe 'definitions object' do
200+
let(:definitions) { subject['definitions'] }
201+
202+
specify do
203+
definitions.each do |model, properties|
204+
expect(model).to match(/\w+/)
205+
expect(properties).to have_key('properties')
206+
end
198207
end
199208
end
200209
end
210+
211+
describe 'swagger file' do
212+
it do
213+
expect(subject).to eql swagger_json
214+
end
215+
end
201216
end
202217

203-
describe 'swagger file' do
204-
it do
205-
expect(json).to eql swagger_json
218+
describe 'specific resource documentation' do
219+
subject do
220+
get '/v3/swagger_doc/other_thing'
221+
JSON.parse(last_response.body)
222+
end
223+
224+
let(:tags) { subject['tags'] }
225+
specify do
226+
expect(tags).to eql [
227+
{
228+
'name' => 'other_thing',
229+
'description' => 'Operations about other_things'
230+
}
231+
]
206232
end
207233
end
208234
end

spec/swagger_v2/guarded_endpoint_spec.rb

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def app
8686
'swagger' => '2.0',
8787
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
8888
'host' => 'example.org',
89+
'tags' => [{ 'name' => 'auth', 'description' => 'Operations about auths' }],
8990
'paths' => {
9091
'/auth' => {
9192
'get' => {

spec/swagger_v2/namespace_tags_prefix_spec.rb

+2-8
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,7 @@ def app
5555
specify do
5656
expect(subject['tags']).to eql(
5757
[
58-
{ 'name' => 'hudson', 'description' => 'Operations about hudsons' },
59-
{ 'name' => 'colorado', 'description' => 'Operations about colorados' },
60-
{ 'name' => 'thames', 'description' => 'Operations about thames' },
61-
{ 'name' => 'niles', 'description' => 'Operations about niles' }
58+
{ 'name' => 'colorado', 'description' => 'Operations about colorados' }
6259
]
6360
)
6461

@@ -75,10 +72,7 @@ def app
7572
specify do
7673
expect(subject['tags']).to eql(
7774
[
78-
{ 'name' => 'hudson', 'description' => 'Operations about hudsons' },
79-
{ 'name' => 'colorado', 'description' => 'Operations about colorados' },
80-
{ 'name' => 'thames', 'description' => 'Operations about thames' },
81-
{ 'name' => 'niles', 'description' => 'Operations about niles' }
75+
{ 'name' => 'thames', 'description' => 'Operations about thames' }
8276
]
8377
)
8478

spec/swagger_v2/namespace_tags_spec.rb

+2-8
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,7 @@ def app
4848
specify do
4949
expect(subject['tags']).to eql(
5050
[
51-
{ 'name' => 'hudson', 'description' => 'Operations about hudsons' },
52-
{ 'name' => 'colorado', 'description' => 'Operations about colorados' },
53-
{ 'name' => 'thames', 'description' => 'Operations about thames' },
54-
{ 'name' => 'niles', 'description' => 'Operations about niles' }
51+
{ 'name' => 'colorado', 'description' => 'Operations about colorados' }
5552
]
5653
)
5754

@@ -68,10 +65,7 @@ def app
6865
specify do
6966
expect(subject['tags']).to eql(
7067
[
71-
{ 'name' => 'hudson', 'description' => 'Operations about hudsons' },
72-
{ 'name' => 'colorado', 'description' => 'Operations about colorados' },
73-
{ 'name' => 'thames', 'description' => 'Operations about thames' },
74-
{ 'name' => 'niles', 'description' => 'Operations about niles' }
68+
{ 'name' => 'thames', 'description' => 'Operations about thames' }
7569
]
7670
)
7771

spec/swagger_v2/simple_mounted_api_spec.rb

+2-14
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,7 @@ def app
193193
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
194194
'host' => 'example.org',
195195
'tags' => [
196-
{ 'name' => 'simple', 'description' => 'Operations about simples' },
197-
{ 'name' => 'simple-test', 'description' => 'Operations about simple-tests' },
198-
{ 'name' => 'simple-head-test', 'description' => 'Operations about simple-head-tests' },
199-
{ 'name' => 'simple-options-test', 'description' => 'Operations about simple-options-tests' },
200-
{ 'name' => 'simple_with_headers', 'description' => 'Operations about simple_with_headers' },
201-
{ 'name' => 'items', 'description' => 'Operations about items' },
202-
{ 'name' => 'custom', 'description' => 'Operations about customs' }
196+
{ 'name' => 'simple', 'description' => 'Operations about simples' }
203197
],
204198
'paths' => {
205199
'/simple' => {
@@ -231,13 +225,7 @@ def app
231225
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
232226
'host' => 'example.org',
233227
'tags' => [
234-
{ 'name' => 'simple', 'description' => 'Operations about simples' },
235-
{ 'name' => 'simple-test', 'description' => 'Operations about simple-tests' },
236-
{ 'name' => 'simple-head-test', 'description' => 'Operations about simple-head-tests' },
237-
{ 'name' => 'simple-options-test', 'description' => 'Operations about simple-options-tests' },
238-
{ 'name' => 'simple_with_headers', 'description' => 'Operations about simple_with_headers' },
239-
{ 'name' => 'items', 'description' => 'Operations about items' },
240-
{ 'name' => 'custom', 'description' => 'Operations about customs' }
228+
{ 'name' => 'simple-test', 'description' => 'Operations about simple-tests' }
241229
],
242230
'paths' => {
243231
'/simple-test' => {

0 commit comments

Comments
 (0)