Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#### Fixes

* [#1016](https://github.com/ruby-grape/grape-swagger/pull/1016): Hide the nested parameters of a Hash parameter marked `documentation: { hidden: true }`, and pass the resolved `token_owner` to parameter-level `hidden:` procs like route-level ones (raising `TokenOwnerNotFound` if the configured method is missing) - [@numbata](https://github.com/numbata).
* [#1013](https://github.com/ruby-grape/grape-swagger/pull/1013): Fix array `default` values being placed inside `items` instead of on the array parameter or property, and emit an empty array `default` - [@numbata](https://github.com/numbata).
* [#1012](https://github.com/ruby-grape/grape-swagger/pull/1012): Keep the Danger PR check running in CI by pinning `git` below 6 - [@numbata](https://github.com/numbata).
* [#1011](https://github.com/ruby-grape/grape-swagger/pull/1011): Preserve string length, array item and object property limits in body parameter definitions, and emit `minLength`/`maxLength` only for strings (`minProperties`/`maxProperties` for hashes) instead of any non-array type - [@numbata](https://github.com/numbata).
* [#1009](https://github.com/ruby-grape/grape-swagger/pull/1009): Bump the Danger `danger-comment.yml` workflow from 0.1.0 to 0.1.1 - [@dependabot[bot]](https://github.com/dependabot%5Bbot%5D).
Expand Down
1 change: 1 addition & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- **A blank `desc(..., tags:)` now means "not specified".** `tags: nil` no longer suppresses the tag and `tags: []` no longer emits an empty `"tags": []`; both derive the tag from the path, as if `tags:` had been omitted. `tags:` is an override, and only a non-empty list overrides anything.

The old `nil` behaviour was never a deliberate one: [#523](https://github.com/ruby-grape/grape-swagger/pull/523) introduced route-level tags to *override* path-derived grouping and read them with `route.options.fetch(:tags, tag_object(route))`, whose default-on-absence semantics happened to give `nil` a meaning of its own. It was never documented or tested.
- **An `Array` default on an array parameter is now documented on the array, not inside `items`.** `optional :ids, type: [String], default: %w[a b]` emits `default: ["a", "b"]` next to `type: array` (as a body property or a query/formData parameter) instead of `items.default`, which is not a valid place for a list. Consumers that read `items.default` for such a default must read the parameter/property `default` instead; scalar defaults on array parameters still land in `items.default`. An empty array default (`default: []`) is now emitted as well. See [#1013](https://github.com/ruby-grape/grape-swagger/pull/1013).

### Upgrading to >= 2.2.0

Expand Down
2 changes: 1 addition & 1 deletion lib/grape-swagger/doc_methods/move_params.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def property_keys
end

def array_schema_keys
%i[minItems maxItems]
%i[minItems maxItems default]
end

def deletable?(param)
Expand Down
7 changes: 6 additions & 1 deletion lib/grape-swagger/doc_methods/parse_params.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,12 @@ def parse_array_item(definitions, type, value_type)
enum_or_range_values = parse_enum_or_range_values(values)
array_items.merge!(enum_or_range_values) if enum_or_range_values

array_items[:default] = value_type[:default] if value_type[:default].present?
default = value_type[:default]
if default.is_a?(Array)
@parsed_param[:default] = default
elsif default.present?
array_items[:default] = default
end

set_additional_properties, additional_properties = parse_additional_properties(definitions, value_type)
array_items[:additionalProperties] = additional_properties if set_additional_properties
Expand Down
124 changes: 124 additions & 0 deletions spec/issues/950_array_default_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# frozen_string_literal: true

require 'spec_helper'

describe '#950 array default belongs to the array, not its items' do
let(:app) do
Class.new(Grape::API) do
params do
optional :dns_servers, type: [String], default: %w[8.8.8.8 8.8.4.4]
end
get '/query' do
{}
end

params do
optional :dns_servers, type: [String], default: %w[8.8.8.8 8.8.4.4]
end
post '/body' do
{}
end

params do
optional :dns_servers, type: [String], default: %w[8.8.8.8 8.8.4.4]
end
desc 'form', consumes: ['application/x-www-form-urlencoded']
post '/form' do
{}
end

params do
optional :dns_servers, type: [String], default: []
end
get '/empty' do
{}
end

params do
optional :dns_servers, type: [String], default: 'z'
end
get '/scalar' do
{}
end

params do
optional :dns_servers, type: [String], default: 'z'
end
post '/scalar_body' do
{}
end

params do
optional :things, type: [JSON], default: [{ 'a' => 1 }] do
optional :a, type: Integer
end
end
post '/json' do
{}
end

add_swagger_documentation
end
end

subject do
get '/swagger_doc'
JSON.parse(last_response.body)
end

it 'puts the default on the array for a query parameter' do
expect(subject['paths']['/query']['get']['parameters']).to eql(
[
{ 'in' => 'query', 'name' => 'dns_servers', 'type' => 'array', 'items' => { 'type' => 'string' },
'default' => %w[8.8.8.8 8.8.4.4], 'required' => false }
]
)
end

it 'puts the default on the array property of a body definition' do
expect(subject['definitions']['postBody']['properties']['dns_servers']).to eql(
'type' => 'array', 'items' => { 'type' => 'string' }, 'default' => %w[8.8.8.8 8.8.4.4]
)
end

it 'puts the default on the array for a formData parameter' do
expect(subject['paths']['/form']['post']['parameters']).to eql(
[
{ 'in' => 'formData', 'name' => 'dns_servers', 'type' => 'array', 'items' => { 'type' => 'string' },
'default' => %w[8.8.8.8 8.8.4.4], 'required' => false }
]
)
end

it 'emits an empty array default on the array' do
expect(subject['paths']['/empty']['get']['parameters']).to eql(
[
{ 'in' => 'query', 'name' => 'dns_servers', 'type' => 'array', 'items' => { 'type' => 'string' },
'default' => [], 'required' => false }
]
)
end

it 'keeps a scalar default of an array parameter in items' do
expect(subject['paths']['/scalar']['get']['parameters']).to eql(
[
{ 'in' => 'query', 'name' => 'dns_servers', 'type' => 'array',
'items' => { 'type' => 'string', 'default' => 'z' }, 'required' => false }
]
)
end

it 'keeps a scalar default of an array body property in items' do
expect(subject['definitions']['postScalarBody']['properties']['dns_servers']).to eql(
'type' => 'array', 'items' => { 'type' => 'string', 'default' => 'z' }
)
end

it 'puts the default of an array of nested objects on the array property' do
expect(subject['definitions']['postJson']['properties']['things']).to eql(
'type' => 'array',
'items' => { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'integer', 'format' => 'int32' } } },
'default' => [{ 'a' => 1 }]
)
end
end
Loading