grape 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|