Skip to content

Commit c35ac86

Browse files
committed
fix(#2350): Use musterman-grape 1.1.0 for recognize_paths taking into account the route_param type
1 parent 103928a commit c35ac86

File tree

7 files changed

+160
-4
lines changed

7 files changed

+160
-4
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
* [#2371](https://github.com/ruby-grape/grape/pull/2371): Use a param value as the `default` value of other param - [@jcagarcia](https://github.com/jcagarcia).
66
* [#2377](https://github.com/ruby-grape/grape/pull/2377): Allow to use instance variables values inside `rescue_from` - [@jcagarcia](https://github.com/jcagarcia).
7+
* [#2379](https://github.com/ruby-grape/grape/pull/2379): `recognize_path` now takes into account the `route_param` type - [@jcagarcia](https://github.com/jcagarcia)
78
* Your contribution here.
89

910
#### Fixes

README.md

+27
Original file line numberDiff line numberDiff line change
@@ -2408,6 +2408,33 @@ end
24082408
API.recognize_path '/statuses'
24092409
```
24102410

2411+
Since version `2.1.0`, the `recognize_path` method takes into account the parameters type to determine which endpoint should match with given path.
2412+
2413+
```ruby
2414+
class Books < Grape::API
2415+
resource :books do
2416+
route_param :id, type: Integer do
2417+
# GET /books/:id
2418+
get do
2419+
#...
2420+
end
2421+
end
2422+
2423+
resource :share do
2424+
# POST /books/share
2425+
post do
2426+
# ....
2427+
end
2428+
end
2429+
end
2430+
end
2431+
2432+
API.recognize_path '/books/1' # => /books/:id
2433+
API.recognize_path '/books/share' # => /books/share
2434+
API.recognize_path '/books/other' # => nil
2435+
```
2436+
2437+
24112438
## Allowed Methods
24122439

24132440
When you add a `GET` route for a resource, a route for the `HEAD` method will also be added automatically. You can disable this behavior with `do_not_route_head!`.

UPGRADING.md

+42
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,48 @@ class TwitterAPI < Grape::API
5151
end
5252
```
5353

54+
#### Recognizing Path
55+
56+
Due to the changes done in [#2379](https://github.com/ruby-grape/grape/pull/2379), Grape now takes in mind the types of the configured `route_params` in order to determine the endpoint that matches with the performed request.
57+
58+
So taking into account this `Grape::API` class
59+
60+
```ruby
61+
class Books < Grape::API
62+
resource :books do
63+
route_param :id, type: Integer do
64+
# GET /books/:id
65+
get do
66+
#...
67+
end
68+
end
69+
70+
resource :share do
71+
# POST /books/share
72+
post do
73+
# ....
74+
end
75+
end
76+
end
77+
end
78+
```
79+
80+
This was the behavior before the changes:
81+
```ruby
82+
API.recognize_path '/books/1' # => /books/:id
83+
API.recognize_path '/books/share' # => /books/:id
84+
API.recognize_path '/books/other' # => /books/:id
85+
```
86+
87+
And this is the behavior now:
88+
```ruby
89+
API.recognize_path '/books/1' # => /books/:id
90+
API.recognize_path '/books/share' # => /books/share
91+
API.recognize_path '/books/other' # => nil
92+
```
93+
94+
This implies that before this changes, when you performed `/books/other` and it matched with the `/books/:id` endpoint, you get a `400 Bad Request` response because the type of the provided `:id` param was not an `Integer`. However, after upgrading to version `2.1.0` you will get a `404 Not Found` response, because there is not a defined endpoint that matches with `/books/other`.
95+
5496
### Upgrading to >= 2.0.0
5597

5698
#### Headers

grape.gemspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
2323
s.add_runtime_dependency 'activesupport', '>= 5'
2424
s.add_runtime_dependency 'builder'
2525
s.add_runtime_dependency 'dry-types', '>= 1.1'
26-
s.add_runtime_dependency 'mustermann-grape', '~> 1.0.0'
26+
s.add_runtime_dependency 'mustermann-grape', '~> 1.1.0'
2727
s.add_runtime_dependency 'rack', '>= 1.3.0'
2828
s.add_runtime_dependency 'rack-accept'
2929

lib/grape/router/pattern.rb

+2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ def initialize(pattern, **options)
2828

2929
def pattern_options(options)
3030
capture = extract_capture(**options)
31+
params = options[:params]
3132
options = DEFAULT_PATTERN_OPTIONS.dup
3233
options[:capture] = capture if capture.present?
34+
options[:params] = params if params.present?
3335
options
3436
end
3537

spec/grape/api/recognize_path_spec.rb

+67
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,72 @@
1717
subject.get {}
1818
expect(subject.recognize_path('/bar/1234')).to be_nil
1919
end
20+
21+
context 'given parametrized route with type specified and static route' do
22+
subject do
23+
Class.new(described_class) do
24+
resource :books do
25+
route_param :id, type: Integer do
26+
get do
27+
end
28+
29+
resource :loans do
30+
route_param :loan_id, type: Integer do
31+
get do
32+
end
33+
end
34+
35+
resource :print do
36+
post do
37+
end
38+
end
39+
end
40+
end
41+
42+
resource :share do
43+
post do
44+
end
45+
end
46+
end
47+
end
48+
end
49+
50+
context 'when the parameter does not match with the specified type' do
51+
it 'recognizes the static route' do
52+
actual = subject.recognize_path('/books/share').routes[0].origin
53+
expect(actual).to eq('/books/share')
54+
end
55+
56+
context 'and there is not other endpoint that matches with the requested path' do
57+
it 'does not recognize any endpoint' do
58+
actual = subject.recognize_path('/books/other')
59+
expect(actual).to eq(nil)
60+
end
61+
end
62+
end
63+
64+
context 'when the parameter matches with the specified type' do
65+
it 'recognizes the parametrized route' do
66+
actual = subject.recognize_path('/books/1').routes[0].origin
67+
expect(actual).to eq('/books/:id')
68+
end
69+
end
70+
71+
context 'when requesting nested paths' do
72+
context 'when the parameter does not match with the specified type' do
73+
it 'recognizes the static route' do
74+
actual = subject.recognize_path('/books/1/loans/print').routes[0].origin
75+
expect(actual).to eq('/books/:id/loans/print')
76+
end
77+
end
78+
79+
context 'when the parameter matches with the specified type' do
80+
it 'recognizes the parametrized route' do
81+
actual = subject.recognize_path('/books/1/loans/33').routes[0].origin
82+
expect(actual).to eq('/books/:id/loans/:loan_id')
83+
end
84+
end
85+
end
86+
end
2087
end
2188
end

spec/grape/api_spec.rb

+20-3
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,7 @@ class DummyFormatClass
11321132
d = double('after mock')
11331133

11341134
subject.params do
1135-
requires :id, type: Integer
1135+
requires :id, type: Integer, values: [1, 2, 3]
11361136
end
11371137
subject.resource ':id' do
11381138
before { a.do_something! }
@@ -1151,9 +1151,9 @@ class DummyFormatClass
11511151
expect(c).to receive(:do_something!).exactly(0).times
11521152
expect(d).to receive(:do_something!).exactly(0).times
11531153

1154-
get '/abc'
1154+
get '/4'
11551155
expect(last_response.status).to be 400
1156-
expect(last_response.body).to eql 'id is invalid'
1156+
expect(last_response.body).to eql 'id does not have a valid value'
11571157
end
11581158

11591159
it 'calls filters in the correct order' do
@@ -4408,5 +4408,22 @@ def uniqe_id_route
44084408
expect(last_response.body).to eq({ my_var: nil }.to_json)
44094409
end
44104410
end
4411+
4412+
context 'when set type to a route_param' do
4413+
context 'and the param does not match' do
4414+
it 'returns a 404 response' do
4415+
subject.namespace :books do
4416+
route_param :id, type: Integer do
4417+
get do
4418+
params[:id]
4419+
end
4420+
end
4421+
end
4422+
4423+
get '/books/other'
4424+
expect(last_response.status).to be 404
4425+
end
4426+
end
4427+
end
44114428
end
44124429
end

0 commit comments

Comments
 (0)