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 @@ -6,6 +6,7 @@

#### Fixes

* [#986](https://github.com/ruby-grape/grape-swagger/pull/986): Read a route's tags through `route.tags` instead of `route.options`; a blank `tags:` (`nil` or `[]`) now means "not specified" and derives the tag from the path. See [UPGRADING](UPGRADING.md) - [@ericproulx](https://github.com/ericproulx).
* Your contribution here.

### 2.2.0 (2026-08-06)
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,8 @@ end
Tags are used for logical grouping of operations by resources or any other qualifier. To override the
tags array, add `tags: ['tag1', 'tag2']` after the description.

When `tags:` is not given, or is `nil` or empty, the tag is derived from the path.

```ruby
namespace 'order' do
desc 'This will be your summary', tags: ['orders']
Expand Down
6 changes: 6 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## Upgrading Grape-swagger

### Upgrading to >= 2.3.0

- **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.

### Upgrading to >= 2.2.0

- **Minimum Grape version is now `>= 2.1`** (was `>= 1.7`). Grape 1.8.0 and 2.0.0 cannot be used on Ruby 3.3+ because of an upstream Mustermann/forwardable incompatibility; the CI rows for those combinations were already failing on `master` and have been removed.
Expand Down
2 changes: 1 addition & 1 deletion lib/grape-swagger/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def method_object(route, options, path)
method[:parameters] = params_object(route, options, path, method[:consumes])
method[:security] = security_object(route)
method[:responses] = response_object(route, options)
method[:tags] = route.options.key?(:tags) ? route.tags : tag_object(route, path)
method[:tags] = route.tags.presence || tag_object(route, path)
method[:operationId] = GrapeSwagger::DocMethods::OperationId.build(route, path)
method[:deprecated] = deprecated_object(route)
method.delete_if { |_, value| value.nil? }
Expand Down
21 changes: 19 additions & 2 deletions spec/swagger_v2/endpoint_versioned_path_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,25 @@
end
end

it 'omits the tags key instead of falling back to the default tag' do
expect(subject.first['/v1/item'][:get]).not_to have_key(:tags)
it 'falls back to the default tag' do
expect(subject.first['/v1/item'][:get][:tags]).to eq ['item']
end
end

context 'when tags are explicitly empty' do
let(:item) do
Class.new(Grape::API) do
version 'v1', using: :path

resource :item do
desc 'Item description', tags: []
get '/'
end
end
end

it 'falls back to the default tag' do
expect(subject.first['/v1/item'][:get][:tags]).to eq ['item']
end
end

Expand Down
Loading