Skip to content

Commit

Permalink
Fix reference creation when two types are provided (#756)
Browse files Browse the repository at this point in the history
Previously the type from param definition would be used to documentation
even if we try to override it in the `documentation` hash.
It caused Swagger UI to render, for example, "Unknown Type: Color"
instead of using the provided entity.

It terms of code, before this change we would return something like this:
{ color: { type: 'Color' }
instead of:
{ color: { '$ref' => 'ColorEntity' }
if Color is not inherited from Grape::Entity

Having different types can be useful when two different classes
are used for parsing and presenting an attribute.
E.g. the input format for Base64 File can be represented as a Hash (content,
content_type and filename), whereas the type after parsing can be
ActionDispatch::Http::UploadedFile.

In the current situation the solution to this problem is to put coercion
methods to the same entity and specify `type` only for the param without
using `documentation`.
  • Loading branch information
bikolya authored and LeFnord committed Sep 5, 2019
1 parent 445d2d4 commit 204ced4
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#### Fixes

* Your contribution here.
* [#756](https://github.com/ruby-grape/grape-swagger/pull/756): Fix reference creation when custom type for documentation is provided - [@bikolya](https://github.com/bikolya).

### 0.33.0 (June 21, 2019)

Expand Down
6 changes: 3 additions & 3 deletions lib/grape-swagger/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,10 @@ def params_object(route, options, path)
parameters = partition_params(route, options).map do |param, value|
value = { required: false }.merge(value) if value.is_a?(Hash)
_, value = default_type([[param, value]]).first if value == ''
if value[:type]
expose_params(value[:type])
elsif value[:documentation]
if value.dig(:documentation, :type)
expose_params(value[:documentation][:type])
elsif value[:type]
expose_params(value[:type])
end
GrapeSwagger::DocMethods::ParseParams.call(param, value, path, route, @definitions)
end
Expand Down
33 changes: 33 additions & 0 deletions spec/swagger_v2/endpoint_versioned_path_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,39 @@
expect(subject.first['/v1/item'][:get][:tags]).to eq ['special-item']
end
end

context 'when parameter with a custom type is specified' do
let(:item) do
Class.new(Grape::API) do
Color = Struct.new(:value) do
def self.parse(value)
new(value: value)
end
end

class ColorEntity < Grape::Entity
expose :value
end

version 'v1', using: :path

resource :item do
params do
requires :root, type: Hash do
optional :color, type: Color, documentation: { type: ColorEntity }
end
end
post '/'
end
end
end

it 'creates a reference to the model instead of using the non-existent type' do
color = subject.dig(1, 'postV1Item', :properties, :root, :properties, :color)
expect(color).not_to eq(type: 'ColorEntity')
expect(color).to eq('$ref' => '#/definitions/ColorEntity')
end
end
end

context 'when mounting an API more than once', if: GrapeVersion.satisfy?('>= 1.2.0') do
Expand Down

0 comments on commit 204ced4

Please sign in to comment.