grape 1.0.0 → 1.0.1
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 +14 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +15 -15
- data/README.md +21 -2
- data/gemfiles/multi_json.gemfile +1 -1
- data/gemfiles/multi_xml.gemfile +1 -1
- data/gemfiles/rack_1.5.2.gemfile +1 -1
- data/gemfiles/rack_edge.gemfile +1 -1
- data/gemfiles/rails_3.gemfile +1 -1
- data/gemfiles/rails_4.gemfile +1 -1
- data/gemfiles/rails_5.gemfile +1 -1
- data/gemfiles/rails_edge.gemfile +1 -1
- data/lib/grape.rb +2 -0
- data/lib/grape/dsl/inside_route.rb +10 -2
- data/lib/grape/dsl/parameters.rb +2 -3
- data/lib/grape/dsl/settings.rb +14 -2
- data/lib/grape/error_formatter/json.rb +6 -2
- data/lib/grape/error_formatter/txt.rb +8 -3
- data/lib/grape/error_formatter/xml.rb +6 -2
- data/lib/grape/middleware/error.rb +17 -9
- data/lib/grape/middleware/formatter.rb +2 -2
- data/lib/grape/validations/params_scope.rb +11 -2
- data/lib/grape/validations/validators/as.rb +15 -0
- data/lib/grape/validations/validators/base.rb +1 -1
- data/lib/grape/validations/validators/values.rb +8 -3
- data/lib/grape/version.rb +1 -1
- data/pkg/grape-0.19.1.gem +0 -0
- data/spec/grape/api/inherited_helpers_spec.rb +114 -0
- data/spec/grape/api_spec.rb +2 -2
- data/spec/grape/dsl/helpers_spec.rb +19 -0
- data/spec/grape/dsl/parameters_spec.rb +4 -4
- data/spec/grape/middleware/exception_spec.rb +138 -44
- data/spec/grape/middleware/formatter_spec.rb +24 -0
- data/spec/grape/validations/params_scope_spec.rb +76 -0
- data/spec/grape/validations/validators/values_spec.rb +25 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f90062d2ff701a0d5a85be85c6658ba4f586849b
|
4
|
+
data.tar.gz: f43b46740851eb22a55e1fae15c8173875d5da9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3385b8c8c88db4eefd090030a8b73af0cd00b7b5ff5a247221a21fddfb3956d0268a7b2ed40ef74e222dee81fc4c5b3e99065501d5b044297e50edfc3c32054
|
7
|
+
data.tar.gz: 7cd058957cf3f3d8e770db3887a016e9a0dfa000985487973afb399203a1fda0a0a95a94e2e4a3541a2641008197d94c182ef4d92a85ffde0def8440099184bc
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
### 1.0.1 (9/8/2017)
|
2
|
+
|
3
|
+
#### Features
|
4
|
+
|
5
|
+
* [#1652](https://github.com/ruby-grape/grape/pull/1652): Add the original exception to the error_formatter the original exception - [@dcsg](https://github.com/dcsg).
|
6
|
+
* [#1665](https://github.com/ruby-grape/grape/pull/1665): Make helpers available in subclasses - [@pablonahuelgomez](https://github.com/pablonahuelgomez).
|
7
|
+
* [#1674](https://github.com/ruby-grape/grape/pull/1674): Add parameter alias (`as`) - [@glaucocustodio](https://github.com/glaucocustodio).
|
8
|
+
|
9
|
+
#### Fixes
|
10
|
+
|
11
|
+
* [#1652](https://github.com/ruby-grape/grape/pull/1652): Fix missing backtrace that was not being bubbled up to the `error_formatter` - [@dcsg](https://github.com/dcsg).
|
12
|
+
* [#1661](https://github.com/ruby-grape/grape/pull/1661): Handle deeply-nested dependencies correctly - [@rnubel](https://github.com/rnubel), [@jnardone](https://github.com/jnardone).
|
13
|
+
* [#1679](https://github.com/ruby-grape/grape/pull/1679): Treat StandardError from explicit values validator proc as false - [@jlfaber](https://github.com/jlfaber).
|
14
|
+
|
1
15
|
### 1.0.0 (7/3/2017)
|
2
16
|
|
3
17
|
#### Features
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
grape (1.0.
|
4
|
+
grape (1.0.1)
|
5
5
|
activesupport
|
6
6
|
builder
|
7
7
|
mustermann-grape (~> 1.0.0)
|
@@ -12,13 +12,13 @@ PATH
|
|
12
12
|
GEM
|
13
13
|
remote: https://rubygems.org/
|
14
14
|
specs:
|
15
|
-
activesupport (5.1.
|
15
|
+
activesupport (5.1.4)
|
16
16
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
17
17
|
i18n (~> 0.7)
|
18
18
|
minitest (~> 5.1)
|
19
19
|
tzinfo (~> 1.1)
|
20
|
-
addressable (2.5.
|
21
|
-
public_suffix (
|
20
|
+
addressable (2.5.2)
|
21
|
+
public_suffix (>= 2.0.2, < 4.0)
|
22
22
|
appraisal (2.2.0)
|
23
23
|
bundler
|
24
24
|
rake
|
@@ -35,7 +35,7 @@ GEM
|
|
35
35
|
cork
|
36
36
|
nap
|
37
37
|
open4 (~> 1.3)
|
38
|
-
coderay (1.1.
|
38
|
+
coderay (1.1.2)
|
39
39
|
coercible (1.0.0)
|
40
40
|
descendants_tracker (~> 0.0.1)
|
41
41
|
colored (1.2)
|
@@ -70,7 +70,7 @@ GEM
|
|
70
70
|
diff-lcs (1.3)
|
71
71
|
docile (1.1.5)
|
72
72
|
equalizer (0.0.11)
|
73
|
-
faraday (0.
|
73
|
+
faraday (0.13.1)
|
74
74
|
multipart-post (>= 1.2, < 3)
|
75
75
|
faraday-http-cache (1.3.1)
|
76
76
|
faraday (~> 0.8)
|
@@ -97,8 +97,8 @@ GEM
|
|
97
97
|
guard-rubocop (1.3.0)
|
98
98
|
guard (~> 2.0)
|
99
99
|
rubocop (~> 0.20)
|
100
|
-
hashie (3.5.
|
101
|
-
i18n (0.8.
|
100
|
+
hashie (3.5.6)
|
101
|
+
i18n (0.8.6)
|
102
102
|
ice_nine (0.11.2)
|
103
103
|
json (2.1.0)
|
104
104
|
kramdown (1.14.0)
|
@@ -112,10 +112,10 @@ GEM
|
|
112
112
|
mime-types (3.1)
|
113
113
|
mime-types-data (~> 3.2015)
|
114
114
|
mime-types-data (3.2016.0521)
|
115
|
-
minitest (5.10.
|
116
|
-
multi_json (1.12.
|
115
|
+
minitest (5.10.3)
|
116
|
+
multi_json (1.12.2)
|
117
117
|
multipart-post (2.0.0)
|
118
|
-
mustermann (1.0.
|
118
|
+
mustermann (1.0.1)
|
119
119
|
mustermann-grape (1.0.0)
|
120
120
|
mustermann (~> 1.0.0)
|
121
121
|
nap (1.1.0)
|
@@ -133,7 +133,7 @@ GEM
|
|
133
133
|
coderay (~> 1.1.0)
|
134
134
|
method_source (~> 0.8.1)
|
135
135
|
slop (~> 3.4)
|
136
|
-
public_suffix (
|
136
|
+
public_suffix (3.0.0)
|
137
137
|
rack (2.0.3)
|
138
138
|
rack-accept (0.4.5)
|
139
139
|
rack (>= 0.4)
|
@@ -180,7 +180,7 @@ GEM
|
|
180
180
|
docile (~> 1.1.0)
|
181
181
|
json (>= 1.8, < 3)
|
182
182
|
simplecov-html (~> 0.10.0)
|
183
|
-
simplecov-html (0.10.
|
183
|
+
simplecov-html (0.10.2)
|
184
184
|
slop (3.6.0)
|
185
185
|
term-ansicolor (1.6.0)
|
186
186
|
tins (~> 1.0)
|
@@ -217,7 +217,7 @@ DEPENDENCIES
|
|
217
217
|
maruku
|
218
218
|
mime-types
|
219
219
|
rack-jsonp
|
220
|
-
rack-test
|
220
|
+
rack-test (~> 0.6.3)
|
221
221
|
rake
|
222
222
|
redcarpet
|
223
223
|
rspec (~> 3.0)
|
@@ -226,4 +226,4 @@ DEPENDENCIES
|
|
226
226
|
yard
|
227
227
|
|
228
228
|
BUNDLED WITH
|
229
|
-
1.
|
229
|
+
1.15.3
|
data/README.md
CHANGED
@@ -42,6 +42,7 @@
|
|
42
42
|
- [Validation of Nested Parameters](#validation-of-nested-parameters)
|
43
43
|
- [Dependent Parameters](#dependent-parameters)
|
44
44
|
- [Group Options](#group-options)
|
45
|
+
- [Alias](#alias)
|
45
46
|
- [Built-in Validators](#built-in-validators)
|
46
47
|
- [Namespace Validation and Coercion](#namespace-validation-and-coercion)
|
47
48
|
- [Custom Validators](#custom-validators)
|
@@ -109,7 +110,7 @@ content negotiation, versioning and much more.
|
|
109
110
|
|
110
111
|
## Stable Release
|
111
112
|
|
112
|
-
You're reading the documentation for the stable release of Grape, 1.0.
|
113
|
+
You're reading the documentation for the stable release of Grape, 1.0.1.
|
113
114
|
Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
|
114
115
|
|
115
116
|
## Project Resources
|
@@ -1093,6 +1094,23 @@ params do
|
|
1093
1094
|
end
|
1094
1095
|
```
|
1095
1096
|
|
1097
|
+
### Alias
|
1098
|
+
|
1099
|
+
You can set an alias for parameters using `as`, which can be useful when refactoring existing APIs:
|
1100
|
+
|
1101
|
+
```ruby
|
1102
|
+
resource :users do
|
1103
|
+
params do
|
1104
|
+
requires :email_address, as: :email
|
1105
|
+
requires :password
|
1106
|
+
end
|
1107
|
+
post do
|
1108
|
+
User.create!(declared(params)) # User takes email and password
|
1109
|
+
end
|
1110
|
+
end
|
1111
|
+
```
|
1112
|
+
|
1113
|
+
The value passed to `as` will be the key when calling `params` or `declared(params)`.
|
1096
1114
|
|
1097
1115
|
### Built-in Validators
|
1098
1116
|
|
@@ -1160,7 +1178,8 @@ end
|
|
1160
1178
|
|
1161
1179
|
Alternatively, a Proc with arity one (i.e. taking one argument) can be used to explicitly validate
|
1162
1180
|
each parameter value. In that case, the Proc is expected to return a truthy value if the parameter
|
1163
|
-
value is valid.
|
1181
|
+
value is valid. The parameter will be considered invalid if the Proc returns a falsy value or if it
|
1182
|
+
raises a StandardError.
|
1164
1183
|
|
1165
1184
|
```ruby
|
1166
1185
|
params do
|
data/gemfiles/multi_json.gemfile
CHANGED
data/gemfiles/multi_xml.gemfile
CHANGED
data/gemfiles/rack_1.5.2.gemfile
CHANGED
data/gemfiles/rack_edge.gemfile
CHANGED
data/gemfiles/rails_3.gemfile
CHANGED
data/gemfiles/rails_4.gemfile
CHANGED
data/gemfiles/rails_5.gemfile
CHANGED
data/gemfiles/rails_edge.gemfile
CHANGED
data/lib/grape.rb
CHANGED
@@ -13,6 +13,7 @@ require 'active_support/core_ext/array/wrap'
|
|
13
13
|
require 'active_support/core_ext/hash/deep_merge'
|
14
14
|
require 'active_support/core_ext/hash/reverse_merge'
|
15
15
|
require 'active_support/core_ext/hash/except'
|
16
|
+
require 'active_support/core_ext/hash/slice'
|
16
17
|
require 'active_support/core_ext/hash/conversions'
|
17
18
|
require 'active_support/dependencies/autoload'
|
18
19
|
require 'active_support/notifications'
|
@@ -198,6 +199,7 @@ require 'grape/util/content_types'
|
|
198
199
|
require 'grape/validations/validators/base'
|
199
200
|
require 'grape/validations/attributes_iterator'
|
200
201
|
require 'grape/validations/validators/allow_blank'
|
202
|
+
require 'grape/validations/validators/as'
|
201
203
|
require 'grape/validations/validators/at_least_one_of'
|
202
204
|
require 'grape/validations/validators/coerce'
|
203
205
|
require 'grape/validations/validators/default'
|
@@ -50,8 +50,16 @@ module Grape
|
|
50
50
|
# If it is not a Hash then it does not have children.
|
51
51
|
# Find its value or set it to nil.
|
52
52
|
if !declared_param.is_a?(Hash)
|
53
|
-
|
54
|
-
|
53
|
+
has_alias = route_setting(:aliased_params) && route_setting(:aliased_params).find { |current| current[declared_param] }
|
54
|
+
param_alias = has_alias[declared_param] if has_alias
|
55
|
+
|
56
|
+
next unless options[:include_missing] || passed_params.key?(declared_param) || param_alias
|
57
|
+
|
58
|
+
if param_alias
|
59
|
+
memo[optioned_param_key(param_alias, options)] = passed_params[param_alias]
|
60
|
+
else
|
61
|
+
memo[optioned_param_key(declared_param, options)] = passed_params[declared_param]
|
62
|
+
end
|
55
63
|
else
|
56
64
|
declared_param.each_pair do |declared_parent_param, declared_children_params|
|
57
65
|
next unless options[:include_missing] || passed_params.key?(declared_parent_param)
|
data/lib/grape/dsl/parameters.rb
CHANGED
@@ -131,8 +131,7 @@ module Grape
|
|
131
131
|
require_required_and_optional_fields(attrs.first, opts)
|
132
132
|
else
|
133
133
|
validate_attributes(attrs, opts, &block)
|
134
|
-
|
135
|
-
block_given? ? new_scope(orig_attrs, &block) : push_declared_params(attrs)
|
134
|
+
block_given? ? new_scope(orig_attrs, &block) : push_declared_params(attrs, opts.slice(:as))
|
136
135
|
end
|
137
136
|
end
|
138
137
|
|
@@ -158,7 +157,7 @@ module Grape
|
|
158
157
|
else
|
159
158
|
validate_attributes(attrs, opts, &block)
|
160
159
|
|
161
|
-
block_given? ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs)
|
160
|
+
block_given? ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, opts.slice(:as))
|
162
161
|
end
|
163
162
|
end
|
164
163
|
|
data/lib/grape/dsl/settings.rb
CHANGED
@@ -2,7 +2,7 @@ require 'active_support/concern'
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
module DSL
|
5
|
-
# Keeps track of settings (
|
5
|
+
# Keeps track of settings (implemented as key-value pairs, grouped by
|
6
6
|
# types), in two contexts: top-level settings which apply globally no
|
7
7
|
# matter where they're defined, and inheritable settings which apply only
|
8
8
|
# in the current scope and scopes nested under it.
|
@@ -13,7 +13,7 @@ module Grape
|
|
13
13
|
|
14
14
|
# Fetch our top-level settings, which apply to all endpoints in the API.
|
15
15
|
def top_level_setting
|
16
|
-
@top_level_setting ||=
|
16
|
+
@top_level_setting ||= build_top_level_setting
|
17
17
|
end
|
18
18
|
|
19
19
|
# Fetch our current inheritable settings, which are inherited by
|
@@ -162,6 +162,18 @@ module Grape
|
|
162
162
|
|
163
163
|
result
|
164
164
|
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
# Builds the current class :inheritable_setting. If available, it returns the superclass's :inheritable_setting.
|
169
|
+
# Otherwise, a clean :inheritable_setting is returned.
|
170
|
+
def build_top_level_setting
|
171
|
+
if defined?(superclass) && superclass.respond_to?(:inheritable_setting) && superclass != Grape::API
|
172
|
+
superclass.inheritable_setting
|
173
|
+
else
|
174
|
+
Grape::Util::InheritableSetting.new
|
175
|
+
end
|
176
|
+
end
|
165
177
|
end
|
166
178
|
end
|
167
179
|
end
|
@@ -4,12 +4,16 @@ module Grape
|
|
4
4
|
extend Base
|
5
5
|
|
6
6
|
class << self
|
7
|
-
def call(message, backtrace, options = {}, env = nil)
|
7
|
+
def call(message, backtrace, options = {}, env = nil, original_exception = nil)
|
8
8
|
result = wrap_message(present(message, env))
|
9
9
|
|
10
|
-
|
10
|
+
rescue_options = options[:rescue_options] || {}
|
11
|
+
if rescue_options[:backtrace] && backtrace && !backtrace.empty?
|
11
12
|
result = result.merge(backtrace: backtrace)
|
12
13
|
end
|
14
|
+
if rescue_options[:original_exception] && original_exception
|
15
|
+
result = result.merge(original_exception: original_exception.inspect)
|
16
|
+
end
|
13
17
|
::Grape::Json.dump(result)
|
14
18
|
end
|
15
19
|
|
@@ -4,14 +4,19 @@ module Grape
|
|
4
4
|
extend Base
|
5
5
|
|
6
6
|
class << self
|
7
|
-
def call(message, backtrace, options = {}, env = nil)
|
7
|
+
def call(message, backtrace, options = {}, env = nil, original_exception = nil)
|
8
8
|
message = present(message, env)
|
9
9
|
|
10
10
|
result = message.is_a?(Hash) ? ::Grape::Json.dump(message) : message
|
11
|
-
|
12
|
-
|
11
|
+
rescue_options = options[:rescue_options] || {}
|
12
|
+
if rescue_options[:backtrace] && backtrace && !backtrace.empty?
|
13
|
+
result += "\r\n backtrace:"
|
13
14
|
result += backtrace.join("\r\n ")
|
14
15
|
end
|
16
|
+
if rescue_options[:original_exception] && original_exception
|
17
|
+
result += "\r\n original exception:"
|
18
|
+
result += "\r\n #{original_exception.inspect}"
|
19
|
+
end
|
15
20
|
result
|
16
21
|
end
|
17
22
|
end
|
@@ -4,13 +4,17 @@ module Grape
|
|
4
4
|
extend Base
|
5
5
|
|
6
6
|
class << self
|
7
|
-
def call(message, backtrace, options = {}, env = nil)
|
7
|
+
def call(message, backtrace, options = {}, env = nil, original_exception = nil)
|
8
8
|
message = present(message, env)
|
9
9
|
|
10
10
|
result = message.is_a?(Hash) ? message : { message: message }
|
11
|
-
|
11
|
+
rescue_options = options[:rescue_options] || {}
|
12
|
+
if rescue_options[:backtrace] && backtrace && !backtrace.empty?
|
12
13
|
result = result.merge(backtrace: backtrace)
|
13
14
|
end
|
15
|
+
if rescue_options[:original_exception] && original_exception
|
16
|
+
result = result.merge(original_exception: original_exception.inspect)
|
17
|
+
end
|
14
18
|
result.respond_to?(:to_xml) ? result.to_xml(root: :error) : result.to_s
|
15
19
|
end
|
16
20
|
end
|
@@ -14,7 +14,10 @@ module Grape
|
|
14
14
|
rescue_all: false, # true to rescue all exceptions
|
15
15
|
rescue_grape_exceptions: false,
|
16
16
|
rescue_subclasses: true, # rescue subclasses of exceptions listed
|
17
|
-
rescue_options: {
|
17
|
+
rescue_options: {
|
18
|
+
backtrace: false, # true to display backtrace, true to let Grape handle Grape::Exceptions
|
19
|
+
original_exception: false, # true to display exception
|
20
|
+
},
|
18
21
|
rescue_handlers: {}, # rescue handler blocks
|
19
22
|
base_only_rescue_handlers: {}, # rescue handler blocks rescuing only the base class
|
20
23
|
all_rescue_handler: nil # rescue handler block to rescue from all exceptions
|
@@ -77,13 +80,13 @@ module Grape
|
|
77
80
|
end
|
78
81
|
end
|
79
82
|
|
80
|
-
def error!(message, status = options[:default_status], headers = {}, backtrace = [])
|
83
|
+
def error!(message, status = options[:default_status], headers = {}, backtrace = [], original_exception = nil)
|
81
84
|
headers = headers.reverse_merge(Grape::Http::Headers::CONTENT_TYPE => content_type)
|
82
|
-
rack_response(format_message(message, backtrace), status, headers)
|
85
|
+
rack_response(format_message(message, backtrace, original_exception), status, headers)
|
83
86
|
end
|
84
87
|
|
85
88
|
def handle_error(e)
|
86
|
-
error_response(message: e.message, backtrace: e.backtrace)
|
89
|
+
error_response(message: e.message, backtrace: e.backtrace, original_exception: e)
|
87
90
|
end
|
88
91
|
|
89
92
|
# TODO: This method is deprecated. Refactor out.
|
@@ -92,19 +95,24 @@ module Grape
|
|
92
95
|
message = error[:message] || options[:default_message]
|
93
96
|
headers = { Grape::Http::Headers::CONTENT_TYPE => content_type }
|
94
97
|
headers.merge!(error[:headers]) if error[:headers].is_a?(Hash)
|
95
|
-
backtrace = error[:backtrace] || []
|
96
|
-
|
98
|
+
backtrace = error[:backtrace] || error[:original_exception] && error[:original_exception].backtrace || []
|
99
|
+
original_exception = error.is_a?(Exception) ? error : error[:original_exception] || nil
|
100
|
+
rack_response(format_message(message, backtrace, original_exception), status, headers)
|
97
101
|
end
|
98
102
|
|
99
103
|
def rack_response(message, status = options[:default_status], headers = { Grape::Http::Headers::CONTENT_TYPE => content_type })
|
100
104
|
Rack::Response.new([message], status, headers).finish
|
101
105
|
end
|
102
106
|
|
103
|
-
def format_message(message, backtrace)
|
107
|
+
def format_message(message, backtrace, original_exception = nil)
|
104
108
|
format = env[Grape::Env::API_FORMAT] || options[:format]
|
105
109
|
formatter = Grape::ErrorFormatter.formatter_for(format, options)
|
106
|
-
throw :error,
|
107
|
-
|
110
|
+
throw :error,
|
111
|
+
status: 406,
|
112
|
+
message: "The requested format '#{format}' is not supported.",
|
113
|
+
backtrace: backtrace,
|
114
|
+
original_exception: original_exception unless formatter
|
115
|
+
formatter.call(message, backtrace, options, env, original_exception)
|
108
116
|
end
|
109
117
|
|
110
118
|
private
|