Fix Grape 3.2+ compatibility: desc kwargs, custom types, multi-type param recovery#978
Open
numbata wants to merge 11 commits into
Open
Fix Grape 3.2+ compatibility: desc kwargs, custom types, multi-type param recovery#978numbata wants to merge 11 commits into
numbata wants to merge 11 commits into
Conversation
Danger ReportNo issues found. |
dblock
approved these changes
May 18, 2026
Contributor
Author
|
@dblock FYI, I’ll jump back into this and the other PRs in the my grape-review queue later today. It looks like we have everything we need to release the new minor version of the gem. |
Member
|
CI does need to be fixed |
Member
|
Since this breaks backwards compat, needs a version bump and an UPGRADING note. Check compatibility in README, too. |
moskvin
approved these changes
May 29, 2026
Contributor
Author
numbata
added a commit
that referenced
this pull request
May 31, 2026
Per maintainer feedback on PR #978, this release carries breaking changes (Grape floor bump, `type: 'Object'` migration, custom-type `parse` requirement) and therefore lands as 2.2.0, with a matching UPGRADING entry and README compatibility-matrix row. Docs - README: add a `>= 2.2.0` compatibility row and cap the prior row at `< 2.2.0`. Document the new `:description` alias / string-keyed `api_documentation` affordance and the `:desc` precedence rule. - UPGRADING: new "Upgrading to >= 2.2.0" section covering all three user-facing breaking changes (Grape floor, `type: 'Object'`, custom types needing `.parse`). - CHANGELOG: split bullets into Breaking changes / Features / Fixes with accurate wording. Drop the misleading "matching the pre-keyword -args behaviour" framing — `:description` and string keys are new affordances. Add the custom-type `parse` requirement. Note that the variant-type recovery is a no-op on Grape < 3.3. Code - `pop_desc` is now private; it was an internal helper to `setup` but was leaking onto every `Grape::API` that mixed in `DocMethods`. - `route.rb`: `flatten(1)` instead of unbounded `.flatten`, and skip the merge when the recovered coercer `@types` is empty so we don't overwrite the legacy serialisation with `[]`. Tests - Add regression coverage for the parts of `pop_desc` that the v2 fix was actually for: explicit `desc: nil` must not fall through to `:description`, and `specific_api_documentation: { description: ... }` goes through the second `pop_desc` call site too. Public-API audit: `@converter` / `@types` (on VariantCollectionCoercer) and `@scope` (on Validators::Base) have no public reader on the supported Grape range (`scope` is private on HEAD and absent on 3.2.1), so the `instance_variable_get` reaches remain — there is no stable public alternative across the matrix.
728e002 to
a605502
Compare
a605502 to
2c2bbe0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR brings grape-swagger into full compatibility with Grape 3.2 and beyond. It fixes two breaking changes introduced in Grape 3.2+ — the
desckeyword-argument deprecation (which raises whenGrape.deprecator.behavior = :raise) and the rejection of string type names and non-.parsecustom types inparamsblocks — and adds recovery oftype: [A, B]multi-type params, which Grape 3.2+ was serialising as a raw coercer string in swagger output instead of the declared type. The minimum Grape dependency is bumped to>= 2.1(Grape 1.8 and 2.0 were already failing on Ruby 3.3+ due to an upstream Mustermann incompatibility), and the upper bound is expanded to< 5.0to support Grape 4.x.Changes
lib/grape-swagger/doc_methods.rbdesccalls so Grape's deprecator does not fire (or raise whenbehavior = :raise).api_documentation/specific_api_documentationhashes (e.g. loaded from YAML/JSON) viatransform_keys(&:to_sym).:descriptionas an alias for:desc; explicitdesc: nilwins and does not fall through.lib/grape-swagger/request_param_parsers/route.rbcollect_variant_types+extract_variant_validator_parts+restore_variant_typeto recover the actual type list fromVariantCollectionCoercerwhen Grape serialisestype: [A, B]via#to_s. Grape 3.2+ stores validator metadata as Hash entries; older supported versions useCoerceValidatorobject instances — both shapes are handled.spec/support/model_parsers/mock_parser.rbandrepresentable_parser.rbdef self.parse(val) = valtoNestedModule::ApiResponse. Grape 3.2+ requires unknown types to satisfyTypes.custom?(respond to.parsewith arity 1);Grape::Entityalready provides it soentity_parser.rbneeds no change.spec/swagger_v2/params_example_spec.rbtype: 'Object'from the Grapeparamsdeclaration intodocumentation: { type: 'Object' }. Grape 3.2+ rejects string type names in params blocks; grape-swagger picks the type from the merged settings hash so swagger output is unchanged.grape-swagger.gemspec>= 2.1(was>= 1.7); expand upper bound to< 5.0(was< 4.0) to support Grape 4.x HEAD..github/workflows/ci.ymlruby: '3.1', grape: '3.2.1'(Grape 3.2.1 requires Ruby >= 3.2)..rubocop.ymlStyle/OneClassPerFile—lib/grape-swagger.rbdefinesSwaggerRoutingandSwaggerDocumentationAdderas separate top-level modules; moving them into theGrapeSwaggernamespace would be a breaking change and will ship separately.Gemfilemulti_jsonexplicitly — required transitively byrepresentablebut not bundled on Ruby HEAD.Validation
Tested against Grape 2.1.3, 2.2.0, 3.2.1, and HEAD.
Closes #977