Skip to content
Open
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 @@ -12,6 +12,7 @@
* [#2643](https://github.com/ruby-grape/grape/pull/2638): Remove `try` method in codebase - [@ericproulx](https://github.com/ericproulx).
* [#2646](https://github.com/ruby-grape/grape/pull/2646): Call `valid_encoding?` before scrub - [@ericproulx](https://github.com/ericproulx).
* [#2644](https://github.com/ruby-grape/grape/pull/2644): Clean useless/not valuable dependencies - [@ericproulx](https://github.com/ericproulx).
* [#2648](https://github.com/ruby-grape/grape/pull/2648): Explicit kwargs for `namespace` and `route_param` - [@ericproulx](https://github.com/ericproulx).
* Your contribution here.

#### Fixes
Expand Down
6 changes: 6 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Upgrading Grape
===============

### Upgrading to >= 3.1

#### Explicit kwargs for `namespace` and `route_param`

`namespace` and `route_param` are now now defined with a `**options` instead of `options = {}`. In addtion, `requirements` in explicitely defined so its 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.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
`namespace` and `route_param` are now now defined with a `**options` instead of `options = {}`. In addtion, `requirements` in explicitely defined so its 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.
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.

Copy link
Member

Choose a reason for hiding this comment

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

Is this part of an API change/breaking change?
Does this need a before/after with an example of how to call it?


### Upgrading to >= 3.0.0

#### Ruby 3+ Argument Delegation Modernization
Expand Down
18 changes: 7 additions & 11 deletions lib/grape/dsl/routing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,12 @@ def route(methods, paths = ['/'], route_options = {}, &block)
# # 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
Expand All @@ -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, &block)
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, &block)
requirements = { param.to_sym => requirements } if requirements.is_a?(Regexp)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
requirements = { param.to_sym => requirements } if requirements.is_a?(Regexp)
requirements = { param.to_sym => requirements } if requirements&.is_a?(Regexp)

Nit, but that avoids calling is_a?(nil)?


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, &block)
namespace(":#{param}", requirements: requirements, **options, &block)
end

# @return array of defined versions
Expand Down
14 changes: 5 additions & 9 deletions lib/grape/namespace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion spec/grape/dsl/routing_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading