diff --git a/CHANGELOG.md b/CHANGELOG.md index cb8288c9..53d79683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * [#126](https://github.com/tim-vandecasteele/grape-swagger/pull/126): Rewritten demo in the `test` folder with CORS enabled - [@dblock](https://github.com/dblock). * [#127](https://github.com/tim-vandecasteele/grape-swagger/pull/127): Fixed `undefined method 'reject' for nil:NilClass` error for an invalid route, now returning 404 Not Found - [@dblock](https://github.com/dblock). * [#128](https://github.com/tim-vandecasteele/grape-swagger/pull/128): Combine global models and endpoint entities - [@dspaeth-faber](https://github.com/dspaeth-faber). +* [#132](https://github.com/tim-vandecasteele/grape-swagger/pull/132): Addes support for enum values in entity documentation and form parameters - [@Antek-drzewiecki](https://github.com/Antek-drzewiecki). * Your Contribution Here ### 0.7.2 (February 6, 2014) diff --git a/README.md b/README.md index a2c095ac..abda14a0 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,7 @@ module API class Status < Grape::Entity expose :text, documentation: { type: 'string', desc: 'Status update text.' } expose :links, using: Link, documentation: { type: 'link', is_array: true } + expose :numbers, documentation: { type: 'integer', desc: 'favourite number', values: [1,2,3,4] } end class Link < Grape::Entity @@ -215,6 +216,11 @@ module API type = current_user.admin? ? :full : :default present statuses, with: API::Entities::Status, type: type end + + desc 'Creates a new status', entity: API::Entities::Status, params: API::Entities::Status.documentation + post '/statuses' do + ... + end end end ``` diff --git a/lib/grape-swagger.rb b/lib/grape-swagger.rb index bf064933..71fb26d2 100644 --- a/lib/grape-swagger.rb +++ b/lib/grape-swagger.rb @@ -240,6 +240,9 @@ def parse_params(params, path, method) required = value.is_a?(Hash) ? !!value[:required] : false default_value = value.is_a?(Hash) ? value[:default] : nil is_array = value.is_a?(Hash) ? (value[:is_array] || false) : false + enum_values = value.is_a?(Hash) ? value[:values] : nil + enum_values = enum_values.call if enum_values && enum_values.is_a?(Proc) + if value.is_a?(Hash) && value.key?(:param_type) param_type = value[:param_type] if is_array @@ -274,7 +277,7 @@ def parse_params(params, path, method) parsed_params.merge!(format: 'int64') if data_type == 'long' parsed_params.merge!(items: items) if items.present? parsed_params.merge!(defaultValue: default_value) if default_value - + parsed_params.merge!(enum: enum_values) if enum_values parsed_params end end @@ -373,7 +376,15 @@ def parse_entity_models(models) property_description = p.delete(:desc) p[:description] = property_description if property_description + # rename Grape's 'values' to 'enum' + select_values = p.delete(:values) + if select_values + select_values = select_values.call if select_values.is_a?(Proc) + p[:enum] = select_values + end + properties[property_name] = p + end result[name] = { diff --git a/spec/api_models_spec.rb b/spec/api_models_spec.rb index f3fca9d4..d59d32db 100644 --- a/spec/api_models_spec.rb +++ b/spec/api_models_spec.rb @@ -9,6 +9,13 @@ class Something < Grape::Entity end end + module Entities + class EnumValues < Grape::Entity + expose :gender, documentation: { type: 'string', desc: 'Content of something.', values: %w(Male Female) } + expose :number, documentation: { type: 'integer', desc: 'Content of something.', values: proc { [1, 2] } } + end + end + module Entities module Some class Thing < Grape::Entity @@ -64,6 +71,14 @@ def app present thing, with: Entities::SomeThingElse end + desc 'This tests the enum values in params and documentation.', entity: Entities::EnumValues, params: Entities::EnumValues.documentation + get '/enum_description_in_entity' do + + enum_value = OpenStruct.new gender: 'Male', number: 1 + + present enum_value, with: Entities::EnumValues + end + add_swagger_documentation end end @@ -88,6 +103,7 @@ def app { 'path' => '/something.{format}', 'description' => 'Operations about somethings' }, { 'path' => '/thing.{format}', 'description' => 'Operations about things' }, { 'path' => '/somethingelse.{format}', 'description' => 'Operations about somethingelses' }, + { 'path' => '/enum_description_in_entity.{format}', 'description' => 'Operations about enum_description_in_entities' }, { 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' } ] end @@ -157,4 +173,26 @@ def app } ) end + + it 'includes enum values in params and documentation.' do + get '/swagger_doc/enum_description_in_entity.json' + result = JSON.parse(last_response.body) + expect(result['models']['EnumValues']).to eq( + 'id' => 'EnumValues', + 'properties' => { + 'gender' => { 'type' => 'string', 'description' => 'Content of something.', 'enum' => %w(Male Female) }, + 'number' => { 'type' => 'integer', 'description' => 'Content of something.', 'enum' => [1, 2] } + } + ) + + expect(result['apis'][0]['operations'][0]).to include( + 'parameters' => + [ + { 'paramType' => 'query', 'name' => 'gender', 'description' => 'Content of something.', 'type' => 'string', 'required' => false, 'allowMultiple' => false, 'enum' => %w(Male Female) }, + { 'paramType' => 'query', 'name' => 'number', 'description' => 'Content of something.', 'type' => 'integer', 'required' => false, 'allowMultiple' => false, 'format' => 'int32', 'enum' => [1, 2] } + ], + 'type' => 'EnumValues' + ) + + end end diff --git a/spec/form_params_spec.rb b/spec/form_params_spec.rb index 33862d2f..a0bd6db4 100644 --- a/spec/form_params_spec.rb +++ b/spec/form_params_spec.rb @@ -15,6 +15,7 @@ def app params do requires :id, type: Integer, desc: 'id of item' requires :name, type: String, desc: 'name of item' + requires :conditions, type: Integer, desc: 'conditions of item', values: [1, 2, 3] end put '/items/:id' do {} @@ -23,6 +24,7 @@ def app params do requires :id, type: Integer, desc: 'id of item' requires :name, type: String, desc: 'name of item' + optional :conditions, type: String, desc: 'conditions of item', values: proc { %w(1 2) } end patch '/items/:id' do {} @@ -38,6 +40,7 @@ def app end it 'retrieves the documentation form params' do + puts subject['apis'] expect(subject['apis']).to eq([ { 'path' => '/items.{format}', @@ -59,7 +62,11 @@ def app 'summary' => '', 'nickname' => 'PUT-items--id---format-', 'method' => 'PUT', - 'parameters' => [{ 'paramType' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' }, { 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false }], + 'parameters' => [ + { 'paramType' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' }, + { 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false }, + { 'paramType' => 'form', 'name' => 'conditions', 'description' => 'conditions of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32', 'enum' => [1, 2, 3] } + ], 'type' => 'void' }, { @@ -67,7 +74,11 @@ def app 'summary' => '', 'nickname' => 'PATCH-items--id---format-', 'method' => 'PATCH', - 'parameters' => [{ 'paramType' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' }, { 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false }], + 'parameters' => [ + { 'paramType' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' }, + { 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false }, + { 'paramType' => 'form', 'name' => 'conditions', 'description' => 'conditions of item', 'type' => 'string', 'required' => false, 'allowMultiple' => false, 'enum' => %w(1 2) } + ], 'type' => 'void' } ]