grape 1.6.0 → 1.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/CONTRIBUTING.md +2 -1
- data/README.md +9 -1
- data/UPGRADING.md +4 -4
- data/lib/grape/api.rb +12 -0
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +1 -1
- data/lib/grape/middleware/auth/dsl.rb +7 -1
- data/lib/grape/middleware/base.rb +1 -1
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/validators/all_or_none.rb +7 -5
- data/lib/grape/validations/validators/allow_blank.rb +9 -7
- data/lib/grape/validations/validators/as.rb +7 -5
- data/lib/grape/validations/validators/at_least_one_of.rb +6 -4
- data/lib/grape/validations/validators/base.rb +73 -71
- data/lib/grape/validations/validators/coerce.rb +63 -75
- data/lib/grape/validations/validators/default.rb +36 -34
- data/lib/grape/validations/validators/exactly_one_of.rb +8 -6
- data/lib/grape/validations/validators/except_values.rb +13 -11
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -22
- data/lib/grape/validations/validators/mutual_exclusion.rb +7 -5
- data/lib/grape/validations/validators/presence.rb +6 -4
- data/lib/grape/validations/validators/regexp.rb +7 -5
- data/lib/grape/validations/validators/same_as.rb +17 -15
- data/lib/grape/validations/validators/values.rb +59 -57
- data/lib/grape/validations.rb +6 -0
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +2 -0
- data/spec/grape/api/custom_validations_spec.rb +77 -46
- data/spec/grape/api/deeply_included_options_spec.rb +3 -3
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +1 -1
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
- data/spec/grape/api_remount_spec.rb +16 -15
- data/spec/grape/api_spec.rb +317 -193
- data/spec/grape/dsl/callbacks_spec.rb +1 -0
- data/spec/grape/dsl/headers_spec.rb +39 -9
- data/spec/grape/dsl/helpers_spec.rb +3 -2
- data/spec/grape/dsl/inside_route_spec.rb +6 -4
- data/spec/grape/dsl/logger_spec.rb +16 -18
- data/spec/grape/dsl/middleware_spec.rb +1 -0
- data/spec/grape/dsl/parameters_spec.rb +1 -0
- data/spec/grape/dsl/request_response_spec.rb +1 -0
- data/spec/grape/dsl/routing_spec.rb +9 -6
- data/spec/grape/endpoint/declared_spec.rb +12 -12
- data/spec/grape/endpoint_spec.rb +59 -50
- data/spec/grape/entity_spec.rb +13 -13
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
- data/spec/grape/exceptions/validation_spec.rb +5 -3
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
- data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
- data/spec/grape/loading_spec.rb +8 -8
- data/spec/grape/middleware/auth/dsl_spec.rb +14 -5
- data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
- data/spec/grape/middleware/base_spec.rb +24 -15
- data/spec/grape/middleware/error_spec.rb +1 -0
- data/spec/grape/middleware/exception_spec.rb +111 -161
- data/spec/grape/middleware/formatter_spec.rb +25 -4
- data/spec/grape/middleware/globals_spec.rb +7 -4
- data/spec/grape/middleware/stack_spec.rb +11 -11
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
- data/spec/grape/middleware/versioner/header_spec.rb +14 -13
- data/spec/grape/middleware/versioner/param_spec.rb +7 -1
- data/spec/grape/middleware/versioner/path_spec.rb +5 -1
- data/spec/grape/middleware/versioner_spec.rb +1 -1
- data/spec/grape/parser_spec.rb +4 -0
- data/spec/grape/path_spec.rb +52 -52
- data/spec/grape/presenters/presenter_spec.rb +7 -6
- data/spec/grape/request_spec.rb +6 -4
- data/spec/grape/util/inheritable_setting_spec.rb +7 -7
- data/spec/grape/util/inheritable_values_spec.rb +3 -2
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
- data/spec/grape/util/stackable_values_spec.rb +7 -5
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
- data/spec/grape/validations/params_scope_spec.rb +9 -7
- data/spec/grape/validations/single_attribute_iterator_spec.rb +1 -0
- data/spec/grape/validations/types/primitive_coercer_spec.rb +2 -2
- data/spec/grape/validations/types_spec.rb +8 -8
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
- data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
- data/spec/grape/validations/validators/coerce_spec.rb +10 -12
- data/spec/grape/validations/validators/default_spec.rb +72 -78
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
- data/spec/grape/validations/validators/except_values_spec.rb +1 -1
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
- data/spec/grape/validations/validators/presence_spec.rb +16 -1
- data/spec/grape/validations/validators/regexp_spec.rb +25 -31
- data/spec/grape/validations/validators/same_as_spec.rb +14 -20
- data/spec/grape/validations/validators/values_spec.rb +172 -171
- data/spec/grape/validations_spec.rb +45 -16
- data/spec/integration/eager_load/eager_load_spec.rb +2 -2
- data/spec/integration/multi_json/json_spec.rb +1 -1
- data/spec/integration/multi_xml/xml_spec.rb +1 -1
- data/spec/shared/versioning_examples.rb +10 -7
- data/spec/spec_helper.rb +11 -1
- metadata +102 -102
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d182a6dfa2a571345d24a6a2b7286b4a2b34eeedc6570334ba2259fdda59faac
|
4
|
+
data.tar.gz: c365091e871e7ad78dd46dc0aab52cdd41d1e5ddb5a46503fcf0020af45f4324
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 539fdf761a5058dfcb3bab993a7fac3c7223ec06e0b828e102cb52095ac79f63668ebab1c1c4b47bf16984990c94f9a291537e7b2a1359626736b7abdd2c34ec
|
7
|
+
data.tar.gz: 2b30d941ab114aab53c4f4630742adedd037856ecc63b65f87b0df506349a13eed092964d9f53c003774006e74b9800043178b2ad2e6c55b0d5d42f6039a7e71
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
### 1.6.2 (2021/12/30)
|
2
|
+
|
3
|
+
#### Features
|
4
|
+
|
5
|
+
#### Fixes
|
6
|
+
|
7
|
+
* [#2219](https://github.com/ruby-grape/grape/pull/2219): Revert the changes for autoloading provided in 1.6.1 - [@dm1try](https://github.com/dm1try).
|
8
|
+
|
9
|
+
### 1.6.1 (2021/12/28)
|
10
|
+
|
11
|
+
#### Features
|
12
|
+
|
13
|
+
* [#2196](https://github.com/ruby-grape/grape/pull/2196): Add support for `passwords_hashed` param for `digest_auth` - [@lHydra](https://github.com/lhydra).
|
14
|
+
* [#2208](https://github.com/ruby-grape/grape/pull/2208): Added Rails 7 support - [@ericproulx](https://github.com/ericproulx).
|
15
|
+
|
16
|
+
#### Fixes
|
17
|
+
|
18
|
+
* [#2206](https://github.com/ruby-grape/grape/pull/2206): Require main active_support lib before any of its extension definitions - [@annih](https://github.com/Annih).
|
19
|
+
* [#2193](https://github.com/ruby-grape/grape/pull/2193): Fixed the broken ruby-head NoMethodError spec - [@Jack12816](https://github.com/Jack12816).
|
20
|
+
* [#2192](https://github.com/ruby-grape/grape/pull/2192): Memoize the result of Grape::Middleware::Base#response - [@Jack12816](https://github.com/Jack12816).
|
21
|
+
* [#2200](https://github.com/ruby-grape/grape/pull/2200): Add validators module to all validators - [@ericproulx](https://github.com/ericproulx).
|
22
|
+
* [#2202](https://github.com/ruby-grape/grape/pull/2202): Fix random mock spec error - [@ericproulx](https://github.com/ericproulx).
|
23
|
+
* [#2203](https://github.com/ruby-grape/grape/pull/2203): Add rubocop-rspec - [@ericproulx](https://github.com/ericproulx).
|
24
|
+
* [#2207](https://github.com/ruby-grape/grape/pull/2207): Autoload Validations/Validators - [@ericproulx](https://github.com/ericproulx).
|
25
|
+
* [#2209](https://github.com/ruby-grape/grape/pull/2209): Autoload Validations/Types - [@ericproulx](https://github.com/ericproulx).
|
26
|
+
|
1
27
|
### 1.6.0 (2021/10/04)
|
2
28
|
|
3
29
|
#### Features
|
data/CONTRIBUTING.md
CHANGED
@@ -35,6 +35,7 @@ bundle exec rake
|
|
35
35
|
Run tests against all supported versions of Rails.
|
36
36
|
|
37
37
|
```
|
38
|
+
gem install appraisal
|
38
39
|
appraisal install
|
39
40
|
appraisal rake spec
|
40
41
|
```
|
@@ -118,7 +119,7 @@ Go back to your pull request after a few minutes and see whether it passed muste
|
|
118
119
|
|
119
120
|
#### Be Patient
|
120
121
|
|
121
|
-
It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang
|
122
|
+
It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang in there!
|
122
123
|
|
123
124
|
#### Thank You
|
124
125
|
|
data/README.md
CHANGED
@@ -158,7 +158,7 @@ content negotiation, versioning and much more.
|
|
158
158
|
|
159
159
|
## Stable Release
|
160
160
|
|
161
|
-
You're reading the documentation for the stable release of Grape, **1.6.
|
161
|
+
You're reading the documentation for the stable release of Grape, **1.6.2**.
|
162
162
|
Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
|
163
163
|
|
164
164
|
## Project Resources
|
@@ -3296,12 +3296,20 @@ http_basic do |username, password|
|
|
3296
3296
|
end
|
3297
3297
|
```
|
3298
3298
|
|
3299
|
+
Digest auth supports clear-text passwords and password hashes.
|
3300
|
+
|
3299
3301
|
```ruby
|
3300
3302
|
http_digest({ realm: 'Test Api', opaque: 'app secret' }) do |username|
|
3301
3303
|
# lookup the user's password here
|
3302
3304
|
end
|
3303
3305
|
```
|
3304
3306
|
|
3307
|
+
```ruby
|
3308
|
+
http_digest(realm: { realm: 'Test Api', opaque: 'app secret', passwords_hashed: true }) do |username|
|
3309
|
+
# lookup the user's password hash here
|
3310
|
+
end
|
3311
|
+
```
|
3312
|
+
|
3305
3313
|
### Register custom middleware for authentication
|
3306
3314
|
|
3307
3315
|
Grape can use custom Middleware for authentication. How to implement these
|
data/UPGRADING.md
CHANGED
@@ -27,7 +27,7 @@ declared(params, include_missing: false)
|
|
27
27
|
# actual => { b: '5' } (uncasted, unvalidated, <= 1.5.3)
|
28
28
|
```
|
29
29
|
|
30
|
-
Another implication of this change is the dependent parameter resolution. Prior to 1.6.0 the following code produced
|
30
|
+
Another implication of this change is the dependent parameter resolution. Prior to 1.6.0 the following code produced a `Grape::Exceptions::UnknownParameter` because `:a` was replaced by `:b`:
|
31
31
|
|
32
32
|
```ruby
|
33
33
|
params do
|
@@ -47,7 +47,7 @@ See [#2189](https://github.com/ruby-grape/grape/pull/2189) for more information.
|
|
47
47
|
#### Nil value and coercion
|
48
48
|
|
49
49
|
Prior to 1.2.5 version passing a `nil` value for a parameter with a custom coercer would invoke the coercer, and not passing a parameter would not invoke it.
|
50
|
-
This behavior was not tested or documented. Version 1.3.0 quietly changed this behavior, in
|
50
|
+
This behavior was not tested or documented. Version 1.3.0 quietly changed this behavior, in that `nil` values skipped the coercion. Version 1.5.3 fixes and documents this as follows:
|
51
51
|
|
52
52
|
```ruby
|
53
53
|
class Api < Grape::API
|
@@ -197,13 +197,13 @@ end
|
|
197
197
|
|
198
198
|
#### Nil values for structures
|
199
199
|
|
200
|
-
Nil values always been a special case when dealing with types especially with the following structures:
|
200
|
+
Nil values have always been a special case when dealing with types, especially with the following structures:
|
201
201
|
|
202
202
|
- Array
|
203
203
|
- Hash
|
204
204
|
- Set
|
205
205
|
|
206
|
-
The behavior for these structures has
|
206
|
+
The behavior for these structures has changed throughout the latest releases. For example:
|
207
207
|
|
208
208
|
```ruby
|
209
209
|
class Api < Grape::API
|
data/lib/grape/api.rb
CHANGED
@@ -10,6 +10,18 @@ module Grape
|
|
10
10
|
# Class methods that we want to call on the API rather than on the API object
|
11
11
|
NON_OVERRIDABLE = (Class.new.methods + %i[call call! configuration compile! inherited]).freeze
|
12
12
|
|
13
|
+
class Boolean
|
14
|
+
def self.build(val)
|
15
|
+
return nil if val != true && val != false
|
16
|
+
|
17
|
+
new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Instance
|
22
|
+
Boolean = Grape::API::Boolean
|
23
|
+
end
|
24
|
+
|
13
25
|
class << self
|
14
26
|
attr_accessor :base_instance, :instances
|
15
27
|
|
data/lib/grape/dsl/headers.rb
CHANGED
@@ -3,8 +3,11 @@
|
|
3
3
|
module Grape
|
4
4
|
module DSL
|
5
5
|
module Headers
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# This method has four responsibilities:
|
7
|
+
# 1. Set a specifc header value by key
|
8
|
+
# 2. Retrieve a specifc header value by key
|
9
|
+
# 3. Retrieve all headers that have been set
|
10
|
+
# 4. Delete a specifc header key-value pair
|
8
11
|
def header(key = nil, val = nil)
|
9
12
|
if key
|
10
13
|
val ? header[key.to_s] = val : header.delete(key.to_s)
|
data/lib/grape/dsl/helpers.rb
CHANGED
@@ -32,7 +32,13 @@ module Grape
|
|
32
32
|
|
33
33
|
def http_digest(options = {}, &block)
|
34
34
|
options[:realm] ||= 'API Authorization'
|
35
|
-
|
35
|
+
|
36
|
+
if options[:realm].respond_to?(:values_at)
|
37
|
+
options[:realm][:opaque] ||= 'secret'
|
38
|
+
else
|
39
|
+
options[:opaque] ||= 'secret'
|
40
|
+
end
|
41
|
+
|
36
42
|
auth :http_digest, options, &block
|
37
43
|
end
|
38
44
|
end
|
@@ -60,7 +60,7 @@ module Grape
|
|
60
60
|
def response
|
61
61
|
return @app_response if @app_response.is_a?(Rack::Response)
|
62
62
|
|
63
|
-
Rack::Response.new(@app_response[2], @app_response[0], @app_response[1])
|
63
|
+
@app_response = Rack::Response.new(@app_response[2], @app_response[0], @app_response[1])
|
64
64
|
end
|
65
65
|
|
66
66
|
def content_type_for(format)
|
@@ -4,12 +4,14 @@ require 'grape/validations/validators/multiple_params_base'
|
|
4
4
|
|
5
5
|
module Grape
|
6
6
|
module Validations
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
module Validators
|
8
|
+
class AllOrNoneOfValidator < MultipleParamsBase
|
9
|
+
def validate_params!(params)
|
10
|
+
keys = keys_in_common(params)
|
11
|
+
return if keys.empty? || keys.length == all_keys.length
|
11
12
|
|
12
|
-
|
13
|
+
raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:all_or_none))
|
14
|
+
end
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -2,16 +2,18 @@
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
module Validations
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
module Validators
|
6
|
+
class AllowBlankValidator < Base
|
7
|
+
def validate_param!(attr_name, params)
|
8
|
+
return if (options_key?(:value) ? @option[:value] : @option) || !params.is_a?(Hash)
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
value = params[attr_name]
|
11
|
+
value = value.strip if value.respond_to?(:strip)
|
11
12
|
|
12
|
-
|
13
|
+
return if value == false || value.present?
|
13
14
|
|
14
|
-
|
15
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:blank))
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
module Validations
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
module Validators
|
6
|
+
class AsValidator < Base
|
7
|
+
# We use a validator for renaming parameters. This is just a marker for
|
8
|
+
# the parameter scope to handle the renaming. No actual validation
|
9
|
+
# happens here.
|
10
|
+
def validate_param!(*); end
|
11
|
+
end
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -4,11 +4,13 @@ require 'grape/validations/validators/multiple_params_base'
|
|
4
4
|
|
5
5
|
module Grape
|
6
6
|
module Validations
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
module Validators
|
8
|
+
class AtLeastOneOfValidator < MultipleParamsBase
|
9
|
+
def validate_params!(params)
|
10
|
+
return unless keys_in_common(params).empty?
|
10
11
|
|
11
|
-
|
12
|
+
raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:at_least_one))
|
13
|
+
end
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
@@ -2,91 +2,93 @@
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
module Validations
|
5
|
-
|
6
|
-
|
5
|
+
module Validators
|
6
|
+
class Base
|
7
|
+
attr_reader :attrs
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
9
|
+
# Creates a new Validator from options specified
|
10
|
+
# by a +requires+ or +optional+ directive during
|
11
|
+
# parameter definition.
|
12
|
+
# @param attrs [Array] names of attributes to which the Validator applies
|
13
|
+
# @param options [Object] implementation-dependent Validator options
|
14
|
+
# @param required [Boolean] attribute(s) are required or optional
|
15
|
+
# @param scope [ParamsScope] parent scope for this Validator
|
16
|
+
# @param opts [Array] additional validation options
|
17
|
+
def initialize(attrs, options, required, scope, *opts)
|
18
|
+
@attrs = Array(attrs)
|
19
|
+
@option = options
|
20
|
+
@required = required
|
21
|
+
@scope = scope
|
22
|
+
opts = opts.any? ? opts.shift : {}
|
23
|
+
@fail_fast = opts.fetch(:fail_fast, false)
|
24
|
+
@allow_blank = opts.fetch(:allow_blank, false)
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
# Validates a given request.
|
28
|
+
# @note Override #validate! unless you need to access the entire request.
|
29
|
+
# @param request [Grape::Request] the request currently being handled
|
30
|
+
# @raise [Grape::Exceptions::Validation] if validation failed
|
31
|
+
# @return [void]
|
32
|
+
def validate(request)
|
33
|
+
return unless @scope.should_validate?(request.params)
|
33
34
|
|
34
|
-
|
35
|
-
|
35
|
+
validate!(request.params)
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
# Validates a given parameter hash.
|
39
|
+
# @note Override #validate if you need to access the entire request.
|
40
|
+
# @param params [Hash] parameters to validate
|
41
|
+
# @raise [Grape::Exceptions::Validation] if validation failed
|
42
|
+
# @return [void]
|
43
|
+
def validate!(params)
|
44
|
+
attributes = SingleAttributeIterator.new(self, @scope, params)
|
45
|
+
# we collect errors inside array because
|
46
|
+
# there may be more than one error per field
|
47
|
+
array_errors = []
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
attributes.each do |val, attr_name, empty_val, skip_value|
|
50
|
+
next if skip_value
|
51
|
+
next if !@scope.required? && empty_val
|
52
|
+
next unless @scope.meets_dependency?(val, params)
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
begin
|
55
|
+
validate_param!(attr_name, val) if @required || (val.respond_to?(:key?) && val.key?(attr_name))
|
56
|
+
rescue Grape::Exceptions::Validation => e
|
57
|
+
array_errors << e
|
58
|
+
end
|
57
59
|
end
|
58
|
-
end
|
59
60
|
|
60
|
-
|
61
|
-
|
61
|
+
raise Grape::Exceptions::ValidationArrayErrors.new(array_errors) if array_errors.any?
|
62
|
+
end
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
64
|
+
def self.convert_to_short_name(klass)
|
65
|
+
ret = klass.name.gsub(/::/, '/')
|
66
|
+
ret.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
67
|
+
ret.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
68
|
+
ret.tr!('-', '_')
|
69
|
+
ret.downcase!
|
70
|
+
File.basename(ret, '_validator')
|
71
|
+
end
|
71
72
|
|
72
|
-
|
73
|
-
|
73
|
+
def self.inherited(klass)
|
74
|
+
return unless klass.name.present?
|
74
75
|
|
75
|
-
|
76
|
-
|
76
|
+
Validations.register_validator(convert_to_short_name(klass), klass)
|
77
|
+
end
|
77
78
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
79
|
+
def message(default_key = nil)
|
80
|
+
options = instance_variable_get(:@option)
|
81
|
+
options_key?(:message) ? options[:message] : default_key
|
82
|
+
end
|
82
83
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
def options_key?(key, options = nil)
|
85
|
+
options = instance_variable_get(:@option) if options.nil?
|
86
|
+
options.respond_to?(:key?) && options.key?(key) && !options[key].nil?
|
87
|
+
end
|
87
88
|
|
88
|
-
|
89
|
-
|
89
|
+
def fail_fast?
|
90
|
+
@fail_fast
|
91
|
+
end
|
90
92
|
end
|
91
93
|
end
|
92
94
|
end
|
@@ -1,86 +1,74 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Grape
|
4
|
-
class API
|
5
|
-
class Boolean
|
6
|
-
def self.build(val)
|
7
|
-
return nil if val != true && val != false
|
8
|
-
|
9
|
-
new
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class Instance
|
14
|
-
Boolean = Grape::API::Boolean
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
4
|
module Validations
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
5
|
+
module Validators
|
6
|
+
class CoerceValidator < Base
|
7
|
+
def initialize(attrs, options, required, scope, **opts)
|
8
|
+
super
|
9
|
+
|
10
|
+
@converter = if type.is_a?(Grape::Validations::Types::VariantCollectionCoercer)
|
11
|
+
type
|
12
|
+
else
|
13
|
+
Types.build_coercer(type, method: @option[:method])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_param!(attr_name, params)
|
18
|
+
raise validation_exception(attr_name) unless params.is_a? Hash
|
19
|
+
|
20
|
+
new_value = coerce_value(params[attr_name])
|
21
|
+
|
22
|
+
raise validation_exception(attr_name, new_value.message) unless valid_type?(new_value)
|
23
|
+
|
24
|
+
# Don't assign a value if it is identical. It fixes a problem with Hashie::Mash
|
25
|
+
# which looses wrappers for hashes and arrays after reassigning values
|
26
|
+
#
|
27
|
+
# h = Hashie::Mash.new(list: [1, 2, 3, 4])
|
28
|
+
# => #<Hashie::Mash list=#<Hashie::Array [1, 2, 3, 4]>>
|
29
|
+
# list = h.list
|
30
|
+
# h[:list] = list
|
31
|
+
# h
|
32
|
+
# => #<Hashie::Mash list=[1, 2, 3, 4]>
|
33
|
+
return if params[attr_name].instance_of?(new_value.class) && params[attr_name] == new_value
|
34
|
+
|
35
|
+
params[attr_name] = new_value
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# @!attribute [r] converter
|
41
|
+
# Object that will be used for parameter coercion and type checking.
|
39
42
|
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
|
44
|
-
# h
|
45
|
-
# => #<Hashie::Mash list=[1, 2, 3, 4]>
|
46
|
-
return if params[attr_name].instance_of?(new_value.class) && params[attr_name] == new_value
|
47
|
-
|
48
|
-
params[attr_name] = new_value
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
# @!attribute [r] converter
|
54
|
-
# Object that will be used for parameter coercion and type checking.
|
55
|
-
#
|
56
|
-
# See {Types.build_coercer}
|
57
|
-
#
|
58
|
-
# @return [Object]
|
59
|
-
attr_reader :converter
|
60
|
-
|
61
|
-
def valid_type?(val)
|
62
|
-
!val.is_a?(Types::InvalidValue)
|
63
|
-
end
|
43
|
+
# See {Types.build_coercer}
|
44
|
+
#
|
45
|
+
# @return [Object]
|
46
|
+
attr_reader :converter
|
64
47
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
rescue StandardError
|
69
|
-
Types::InvalidValue.new
|
70
|
-
end
|
48
|
+
def valid_type?(val)
|
49
|
+
!val.is_a?(Types::InvalidValue)
|
50
|
+
end
|
71
51
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
52
|
+
def coerce_value(val)
|
53
|
+
converter.call(val)
|
54
|
+
# Some custom types might fail, so it should be treated as an invalid value
|
55
|
+
rescue StandardError
|
56
|
+
Types::InvalidValue.new
|
57
|
+
end
|
78
58
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
59
|
+
# Type to which the parameter will be coerced.
|
60
|
+
#
|
61
|
+
# @return [Class]
|
62
|
+
def type
|
63
|
+
@option[:type].is_a?(Hash) ? @option[:type][:value] : @option[:type]
|
64
|
+
end
|
65
|
+
|
66
|
+
def validation_exception(attr_name, custom_msg = nil)
|
67
|
+
Grape::Exceptions::Validation.new(
|
68
|
+
params: [@scope.full_name(attr_name)],
|
69
|
+
message: custom_msg || message(:coerce)
|
70
|
+
)
|
71
|
+
end
|
84
72
|
end
|
85
73
|
end
|
86
74
|
end
|