From bc246d86b7e713cc90da66ac4795fc80c8e04a3d Mon Sep 17 00:00:00 2001 From: Eric Proulx Date: Sat, 20 Dec 2025 20:19:25 +0000 Subject: [PATCH] explicit kwargs for namespace and route_param --- CHANGELOG.md | 2 +- UPGRADING.md | 6 ++++-- lib/grape/dsl/routing.rb | 18 +++++++----------- lib/grape/namespace.rb | 14 +++++--------- spec/grape/dsl/routing_spec.rb | 2 +- 5 files changed, 18 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 123610c04..ce0b0f357 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ * [#2649](https://github.com/ruby-grape/grape/pull/2644): Drop support Ruby 3.0 and ActiveSupport 7.0 - [@ericproulx](https://github.com/ericproulx). * [#2648](https://github.com/ruby-grape/grape/pull/2648): Remove deprecated ParamsBuilders extensions - [@ericproulx](https://github.com/ericproulx). * [#2645](https://github.com/ruby-grape/grape/pull/2645): Endpoints are compiled when API is compiled - [@ericproulx](https://github.com/ericproulx). - +* [#2647](https://github.com/ruby-grape/grape/pull/2647): Explicit kwargs for `namespace` and `route_param` - [@ericproulx](https://github.com/ericproulx). * Your contribution here. #### Fixes diff --git a/UPGRADING.md b/UPGRADING.md index c8cfa110c..30ea387e5 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -3,12 +3,14 @@ Upgrading Grape ### Upgrading to >= 3.1 +#### Explicit kwargs for `namespace` and `route_param` + +The `API#namespace` and `route_param` methods are now defined with `**options` instead of `options = {}`. In addtion, `requirements` in explicitly defined so it's not in `options` anymore. You can still call `requirements` like before but `options[:requirements]` will be empty. For `route_param`, `type` is also an explicit parameter so it's not in `options` anymore. See [#2647](https://github.com/ruby-grape/grape/pull/2647) for more information. + #### ParamsBuilder Grape::Extensions Deprecated [ParamsBuilder's extensions](https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#params-builder) have been removed. -### Upgrading to >= 3.1.0 - #### Enhanced API compile! Endpoints are now "compiled" instead of lazy loaded. Historically, when calling `YourAPI.compile!` in `config.ru` (or just receiving the first API call), only routing was compiled see [Grape::Router#compile!](https://github.com/ruby-grape/grape/blob/bf90e95c3b17c415c944363b1c07eb9727089ee7/lib/grape/router.rb#L41-L54) and endpoints were lazy loaded. Now, it's part of the API compilation. See [#2645](https://github.com/ruby-grape/grape/pull/2645) for more information. diff --git a/lib/grape/dsl/routing.rb b/lib/grape/dsl/routing.rb index d80eb23ca..3698fb2db 100644 --- a/lib/grape/dsl/routing.rb +++ b/lib/grape/dsl/routing.rb @@ -198,12 +198,12 @@ def route(methods, paths = ['/'], route_options = {}, &) # # defines the endpoint: GET /foo/bar # end # end - def namespace(space = nil, options = {}, &block) + def namespace(space = nil, requirements: nil, **options, &block) return Namespace.joined_space_path(inheritable_setting.namespace_stackable[:namespace]) unless space || block within_namespace do nest(block) do - inheritable_setting.namespace_stackable[:namespace] = Grape::Namespace.new(space, options) if space + inheritable_setting.namespace_stackable[:namespace] = Grape::Namespace.new(space, requirements: requirements, **options) if space end end end @@ -223,18 +223,14 @@ def routes # # @param param [Symbol] The name of the parameter you wish to declare. # @option options [Regexp] You may supply a regular expression that the declared parameter must meet. - def route_param(param, **options, &) - options = options.dup - - options[:requirements] = { - param.to_sym => options[:requirements] - } if options[:requirements].is_a?(Regexp) + def route_param(param, requirements: nil, type: nil, **options, &) + requirements = { param.to_sym => requirements } if requirements.is_a?(Regexp) Grape::Validations::ParamsScope.new(api: self) do - requires param, type: options[:type] - end if options.key?(:type) + requires param, type: type + end if type - namespace(":#{param}", options, &) + namespace(":#{param}", requirements: requirements, **options, &) end # @return array of defined versions diff --git a/lib/grape/namespace.rb b/lib/grape/namespace.rb index dd19d98be..d6b12adf0 100644 --- a/lib/grape/namespace.rb +++ b/lib/grape/namespace.rb @@ -5,24 +5,19 @@ module Grape # logical grouping of endpoints as well as sharing common configuration. # May also be referred to as group, segment, or resource. class Namespace - attr_reader :space, :options + attr_reader :space, :requirements, :options # @param space [String] the name of this namespace # @param options [Hash] options hash # @option options :requirements [Hash] param-regex pairs, all of which must # be met by a request's params for all endpoints in this namespace, or # validation will fail and return a 422. - def initialize(space, options) + def initialize(space, requirements: nil, **options) @space = space.to_s + @requirements = requirements @options = options end - # Retrieves the requirements from the options hash, if given. - # @return [Hash] - def requirements - options[:requirements] || {} - end - # (see ::joined_space_path) def self.joined_space(settings) settings&.map(&:space) @@ -31,12 +26,13 @@ def self.joined_space(settings) def eql?(other) other.class == self.class && other.space == space && + other.requirements == requirements && other.options == options end alias == eql? def hash - [self.class, space, options].hash + [self.class, space, requirements, options].hash end # Join the namespaces from a list of settings to create a path prefix. diff --git a/spec/grape/dsl/routing_spec.rb b/spec/grape/dsl/routing_spec.rb index 2a46144f9..a173b8418 100644 --- a/spec/grape/dsl/routing_spec.rb +++ b/spec/grape/dsl/routing_spec.rb @@ -280,7 +280,7 @@ class << self let(:regex) { /(.*)/ } it 'calls #namespace with given params' do - expect(subject).to receive(:namespace).with(':foo', {}).and_yield + expect(subject).to receive(:namespace).with(':foo', requirements: nil).and_yield subject.route_param('foo', &proc {}) end