Response model can have required attributes (#521)

* Response model can have required attributes

* Reorganize implementation

* Fix RuboCop offences

* Last touch of refactor
This commit is contained in:
Wojciech Korzeniowski 2016-10-14 11:56:33 +02:00 committed by peter scholz
parent d7b7465a95
commit 7061fd1b75
7 changed files with 47 additions and 3 deletions

View File

@ -2,6 +2,7 @@
#### Features
* [#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).
* Your contribution here.

View File

@ -849,14 +849,14 @@ route_setting :x_def, [{ for: 422, other: 'stuff' }, { for: 200, some: 'stuff' }
Add the [grape-entity](https://github.com/ruby-grape/grape-entity) and [grape-swagger-entity](https://github.com/ruby-grape/grape-swagger-entity) gem to your Gemfile.
The following example exposes statuses. And exposes statuses documentation adding :type and :desc.
The following example exposes statuses. And exposes statuses documentation adding :type, :desc and :required.
The documented class/definition name could be set via `#entity_name`.
```ruby
module API
module Entities
class Status < Grape::Entity
expose :text, documentation: { type: 'string', desc: 'Status update text.' }
expose :text, documentation: { type: 'string', desc: 'Status update text.', required: true }
expose :links, using: Link, documentation: { type: 'link', is_array: true }
expose :numbers, documentation: { type: 'integer', desc: 'favourite number', values: [1,2,3,4] }
end

View File

@ -10,6 +10,7 @@ require 'grape-swagger/doc_methods/tag_name_description'
require 'grape-swagger/doc_methods/parse_params'
require 'grape-swagger/doc_methods/move_params'
require 'grape-swagger/doc_methods/headers'
require 'grape-swagger/doc_methods/build_model_definition'
module GrapeSwagger
module DocMethods

View File

@ -0,0 +1,38 @@
module GrapeSwagger
module DocMethods
class BuildModelDefinition
class << self
def build(model, properties)
definition = { type: 'object', properties: properties }
required = required_attributes(model)
definition[:required] = required unless required.blank?
definition
end
private
def required_attributes(model)
parse_entity(model) || parse_representable(model)
end
def parse_entity(model)
return unless model.respond_to?(:documentation)
model.documentation
.select { |_name, options| options[:required] }
.map { |name, options| options[:as] || name }
end
def parse_representable(model)
return unless model.respond_to?(:map)
model.map
.select { |p| p[:documentation] && p[:documentation][:required] }
.map(&:name)
end
end
end
end
end

View File

@ -291,7 +291,7 @@ module Grape
properties = parser.new(model, self).call
raise GrapeSwagger::Errors::SwaggerSpec, "Empty model #{model_name}, swagger 2.0 doesn't support empty definitions." unless properties && properties.any?
@definitions[model_name] = { type: 'object', properties: properties }
@definitions[model_name] = GrapeSwagger::DocMethods::BuildModelDefinition.build(model, properties)
model_name
end

View File

@ -304,11 +304,13 @@ RSpec.shared_context 'entity swagger example' do
'definitions' => {
'QueryInput' => {
'type' => 'object',
'required' => ['elements'],
'properties' => { 'elements' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/QueryInputElement' }, 'description' => 'Set of configuration' } },
'description' => 'nested route inside namespace'
},
'QueryInputElement' => {
'type' => 'object',
'required' => %w(key value),
'properties' => { 'key' => { 'type' => 'string', 'description' => 'Name of parameter' }, 'value' => { 'type' => 'string', 'description' => 'Value of parameter' } }
},
'ApiError' => {

View File

@ -376,11 +376,13 @@ RSpec.shared_context 'representable swagger example' do
'definitions' => {
'QueryInput' => {
'type' => 'object',
'required' => ['elements'],
'properties' => { 'elements' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/QueryInputElement' }, 'description' => 'Set of configuration' } },
'description' => 'nested route inside namespace'
},
'QueryInputElement' => {
'type' => 'object',
'required' => %w(key value),
'properties' => { 'key' => { 'type' => 'string', 'description' => 'Name of parameter' }, 'value' => { 'type' => 'string', 'description' => 'Value of parameter' } }
},
'ApiError' => {