Skip to content

Ruby 3.4 and refactor swagger documentation modules#976

Open
moskvin wants to merge 13 commits into
ruby-grape:masterfrom
moskvin:master
Open

Ruby 3.4 and refactor swagger documentation modules#976
moskvin wants to merge 13 commits into
ruby-grape:masterfrom
moskvin:master

Conversation

@moskvin
Copy link
Copy Markdown

@moskvin moskvin commented May 11, 2026

  • Aligns lint configuration with Ruby 3.4 target.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 11, 2026

Danger Report

No issues found.

View run

@moskvin moskvin changed the title [dev] Ruby 3.4 Ruby 3.4 and refactor swagger documentation modules May 11, 2026
@numbata numbata self-requested a review May 11, 2026 15:29
@moskvin
Copy link
Copy Markdown
Author

moskvin commented May 12, 2026

I've to drop support the old grape version to make CI happy

@moskvin
Copy link
Copy Markdown
Author

moskvin commented May 12, 2026

I would suggest to dropping ruby 3.1 from CI

@moskvin
Copy link
Copy Markdown
Author

moskvin commented May 12, 2026

@numbata please have a look again - I've removed some weird changes

@numbata
Copy link
Copy Markdown
Contributor

numbata commented May 12, 2026

@moskvin Thx for contribution!
I'll review the PR later today. Hope it is okay for you.

Copy link
Copy Markdown
Contributor

@numbata numbata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! Very good job 👍

Main things before this can merge: the CI matrix now starts at Grape 2.4.0 but the gemspec still says >= 1.7, so either the gemspec needs updating or we should keep at least one older entry. And SwaggerRouting/SwaggerDocumentationAdder sitting at the top level is a collision risk, as now that they have their own files it's a good moment to nest them under GrapeSwagger::.

The triple lookup and test issues are in the inline comments. The dead-code comment and each_key signature are minor but easy to fix while you're already touching those lines.

@@ -0,0 +1,97 @@
# frozen_string_literal: true

module SwaggerRouting
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the module lives in its own file, this is the natural moment to fix the top-level namespace pollution and nest it under GrapeSwagger::. Same applies to SwaggerDocumentationAdder in the sibling file. If you want to keep the old constant reachable for any out-of-tree code that referenced it, you can SwaggerRouting = GrapeSwagger::SwaggerRouting with a deprecation warning, but the canonical name should be namespaced.


defined_options = definition.is_a?(Hash) ? definition : {}
value = (path_params[param] || {}).merge(defined_options)
path_options = path_params[param] || path_params[param.to_s] || path_params[param.to_sym] || {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

  alt = param.is_a?(Symbol) ? param.to_s : param.to_sym
  path_options = path_params[param] || path_params[alt] || {}

or normalize keys once in build_path_params so callers don't need to think about it.

Comment thread .github/workflows/ci.yml
Comment on lines -29 to -32
- { ruby: '3.1', grape: '1.8.0' }
- { ruby: '3.2', grape: '1.8.0' }
- { ruby: '3.3', grape: '1.8.0' }
- { ruby: '3.4', grape: '1.8.0' }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The gemspec declares grape >= 1.7, but this PR replaces all matrix entries for Grape 1.8.0–2.2.0 with 2.4.0+. As the minimum requirement is being raised to 2.4.0, could you update the gemspec and README?

def combine_namespace_routes(namespaces, routes)
combined_namespace_routes = {}
# iterate over each single namespace
namespaces.each_key do |name, _|
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hash#each_key yields exactly one value (the key). The _ parameter silently receives nil. Pre-existing code, but now extracted into a permanent home, so maybe let's do such small fix as well?

Suggested change
namespaces.each_key do |name, _|
namespaces.each_key do |name|

Comment on lines +12 to +14
# want to match emojis ... ;)
# route_match = route_match
# .match('\/([\p{Alnum}p{Emoji}\-\_]*?)[\.\/\(]') || route_match.match('\/([\p{Alpha}\p{Emoji}\-\_]*)$')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably should be removed as a dead-code with comment?

end
end

context 'when route.params uses string keys and path params use symbol keys' do
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This context passes symbol-keyed path_params ({ id: { ... } }), but fetch_inherited_params always produces string keys via space.to_s.gsub(':', ''), so path_params[param.to_sym] can never find anything in production.

The real fix scenario is in symbol-keyed route.params + string-keyed path_params isn't yet covered. The existing 'when inherited namespace stackable values contain path params across levels' context uses string-keyed route.params, so path_params[param] hits directly and the param.to_s fallback is never reached.

Suggest replacing this context with a #parse integration test that exercises the actual fix path:

context 'when route.params has symbol keys but namespace options use string keys' do
  let(:stackable) { Grape::Util::StackableValues.new }
  let(:inheritable_setting) { instance_double('inheritable_setting', namespace_stackable: stackable) }
  let(:app) { instance_double('app', inheritable_setting: inheritable_setting) }

  before do
    stackable[:namespace] = instance_double('namespace', space: ':id', options: { required: true, type: 'Integer' })
    allow(route).to receive(:app).and_return(app)
    allow(route).to receive(:params).and_return(id: {})
  end

  it 'merges namespace options into the symbol-keyed route param' do
    expect(parse_request_params).to eq(id: { required: true, type: 'Integer' })
  end
end

wdyt?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants