use route tags for global tag set (#524)
* minor adoptions on README * build global tag set from route tags - adds changelog entry - adds note in UPGRADING
This commit is contained in:
parent
14364e3c65
commit
7d405ff714
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
#### Features
|
||||
|
||||
* [#524](https://github.com/ruby-grape/grape-swagger/pull/524): Use route tags for global tag set - [@LeFnord](https://github.com/LeFnord).
|
||||
* [#523](https://github.com/ruby-grape/grape-swagger/pull/523): Allow specifying custom tags at the route level - [@jordanfbrown](https://github.com/jordanfbrown).
|
||||
* [#520](https://github.com/ruby-grape/grape-swagger/pull/520): Response model can have required attributes - [@WojciechKo](https://github.com/WojciechKo).
|
||||
* [#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).
|
||||
* [#523](https://github.com/ruby-grape/grape-swagger/pull/523): Allow specifying custom tags at the route level. - [@jordanfbrown](https://github.com/jordanfbrown).
|
||||
* Your contribution here.
|
||||
|
||||
#### Fixes
|
||||
|
|
|
|||
24
README.md
24
README.md
|
|
@ -394,10 +394,10 @@ add_swagger_documentation \
|
|||
* [Overriding the tags](#tags)
|
||||
* [Defining an endpoint as an array](#array)
|
||||
* [Using an options hash](#options)
|
||||
* [Overriding param type](#overriding-param-type)
|
||||
* [Overriding param types](#overriding-param-types)
|
||||
* [Multiple param types](#multiple-types)
|
||||
* [Array type](#array-type)
|
||||
* [Overriding parameter type](#overriding-param-type)
|
||||
* [Overriding data type of the parameter](#overriding-type-of-param)
|
||||
* [Multiple types](#multiple-types)
|
||||
* [Array of data type](#array-type)
|
||||
* [Collection Format](#collection-format)
|
||||
* [Hiding parameters](#hiding-parameters)
|
||||
* [Setting a Swagger default value](#default-value)
|
||||
|
|
@ -530,9 +530,9 @@ get '/kittens' do
|
|||
|
||||
|
||||
<a name="overriding-param-type" />
|
||||
#### Overriding param type
|
||||
#### Overriding parameter type
|
||||
|
||||
You can override paramType in POST|PUT methods to query, using the documentation hash.
|
||||
You can override paramType, using the documentation hash. See [parameter object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#parameter-object) for available types.
|
||||
|
||||
```ruby
|
||||
params do
|
||||
|
|
@ -543,8 +543,9 @@ post :act do
|
|||
end
|
||||
```
|
||||
|
||||
<a name="overriding-param-types" />
|
||||
#### Overriding param types
|
||||
|
||||
<a name="overriding-type-of-param" />
|
||||
#### Overriding data type of the parameter
|
||||
|
||||
You can override type, using the documentation hash.
|
||||
|
||||
|
|
@ -569,9 +570,9 @@ end
|
|||
|
||||
|
||||
<a name="multiple-types" />
|
||||
#### Multi types
|
||||
#### Multiple types
|
||||
|
||||
By default when you set multi types, the first type is selected as swagger type
|
||||
By default when you set multiple types, the first type is selected as swagger type
|
||||
|
||||
```ruby
|
||||
params do
|
||||
|
|
@ -591,8 +592,9 @@ end
|
|||
}
|
||||
```
|
||||
|
||||
|
||||
<a name="array-type" />
|
||||
#### Array type
|
||||
#### Array of data type
|
||||
|
||||
Array types are also supported.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
Upgrading Grape-swagger
|
||||
=======================
|
||||
|
||||
### Upgrading to >= 0.25.0
|
||||
|
||||
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.
|
||||
|
||||
### Upgrading to >= 0.21.0
|
||||
|
||||
With grape >= 0.21.0, `grape-entity` support moved to separate gem `grape-swagger-entity`, if you use grape entity, update your Gemfile:
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@ module GrapeSwagger
|
|||
options
|
||||
)
|
||||
|
||||
paths, definitions = endpoint.path_and_definition_objects(combi_routes, options)
|
||||
paths, definitions = endpoint.path_and_definition_objects(combi_routes, options)
|
||||
tags = GrapeSwagger::DocMethods::TagNameDescription.build(paths)
|
||||
output[:tags] = tags unless tags.empty? || paths.blank?
|
||||
output[:paths] = paths unless paths.blank?
|
||||
output[:definitions] = definitions unless definitions.blank?
|
||||
|
||||
|
|
|
|||
|
|
@ -2,23 +2,15 @@ module GrapeSwagger
|
|||
module DocMethods
|
||||
class TagNameDescription
|
||||
class << self
|
||||
def build(options = {})
|
||||
target_class = options[:target_class]
|
||||
namespaces = target_class.combined_namespaces
|
||||
namespace_routes = target_class.combined_namespace_routes
|
||||
|
||||
namespace_routes.keys.map do |local_route|
|
||||
next if namespace_routes[local_route].map { |route| route.options[:hidden] }.all? { |value| value.respond_to?(:call) ? value.call : value }
|
||||
|
||||
original_namespace_name = target_class.combined_namespace_identifiers.key?(local_route) ? target_class.combined_namespace_identifiers[local_route] : local_route
|
||||
description = namespaces[original_namespace_name] && namespaces[original_namespace_name].options[:desc]
|
||||
description ||= "Operations about #{original_namespace_name.pluralize}"
|
||||
|
||||
{
|
||||
name: local_route,
|
||||
description: description
|
||||
}
|
||||
end.compact
|
||||
def build(paths)
|
||||
paths.values.each_with_object([]) do |path, memo|
|
||||
path.values.first[:tags].each do |tag|
|
||||
memo << {
|
||||
name: tag,
|
||||
description: "Operations about #{tag.pluralize}"
|
||||
}
|
||||
end
|
||||
end.uniq
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ module Grape
|
|||
securityDefinitions: options[:security_definitions],
|
||||
host: GrapeSwagger::DocMethods::OptionalObject.build(:host, options, request),
|
||||
basePath: GrapeSwagger::DocMethods::OptionalObject.build(:base_path, options, request),
|
||||
tags: GrapeSwagger::DocMethods::TagNameDescription.build(options),
|
||||
schemes: options[:schemes].is_a?(String) ? [options[:schemes]] : options[:schemes]
|
||||
}.delete_if { |_, value| value.blank? }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -118,91 +118,117 @@ describe 'swagger spec v2.0' do
|
|||
end
|
||||
end
|
||||
|
||||
before do
|
||||
get '/v3/swagger_doc'
|
||||
end
|
||||
|
||||
let(:json) { JSON.parse(last_response.body) }
|
||||
|
||||
describe 'swagger object' do
|
||||
describe 'required keys' do
|
||||
it { expect(json.keys).to include 'swagger' }
|
||||
it { expect(json['swagger']).to eql '2.0' }
|
||||
it { expect(json.keys).to include 'info' }
|
||||
it { expect(json['info']).to be_a Hash }
|
||||
it { expect(json.keys).to include 'paths' }
|
||||
it { expect(json['paths']).to be_a Hash }
|
||||
describe 'whole documentation' do
|
||||
subject do
|
||||
get '/v3/swagger_doc'
|
||||
JSON.parse(last_response.body)
|
||||
end
|
||||
|
||||
describe 'info object required keys' do
|
||||
let(:info) { json['info'] }
|
||||
|
||||
it { expect(info.keys).to include 'title' }
|
||||
it { expect(info['title']).to be_a String }
|
||||
it { expect(info.keys).to include 'version' }
|
||||
it { expect(info['version']).to be_a String }
|
||||
|
||||
describe 'license object' do
|
||||
let(:license) { json['info']['license'] }
|
||||
|
||||
it { expect(license.keys).to include 'name' }
|
||||
it { expect(license['name']).to be_a String }
|
||||
it { expect(license.keys).to include 'url' }
|
||||
it { expect(license['url']).to be_a String }
|
||||
describe 'swagger object' do
|
||||
describe 'required keys' do
|
||||
it { expect(subject.keys).to include 'swagger' }
|
||||
it { expect(subject['swagger']).to eql '2.0' }
|
||||
it { expect(subject.keys).to include 'info' }
|
||||
it { expect(subject['info']).to be_a Hash }
|
||||
it { expect(subject.keys).to include 'paths' }
|
||||
it { expect(subject['paths']).to be_a Hash }
|
||||
end
|
||||
|
||||
describe 'contact object' do
|
||||
let(:contact) { json['info']['contact'] }
|
||||
describe 'info object required keys' do
|
||||
let(:info) { subject['info'] }
|
||||
|
||||
it { expect(contact.keys).to include 'name' }
|
||||
it { expect(contact['name']).to be_a String }
|
||||
it { expect(contact.keys).to include 'email' }
|
||||
it { expect(contact['email']).to be_a String }
|
||||
it { expect(contact.keys).to include 'url' }
|
||||
it { expect(contact['url']).to be_a String }
|
||||
end
|
||||
end
|
||||
it { expect(info.keys).to include 'title' }
|
||||
it { expect(info['title']).to be_a String }
|
||||
it { expect(info.keys).to include 'version' }
|
||||
it { expect(info['version']).to be_a String }
|
||||
|
||||
describe 'path object' do
|
||||
let(:paths) { json['paths'] }
|
||||
describe 'license object' do
|
||||
let(:license) { subject['info']['license'] }
|
||||
|
||||
it 'hides documentation paths per default' do
|
||||
expect(paths.keys).not_to include '/swagger_doc', '/swagger_doc/{name}'
|
||||
it { expect(license.keys).to include 'name' }
|
||||
it { expect(license['name']).to be_a String }
|
||||
it { expect(license.keys).to include 'url' }
|
||||
it { expect(license['url']).to be_a String }
|
||||
end
|
||||
|
||||
describe 'contact object' do
|
||||
let(:contact) { subject['info']['contact'] }
|
||||
|
||||
it { expect(contact.keys).to include 'name' }
|
||||
it { expect(contact['name']).to be_a String }
|
||||
it { expect(contact.keys).to include 'email' }
|
||||
it { expect(contact['email']).to be_a String }
|
||||
it { expect(contact.keys).to include 'url' }
|
||||
it { expect(contact['url']).to be_a String }
|
||||
end
|
||||
|
||||
describe 'global tags' do
|
||||
let(:tags) { subject['tags'] }
|
||||
|
||||
it { expect(tags).to be_a Array }
|
||||
it { expect(tags).not_to be_empty }
|
||||
end
|
||||
end
|
||||
|
||||
specify do
|
||||
paths.each_pair do |path, value|
|
||||
expect(path).to start_with('/')
|
||||
expect(value).to be_a Hash
|
||||
expect(value).not_to be_empty
|
||||
describe 'path object' do
|
||||
let(:paths) { subject['paths'] }
|
||||
|
||||
value.each do |method, declaration|
|
||||
expect(http_verbs).to include method
|
||||
expect(declaration).to have_key('responses')
|
||||
it 'hides documentation paths per default' do
|
||||
expect(paths.keys).not_to include '/swagger_doc', '/swagger_doc/{name}'
|
||||
end
|
||||
|
||||
declaration['responses'].each do |status_code, response|
|
||||
expect(status_code).to match(/\d{3}/)
|
||||
expect(response).to have_key('description')
|
||||
specify do
|
||||
paths.each_pair do |path, value|
|
||||
expect(path).to start_with('/')
|
||||
expect(value).to be_a Hash
|
||||
expect(value).not_to be_empty
|
||||
|
||||
value.each do |method, declaration|
|
||||
expect(http_verbs).to include method
|
||||
expect(declaration).to have_key('responses')
|
||||
|
||||
declaration['responses'].each do |status_code, response|
|
||||
expect(status_code).to match(/\d{3}/)
|
||||
expect(response).to have_key('description')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'definitions object' do
|
||||
let(:definitions) { subject['definitions'] }
|
||||
|
||||
specify do
|
||||
definitions.each do |model, properties|
|
||||
expect(model).to match(/\w+/)
|
||||
expect(properties).to have_key('properties')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'definitions object' do
|
||||
let(:definitions) { json['definitions'] }
|
||||
specify do
|
||||
definitions.each do |model, properties|
|
||||
expect(model).to match(/\w+/)
|
||||
expect(properties).to have_key('properties')
|
||||
end
|
||||
describe 'swagger file' do
|
||||
it do
|
||||
expect(subject).to eql swagger_json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'swagger file' do
|
||||
it do
|
||||
expect(json).to eql swagger_json
|
||||
describe 'specific resource documentation' do
|
||||
subject do
|
||||
get '/v3/swagger_doc/other_thing'
|
||||
JSON.parse(last_response.body)
|
||||
end
|
||||
|
||||
let(:tags) { subject['tags'] }
|
||||
specify do
|
||||
expect(tags).to eql [
|
||||
{
|
||||
'name' => 'other_thing',
|
||||
'description' => 'Operations about other_things'
|
||||
}
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ describe 'a guarded api endpoint' do
|
|||
'swagger' => '2.0',
|
||||
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
|
||||
'host' => 'example.org',
|
||||
'tags' => [{ 'name' => 'auth', 'description' => 'Operations about auths' }],
|
||||
'paths' => {
|
||||
'/auth' => {
|
||||
'get' => {
|
||||
|
|
|
|||
|
|
@ -55,10 +55,7 @@ describe 'namespace tags check while using prefix and version' do
|
|||
specify do
|
||||
expect(subject['tags']).to eql(
|
||||
[
|
||||
{ 'name' => 'hudson', 'description' => 'Operations about hudsons' },
|
||||
{ 'name' => 'colorado', 'description' => 'Operations about colorados' },
|
||||
{ 'name' => 'thames', 'description' => 'Operations about thames' },
|
||||
{ 'name' => 'niles', 'description' => 'Operations about niles' }
|
||||
{ 'name' => 'colorado', 'description' => 'Operations about colorados' }
|
||||
]
|
||||
)
|
||||
|
||||
|
|
@ -75,10 +72,7 @@ describe 'namespace tags check while using prefix and version' do
|
|||
specify do
|
||||
expect(subject['tags']).to eql(
|
||||
[
|
||||
{ 'name' => 'hudson', 'description' => 'Operations about hudsons' },
|
||||
{ 'name' => 'colorado', 'description' => 'Operations about colorados' },
|
||||
{ 'name' => 'thames', 'description' => 'Operations about thames' },
|
||||
{ 'name' => 'niles', 'description' => 'Operations about niles' }
|
||||
{ 'name' => 'thames', 'description' => 'Operations about thames' }
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -48,10 +48,7 @@ describe 'namespace tags check' do
|
|||
specify do
|
||||
expect(subject['tags']).to eql(
|
||||
[
|
||||
{ 'name' => 'hudson', 'description' => 'Operations about hudsons' },
|
||||
{ 'name' => 'colorado', 'description' => 'Operations about colorados' },
|
||||
{ 'name' => 'thames', 'description' => 'Operations about thames' },
|
||||
{ 'name' => 'niles', 'description' => 'Operations about niles' }
|
||||
{ 'name' => 'colorado', 'description' => 'Operations about colorados' }
|
||||
]
|
||||
)
|
||||
|
||||
|
|
@ -68,10 +65,7 @@ describe 'namespace tags check' do
|
|||
specify do
|
||||
expect(subject['tags']).to eql(
|
||||
[
|
||||
{ 'name' => 'hudson', 'description' => 'Operations about hudsons' },
|
||||
{ 'name' => 'colorado', 'description' => 'Operations about colorados' },
|
||||
{ 'name' => 'thames', 'description' => 'Operations about thames' },
|
||||
{ 'name' => 'niles', 'description' => 'Operations about niles' }
|
||||
{ 'name' => 'thames', 'description' => 'Operations about thames' }
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -193,13 +193,7 @@ describe 'a simple mounted api' do
|
|||
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
|
||||
'host' => 'example.org',
|
||||
'tags' => [
|
||||
{ 'name' => 'simple', 'description' => 'Operations about simples' },
|
||||
{ 'name' => 'simple-test', 'description' => 'Operations about simple-tests' },
|
||||
{ 'name' => 'simple-head-test', 'description' => 'Operations about simple-head-tests' },
|
||||
{ 'name' => 'simple-options-test', 'description' => 'Operations about simple-options-tests' },
|
||||
{ 'name' => 'simple_with_headers', 'description' => 'Operations about simple_with_headers' },
|
||||
{ 'name' => 'items', 'description' => 'Operations about items' },
|
||||
{ 'name' => 'custom', 'description' => 'Operations about customs' }
|
||||
{ 'name' => 'simple', 'description' => 'Operations about simples' }
|
||||
],
|
||||
'paths' => {
|
||||
'/simple' => {
|
||||
|
|
@ -231,13 +225,7 @@ describe 'a simple mounted api' do
|
|||
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
|
||||
'host' => 'example.org',
|
||||
'tags' => [
|
||||
{ 'name' => 'simple', 'description' => 'Operations about simples' },
|
||||
{ 'name' => 'simple-test', 'description' => 'Operations about simple-tests' },
|
||||
{ 'name' => 'simple-head-test', 'description' => 'Operations about simple-head-tests' },
|
||||
{ 'name' => 'simple-options-test', 'description' => 'Operations about simple-options-tests' },
|
||||
{ 'name' => 'simple_with_headers', 'description' => 'Operations about simple_with_headers' },
|
||||
{ 'name' => 'items', 'description' => 'Operations about items' },
|
||||
{ 'name' => 'custom', 'description' => 'Operations about customs' }
|
||||
{ 'name' => 'simple-test', 'description' => 'Operations about simple-tests' }
|
||||
],
|
||||
'paths' => {
|
||||
'/simple-test' => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue