Preserve path metadata inside nested body parameter groups - #146
Conversation
Memory Profile ReportSummary
Iteration Details
Top Memory Allocations (by location)
Generated by Memory Profile workflow • Commit: 2bd2476 |
Danger ReportNo issues found. |
There was a problem hiding this comment.
🟢 Approval recommended
The behavior change is narrowly scoped, matches the stated issue/expected schema, and is covered by both unit and e2e regression tests.
Pull request overview
This PR fixes a request-parameter edge case in the API model builder where a declared route capture (path parameter) could be misclassified as part of a nested request body group and then recreated via the path-parameter fallback as a generic string, losing its declared description/type/format.
Changes:
- Adjust
RequestParams#extract_non_body_paramsto not skip route captures when nested params are present, allowingParamLocationResolverto correctly classify them as"path"and preserve declared metadata. - Add a unit regression test around the nested-param builder output for a path capture inside an outer
param_type: "body"group. - Add an end-to-end regression test across OAS 2.0 / 3.0 / 3.1 that validates both (a) preserved declared path metadata and (b) continued fallback generation for an undeclared capture; document the fix in
CHANGELOG.md.
Review Checklist Findings (schema correctness, test coverage, boundaries, compatibility, changelog/PR body, code quality)
- Nit (
lib/grape_oas/api_model_builders/request_params.rb:99-101): local variableis_hash_paramis actually derived frombody_param?and the comment refers to “Hash type params”, which is misleading now that route-capture exceptions are involved.
File summaries
| File | Description |
|---|---|
| lib/grape_oas/api_model_builders/request_params.rb | Prevents nested-param extraction from skipping declared route captures so path params keep their declared schema/description. |
| test/grape_oas/api_model_builders/request_params_nested_test.rb | Adds a focused unit regression test verifying the API model builder preserves path capture metadata within an outer body group. |
| test/e2e/generate_body_params_test.rb | Adds cross-OAS-version coverage ensuring declared path metadata is preserved while undeclared captures still fall back to required string. |
| CHANGELOG.md | Records the user-visible bug fix under Unreleased. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Automated review (3-reviewer panel) Summary: The nested-params skip now lets route captures through so Medium
next if [Hash, "Hash"].include?(spec[:type])
next if is_body_param && !route_params.include?(name)Add a nested Hash-capture regression either way. If object path params are intended, lock that shape in a test instead of leaving it implicit.
Low
4 files changed · 0 High · 3 Medium · 2 Low · Reviewed by: Bug Hunter, Architect, Guardian |
4177389 to
6f612fe
Compare
Merging #145 removed the only caller of ParamLocationResolver.body_param? (and its sole dependent, body_annotation?), leaving both unreferenced. Rename the surviving Hash-type check to hash_param? and call it directly from request_params.rb, so the Hash-type literal has one home instead of being duplicated across both files. Closes #148.
build_parameter already forces required: true for any "path" location, but no test asserted this for a flat (non-nested) route where the Grape declaration itself is optional. Without coverage, a future change to build_parameter could silently reintroduce invalid specs where an optional Grape path capture is documented as an optional OAS parameter.
Two entries for one PR (one under Fixed, one under Changed) duplicated attribution for the same change; fold the required-flag correction into the existing path-metadata entry, and keep it under the still-unreleased 1.5.1 section alongside #145.
|
Addressed review follow-ups:
Full suite green (1634 runs, 0 failures) and RuboCop clean. |
Problem
A declared path parameter inherits
param_type: "body"from an outer Grape parameter group and is skipped when the request has nested fields. The fallback then recreates it as a string, losing its description, type, and format. Closes #143.Fix
Skip Hash parents while allowing the location resolver to classify scalar route captures ahead of inherited body metadata. Path parameters are always required, even when their Grape declaration is optional. Keep fallback generation for undeclared captures and keep declared captures out of the body schema.
Example
Schema before / after
OAS 2.0 path parameter excerpt:
OAS 3.0 and 3.1 preserve the same description on the parameter and emit
type: integerandformat: int64inside itsschema. The nested payload remains in the request body.Backward compatibility
No public API changes. Optional declared path captures now emit
required: true, as required by OpenAPI. Hash-typed captures retain the existing string fallback. Generated clients may now use the declared path type instead of the fallback string. Undeclared captures retain the required string fallback. No new dependencies.