Skip to content
Merged
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
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 = {}, &)
# # 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, &)
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
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