grape 0.18.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grape might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +52 -69
- data/Gemfile +3 -3
- data/Gemfile.lock +37 -41
- data/README.md +49 -7
- data/UPGRADING.md +56 -1
- data/gemfiles/rack_edge.gemfile +34 -0
- data/gemfiles/rails_5.gemfile +1 -1
- data/gemfiles/rails_edge.gemfile +34 -0
- data/lib/grape/api.rb +1 -1
- data/lib/grape/dsl/helpers.rb +1 -0
- data/lib/grape/dsl/inside_route.rb +2 -0
- data/lib/grape/dsl/parameters.rb +24 -12
- data/lib/grape/dsl/request_response.rb +2 -3
- data/lib/grape/dsl/routing.rb +4 -0
- data/lib/grape/endpoint.rb +15 -16
- data/lib/grape/error_formatter/base.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -2
- data/lib/grape/http/headers.rb +2 -0
- data/lib/grape/middleware/base.rb +3 -4
- data/lib/grape/middleware/error.rb +1 -1
- data/lib/grape/middleware/versioner/path.rb +1 -1
- data/lib/grape/router.rb +37 -21
- data/lib/grape/router/attribute_translator.rb +1 -1
- data/lib/grape/router/pattern.rb +9 -1
- data/lib/grape/router/route.rb +4 -0
- data/lib/grape/validations/params_scope.rb +24 -6
- data/lib/grape/validations/validators/base.rb +1 -2
- data/lib/grape/validations/validators/regexp.rb +2 -1
- data/lib/grape/version.rb +1 -1
- data/pkg/grape-0.17.0.gem +0 -0
- data/spec/grape/api/patch_method_helpers_spec.rb +1 -2
- data/spec/grape/api_spec.rb +87 -21
- data/spec/grape/dsl/desc_spec.rb +2 -4
- data/spec/grape/dsl/inside_route_spec.rb +29 -22
- data/spec/grape/dsl/parameters_spec.rb +15 -1
- data/spec/grape/endpoint_spec.rb +53 -19
- data/spec/grape/middleware/formatter_spec.rb +39 -30
- data/spec/grape/middleware/versioner/param_spec.rb +15 -10
- data/spec/grape/middleware/versioner/path_spec.rb +4 -3
- data/spec/grape/util/inheritable_setting_spec.rb +2 -1
- data/spec/grape/util/strict_hash_configuration_spec.rb +1 -2
- data/spec/grape/validations/params_scope_spec.rb +182 -0
- data/spec/grape/validations/validators/default_spec.rb +1 -3
- data/spec/grape/validations/validators/presence_spec.rb +29 -1
- data/spec/grape/validations/validators/regexp_spec.rb +88 -0
- metadata +5 -3
- data/pkg/grape-0.18.0.gem +0 -0
data/README.md
CHANGED
@@ -38,6 +38,7 @@
|
|
38
38
|
- [Multiple Allowed Types](#multiple-allowed-types)
|
39
39
|
- [Validation of Nested Parameters](#validation-of-nested-parameters)
|
40
40
|
- [Dependent Parameters](#dependent-parameters)
|
41
|
+
- [Group Options](#group-options)
|
41
42
|
- [Built-in Validators](#built-in-validators)
|
42
43
|
- [Namespace Validation and Coercion](#namespace-validation-and-coercion)
|
43
44
|
- [Custom Validators](#custom-validators)
|
@@ -104,7 +105,7 @@ content negotiation, versioning and much more.
|
|
104
105
|
|
105
106
|
## Stable Release
|
106
107
|
|
107
|
-
You're reading the documentation for the stable release of Grape.
|
108
|
+
You're reading the documentation for the stable release of Grape, 0.19.0.
|
108
109
|
Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
|
109
110
|
|
110
111
|
## Project Resources
|
@@ -1000,6 +1001,35 @@ params do
|
|
1000
1001
|
end
|
1001
1002
|
```
|
1002
1003
|
|
1004
|
+
|
1005
|
+
### Group Options
|
1006
|
+
|
1007
|
+
Parameters options can be grouped. It can be useful if you want to extract
|
1008
|
+
common validation or types for several parameters. The example below presents a
|
1009
|
+
typical case when parameters share common options.
|
1010
|
+
|
1011
|
+
```ruby
|
1012
|
+
params do
|
1013
|
+
requires :first_name, type: String, regexp: /w+/, desc: 'First name'
|
1014
|
+
requires :middle_name, type: String, regexp: /w+/, desc: 'Middle name'
|
1015
|
+
requires :last_name, type: String, regexp: /w+/, desc: 'Last name'
|
1016
|
+
end
|
1017
|
+
```
|
1018
|
+
|
1019
|
+
Grape allows you to present the same logic through the `with` method in your
|
1020
|
+
parameters block, like so:
|
1021
|
+
|
1022
|
+
```ruby
|
1023
|
+
params do
|
1024
|
+
with(type: String, regexp: /w+/) do
|
1025
|
+
requires :first_name, desc: 'First name'
|
1026
|
+
requires :middle_name, desc: 'Middle name'
|
1027
|
+
requires :last_name, desc: 'Last name'
|
1028
|
+
end
|
1029
|
+
end
|
1030
|
+
```
|
1031
|
+
|
1032
|
+
|
1003
1033
|
### Built-in Validators
|
1004
1034
|
|
1005
1035
|
#### `allow_blank`
|
@@ -1075,12 +1105,12 @@ end
|
|
1075
1105
|
```
|
1076
1106
|
|
1077
1107
|
Values and except can be combined to define a range of accepted values while not allowing
|
1078
|
-
certain values within the set. Custom error messages can be defined for both when the parameter
|
1079
|
-
passed falls within the ```except``` list or when it falls entirely outside the ```value``` list.
|
1108
|
+
certain values within the set. Custom error messages can be defined for both when the parameter
|
1109
|
+
passed falls within the ```except``` list or when it falls entirely outside the ```value``` list.
|
1080
1110
|
|
1081
1111
|
```ruby
|
1082
1112
|
params do
|
1083
|
-
requires :number, type: Integer, values: { value: 1..20 except: [4,13], except_message: 'includes unsafe numbers', message: 'is outside the range of numbers allowed' }
|
1113
|
+
requires :number, type: Integer, values: { value: 1..20, except: [4, 13], except_message: 'includes unsafe numbers', message: 'is outside the range of numbers allowed' }
|
1084
1114
|
end
|
1085
1115
|
```
|
1086
1116
|
|
@@ -1710,7 +1740,7 @@ cookies.delete :status_count, path: '/'
|
|
1710
1740
|
|
1711
1741
|
## HTTP Status Code
|
1712
1742
|
|
1713
|
-
By default Grape returns a
|
1743
|
+
By default Grape returns a 201 for `POST`-Requests, 204 for `DELETE`-Requests and 200 status code for all other Requests.
|
1714
1744
|
You can use `status` to query and set the actual HTTP Status Code
|
1715
1745
|
|
1716
1746
|
```ruby
|
@@ -1776,7 +1806,9 @@ end
|
|
1776
1806
|
|
1777
1807
|
When you add a route for a resource, a route for the `OPTIONS`
|
1778
1808
|
method will also be added. The response to an OPTIONS request will
|
1779
|
-
include an "Allow" header listing the supported methods.
|
1809
|
+
include an "Allow" header listing the supported methods. If the resource
|
1810
|
+
has `before` and `after` callbacks they will be executed, but no other callbacks will
|
1811
|
+
run.
|
1780
1812
|
|
1781
1813
|
```ruby
|
1782
1814
|
class API < Grape::API
|
@@ -1806,7 +1838,9 @@ curl -v -X OPTIONS http://localhost:3000/rt_count
|
|
1806
1838
|
You can disable this behavior with `do_not_route_options!`.
|
1807
1839
|
|
1808
1840
|
If a request for a resource is made with an unsupported HTTP method, an
|
1809
|
-
HTTP 405 (Method Not Allowed) response will be returned.
|
1841
|
+
HTTP 405 (Method Not Allowed) response will be returned. If the resource
|
1842
|
+
has `before` callbacks they will be executed, but no other callbacks will
|
1843
|
+
run.
|
1810
1844
|
|
1811
1845
|
``` shell
|
1812
1846
|
curl -X DELETE -v http://localhost:3000/rt_count/
|
@@ -2766,6 +2800,14 @@ Before and after callbacks execute in the following order:
|
|
2766
2800
|
|
2767
2801
|
Steps 4, 5 and 6 only happen if validation succeeds.
|
2768
2802
|
|
2803
|
+
If a request for a resource is made with an unsupported HTTP method (returning
|
2804
|
+
HTTP 405) only `before` callbacks will be executed. The remaining callbacks will
|
2805
|
+
be bypassed.
|
2806
|
+
|
2807
|
+
If a request for a resource is made that triggers the built-in `OPTIONS` handler,
|
2808
|
+
only `before` and `after` callbacks will be executed. The remaining callbacks will
|
2809
|
+
be bypassed.
|
2810
|
+
|
2769
2811
|
#### Examples
|
2770
2812
|
|
2771
2813
|
Using a simple `before` block to set a header
|
data/UPGRADING.md
CHANGED
@@ -1,6 +1,61 @@
|
|
1
1
|
Upgrading Grape
|
2
2
|
===============
|
3
3
|
|
4
|
+
### Upgrading to >= 0.18.1
|
5
|
+
|
6
|
+
#### Changes in priority of :any routes
|
7
|
+
|
8
|
+
Prior to this version, `:any` routes were searched after matching first route and 405 routes. This behavior has changed and `:any` routes are now searched before 405 processing. In the following example the `:any` route will match first when making a request with an unsupported verb.
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
post :example do
|
12
|
+
'example'
|
13
|
+
end
|
14
|
+
route :any, '*path' do
|
15
|
+
error! :not_found, 404
|
16
|
+
end
|
17
|
+
|
18
|
+
get '/example' #=> before: 405, after: 404
|
19
|
+
```
|
20
|
+
|
21
|
+
#### Removed param processing from built-in OPTIONS handler
|
22
|
+
|
23
|
+
When a request is made to the built-in `OPTIONS` handler, only the `before` and `after`
|
24
|
+
callbacks associated with the resource will be run. The `before_validation` and
|
25
|
+
`after_validation` callbacks and parameter validations will be skipped.
|
26
|
+
|
27
|
+
See [#1505](https://github.com/ruby-grape/grape/pull/1505) for more information.
|
28
|
+
|
29
|
+
#### Changed endpoint params validation
|
30
|
+
|
31
|
+
Grape now correctly returns validation errors for all params when multiple params are passed to a requires.
|
32
|
+
The following code will return `one is missing, two is missing` when calling the endpoint without parameters.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
params do
|
36
|
+
requires :one, :two
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
Prior to this version the response would be `one is missing`.
|
41
|
+
|
42
|
+
See [#1510](https://github.com/ruby-grape/grape/pull/1510) for more information.
|
43
|
+
|
44
|
+
#### The default status code for DELETE is now 204 instead of 200.
|
45
|
+
|
46
|
+
Breaking change: Sets the default response status code for a delete request to 204.
|
47
|
+
A status of 204 makes the response more distinguishable and therefore easier to handle on the client side, particularly because a DELETE request typically returns an empty body as the resource was deleted or voided.
|
48
|
+
|
49
|
+
To achieve the old behavior, one has to set it explicitly:
|
50
|
+
```ruby
|
51
|
+
delete :id do
|
52
|
+
status 200
|
53
|
+
'foo successfully deleted'
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
For more information see: [#1532](https://github.com/ruby-grape/grape/pull/1532).
|
58
|
+
|
4
59
|
### Upgrading to >= 0.17.0
|
5
60
|
|
6
61
|
#### Removed official support for Ruby < 2.2.2
|
@@ -14,7 +69,7 @@ See [#1441](https://github.com/ruby-grape/grape/pull/1441) for nmore information
|
|
14
69
|
The `rescue_from` clauses declared inside a namespace would take a priority over ones declared in the root scope.
|
15
70
|
This could possibly affect those users who use different `rescue_from` clauses in root scope and in namespaces.
|
16
71
|
|
17
|
-
See [#1405](https://github.com/ruby-grape/grape/pull/1405) for more
|
72
|
+
See [#1405](https://github.com/ruby-grape/grape/pull/1405) for more information.
|
18
73
|
|
19
74
|
#### Helper methods injected inside `rescue_from` in middleware
|
20
75
|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gem 'rack', github: 'rack/rack'
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem 'bundler'
|
9
|
+
gem 'rake'
|
10
|
+
gem 'rubocop', '~> 0.45.0'
|
11
|
+
end
|
12
|
+
|
13
|
+
group :development do
|
14
|
+
gem 'guard'
|
15
|
+
gem 'guard-rspec'
|
16
|
+
gem 'guard-rubocop'
|
17
|
+
gem 'yard'
|
18
|
+
gem 'appraisal'
|
19
|
+
gem 'benchmark-ips'
|
20
|
+
gem 'redcarpet'
|
21
|
+
end
|
22
|
+
|
23
|
+
group :test do
|
24
|
+
gem 'grape-entity', '~> 0.6'
|
25
|
+
gem 'maruku'
|
26
|
+
gem 'rack-test'
|
27
|
+
gem 'rspec', '~> 3.0'
|
28
|
+
gem 'cookiejar'
|
29
|
+
gem 'rack-jsonp', require: 'rack/jsonp'
|
30
|
+
gem 'mime-types', '~> 3.0'
|
31
|
+
gem 'ruby-grape-danger', '~> 0.1.0', require: false
|
32
|
+
end
|
33
|
+
|
34
|
+
gemspec path: '../'
|
data/gemfiles/rails_5.gemfile
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gem 'rails', github: 'rails/rails'
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem 'bundler'
|
9
|
+
gem 'rake'
|
10
|
+
gem 'rubocop', '~> 0.45.0'
|
11
|
+
end
|
12
|
+
|
13
|
+
group :development do
|
14
|
+
gem 'guard'
|
15
|
+
gem 'guard-rspec'
|
16
|
+
gem 'guard-rubocop'
|
17
|
+
gem 'yard'
|
18
|
+
gem 'appraisal'
|
19
|
+
gem 'benchmark-ips'
|
20
|
+
gem 'redcarpet'
|
21
|
+
end
|
22
|
+
|
23
|
+
group :test do
|
24
|
+
gem 'grape-entity', '~> 0.6'
|
25
|
+
gem 'maruku'
|
26
|
+
gem 'rack-test'
|
27
|
+
gem 'rspec', '~> 3.0'
|
28
|
+
gem 'cookiejar'
|
29
|
+
gem 'rack-jsonp', require: 'rack/jsonp'
|
30
|
+
gem 'mime-types', '~> 3.0'
|
31
|
+
gem 'ruby-grape-danger', '~> 0.1.0', require: false
|
32
|
+
end
|
33
|
+
|
34
|
+
gemspec path: '../'
|
data/lib/grape/api.rb
CHANGED
@@ -161,7 +161,7 @@ module Grape
|
|
161
161
|
route_settings[:endpoint] = route.app
|
162
162
|
|
163
163
|
# using the :any shorthand produces [nil] for route methods, substitute all manually
|
164
|
-
route_settings[:methods] = %w(GET PUT POST DELETE PATCH HEAD OPTIONS) if route_settings[:methods].include?('
|
164
|
+
route_settings[:methods] = %w(GET PUT POST DELETE PATCH HEAD OPTIONS) if route_settings[:methods].include?('*')
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
data/lib/grape/dsl/helpers.rb
CHANGED
data/lib/grape/dsl/parameters.rb
CHANGED
@@ -99,6 +99,7 @@ module Grape
|
|
99
99
|
|
100
100
|
opts = attrs.extract_options!.clone
|
101
101
|
opts[:presence] = { value: true, message: opts[:message] }
|
102
|
+
opts = @group.merge(opts) if @group
|
102
103
|
|
103
104
|
if opts[:using]
|
104
105
|
require_required_and_optional_fields(attrs.first, opts)
|
@@ -118,6 +119,7 @@ module Grape
|
|
118
119
|
|
119
120
|
opts = attrs.extract_options!.clone
|
120
121
|
type = opts[:type]
|
122
|
+
opts = @group.merge(opts) if @group
|
121
123
|
|
122
124
|
# check type for optional parameter group
|
123
125
|
if attrs && block_given?
|
@@ -134,6 +136,13 @@ module Grape
|
|
134
136
|
end
|
135
137
|
end
|
136
138
|
|
139
|
+
# Define common settings for one or more parameters
|
140
|
+
# @param (see #requires)
|
141
|
+
# @option (see #requires)
|
142
|
+
def with(*attrs, &block)
|
143
|
+
new_group_scope(attrs.clone, &block)
|
144
|
+
end
|
145
|
+
|
137
146
|
# Disallow the given parameters to be present in the same request.
|
138
147
|
# @param attrs [*Symbol] parameters to validate
|
139
148
|
def mutually_exclusive(*attrs)
|
@@ -167,8 +176,8 @@ module Grape
|
|
167
176
|
# @yield a parameter definition DSL
|
168
177
|
def given(*attrs, &block)
|
169
178
|
attrs.each do |attr|
|
170
|
-
|
171
|
-
raise Grape::Exceptions::UnknownParameter.new(
|
179
|
+
proxy_attr = attr.is_a?(Hash) ? attr.keys[0] : attr
|
180
|
+
raise Grape::Exceptions::UnknownParameter.new(proxy_attr) unless declared_param?(proxy_attr)
|
172
181
|
end
|
173
182
|
new_lateral_scope(dependent_on: attrs, &block)
|
174
183
|
end
|
@@ -184,21 +193,24 @@ module Grape
|
|
184
193
|
|
185
194
|
alias group requires
|
186
195
|
|
196
|
+
def map_params(params, element)
|
197
|
+
if params.is_a?(Array)
|
198
|
+
params.map do |el|
|
199
|
+
map_params(el, element)
|
200
|
+
end
|
201
|
+
elsif params.is_a?(Hash)
|
202
|
+
params[element] || {}
|
203
|
+
else
|
204
|
+
{}
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
187
208
|
# @param params [Hash] initial hash of parameters
|
188
209
|
# @return hash of parameters relevant for the current scope
|
189
210
|
# @api private
|
190
211
|
def params(params)
|
191
212
|
params = @parent.params(params) if @parent
|
192
|
-
if @element
|
193
|
-
params = if params.is_a?(Array)
|
194
|
-
# used for calculating parent array indices for error messages
|
195
|
-
params.map { |el| el[@element] || {} }
|
196
|
-
elsif params.is_a?(Hash)
|
197
|
-
params[@element] || {}
|
198
|
-
else
|
199
|
-
{}
|
200
|
-
end
|
201
|
-
end
|
213
|
+
params = map_params(params, @element) if @element
|
202
214
|
params
|
203
215
|
end
|
204
216
|
end
|
@@ -110,11 +110,10 @@ module Grape
|
|
110
110
|
end
|
111
111
|
handler ||= extract_with(options)
|
112
112
|
|
113
|
-
|
114
|
-
when args.include?(:all)
|
113
|
+
if args.include?(:all)
|
115
114
|
namespace_inheritable(:rescue_all, true)
|
116
115
|
namespace_inheritable :all_rescue_handler, handler
|
117
|
-
|
116
|
+
elsif args.include?(:grape_exceptions)
|
118
117
|
namespace_inheritable(:rescue_all, true)
|
119
118
|
namespace_inheritable(:rescue_grape_exceptions, true)
|
120
119
|
else
|
data/lib/grape/dsl/routing.rb
CHANGED
@@ -99,6 +99,7 @@ module Grape
|
|
99
99
|
method: :any,
|
100
100
|
path: path,
|
101
101
|
app: app,
|
102
|
+
route_options: { anchor: false },
|
102
103
|
forward_match: !app.respond_to?(:inheritable_setting),
|
103
104
|
for: self
|
104
105
|
)
|
@@ -118,6 +119,7 @@ module Grape
|
|
118
119
|
# end
|
119
120
|
# end
|
120
121
|
def route(methods, paths = ['/'], route_options = {}, &block)
|
122
|
+
methods = '*' if methods == :any
|
121
123
|
endpoint_options = {
|
122
124
|
method: methods,
|
123
125
|
path: paths,
|
@@ -198,6 +200,7 @@ module Grape
|
|
198
200
|
# @option options [Regexp] You may supply a regular expression that the declared parameter must meet.
|
199
201
|
def route_param(param, options = {}, &block)
|
200
202
|
options = options.dup
|
203
|
+
|
201
204
|
options[:requirements] = {
|
202
205
|
param.to_sym => options[:requirements]
|
203
206
|
} if options[:requirements].is_a?(Regexp)
|
@@ -205,6 +208,7 @@ module Grape
|
|
205
208
|
Grape::Validations::ParamsScope.new(api: self) do
|
206
209
|
requires param, type: options[:type]
|
207
210
|
end if options.key?(:type)
|
211
|
+
|
208
212
|
namespace(":#{param}", options, &block)
|
209
213
|
end
|
210
214
|
|
data/lib/grape/endpoint.rb
CHANGED
@@ -95,6 +95,8 @@ module Grape
|
|
95
95
|
@options[:route_options] ||= {}
|
96
96
|
|
97
97
|
@lazy_initialize_lock = Mutex.new
|
98
|
+
@lazy_initialized = nil
|
99
|
+
@block = nil
|
98
100
|
|
99
101
|
return unless block_given?
|
100
102
|
|
@@ -124,8 +126,8 @@ module Grape
|
|
124
126
|
[options[:method],
|
125
127
|
Namespace.joined_space(namespace_stackable(:namespace)),
|
126
128
|
(namespace_stackable(:mount_path) || []).join('/'),
|
127
|
-
options[:path].join('/')
|
128
|
-
|
129
|
+
options[:path].join('/')]
|
130
|
+
.join(' ')
|
129
131
|
end
|
130
132
|
|
131
133
|
def routes
|
@@ -248,21 +250,18 @@ module Grape
|
|
248
250
|
|
249
251
|
run_filters befores, :before
|
250
252
|
|
251
|
-
allowed_methods = env[Grape::Env::GRAPE_ALLOWED_METHODS]
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
253
|
+
if (allowed_methods = env[Grape::Env::GRAPE_ALLOWED_METHODS])
|
254
|
+
raise Grape::Exceptions::MethodNotAllowed, header.merge('Allow' => allowed_methods) unless options?
|
255
|
+
header 'Allow', allowed_methods
|
256
|
+
response_object = ''
|
257
|
+
status 204
|
258
|
+
else
|
259
|
+
run_filters before_validations, :before_validation
|
260
|
+
run_validators validations, request
|
261
|
+
run_filters after_validations, :after_validation
|
262
|
+
response_object = @block ? @block.call(self) : nil
|
263
|
+
end
|
257
264
|
|
258
|
-
response_object =
|
259
|
-
if options?
|
260
|
-
header 'Allow', allowed_methods
|
261
|
-
status 204
|
262
|
-
''
|
263
|
-
else
|
264
|
-
@block ? @block.call(self) : nil
|
265
|
-
end
|
266
265
|
run_filters afters, :after
|
267
266
|
cookies.write(header)
|
268
267
|
|