grape 3.1.1 → 3.2.0
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 +21 -1
- data/README.md +76 -161
- data/UPGRADING.md +106 -0
- data/grape.gemspec +2 -2
- data/lib/grape/api/instance.rb +1 -1
- data/lib/grape/api.rb +1 -1
- data/lib/grape/declared_params_handler.rb +3 -3
- data/lib/grape/dsl/declared.rb +1 -1
- data/lib/grape/dsl/desc.rb +1 -1
- data/lib/grape/dsl/inside_route.rb +9 -9
- data/lib/grape/dsl/parameters.rb +14 -14
- data/lib/grape/dsl/routing.rb +8 -8
- data/lib/grape/endpoint.rb +42 -49
- data/lib/grape/error_formatter/base.rb +2 -2
- data/lib/grape/exceptions/base.rb +18 -44
- data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
- data/lib/grape/exceptions/invalid_accept_header.rb +1 -1
- data/lib/grape/exceptions/invalid_formatter.rb +1 -1
- data/lib/grape/exceptions/invalid_message_body.rb +1 -1
- data/lib/grape/exceptions/invalid_version_header.rb +1 -1
- data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
- data/lib/grape/exceptions/method_not_allowed.rb +1 -1
- data/lib/grape/exceptions/missing_mime_type.rb +1 -1
- data/lib/grape/exceptions/request_error.rb +11 -0
- data/lib/grape/exceptions/unknown_auth_strategy.rb +1 -1
- data/lib/grape/exceptions/unknown_parameter.rb +1 -1
- data/lib/grape/exceptions/unknown_params_builder.rb +1 -1
- data/lib/grape/exceptions/unknown_validator.rb +1 -1
- data/lib/grape/exceptions/validation.rb +7 -4
- data/lib/grape/exceptions/validation_errors.rb +13 -7
- data/lib/grape/locale/en.yml +0 -5
- data/lib/grape/middleware/auth/base.rb +2 -0
- data/lib/grape/middleware/base.rb +2 -4
- data/lib/grape/middleware/error.rb +2 -2
- data/lib/grape/middleware/formatter.rb +1 -1
- data/lib/grape/middleware/versioner/accept_version_header.rb +1 -1
- data/lib/grape/request.rb +2 -10
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router.rb +4 -2
- data/lib/grape/util/api_description.rb +1 -1
- data/lib/grape/util/deep_freeze.rb +35 -0
- data/lib/grape/util/inheritable_setting.rb +1 -1
- data/lib/grape/util/media_type.rb +1 -1
- data/lib/grape/util/translation.rb +42 -0
- data/lib/grape/validations/attributes_iterator.rb +33 -18
- data/lib/grape/validations/contract_scope.rb +1 -7
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/param_scope_tracker.rb +57 -0
- data/lib/grape/validations/params_scope.rb +111 -107
- data/lib/grape/validations/single_attribute_iterator.rb +2 -2
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +6 -3
- data/lib/grape/validations/validators/allow_blank_validator.rb +10 -5
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +5 -2
- data/lib/grape/validations/validators/base.rb +95 -18
- data/lib/grape/validations/validators/coerce_validator.rb +15 -35
- data/lib/grape/validations/validators/contract_scope_validator.rb +10 -8
- data/lib/grape/validations/validators/default_validator.rb +12 -18
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
- data/lib/grape/validations/validators/except_values_validator.rb +13 -4
- data/lib/grape/validations/validators/length_validator.rb +21 -22
- data/lib/grape/validations/validators/multiple_params_base.rb +5 -5
- data/lib/grape/validations/validators/mutually_exclusive_validator.rb +3 -1
- data/lib/grape/validations/validators/presence_validator.rb +4 -2
- data/lib/grape/validations/validators/regexp_validator.rb +8 -10
- data/lib/grape/validations/validators/same_as_validator.rb +6 -15
- data/lib/grape/validations/validators/values_validator.rb +29 -21
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +18 -1
- metadata +11 -13
- data/lib/grape/exceptions/conflicting_types.rb +0 -11
- data/lib/grape/exceptions/empty_message_body.rb +0 -11
- data/lib/grape/exceptions/invalid_parameters.rb +0 -11
- data/lib/grape/exceptions/too_deep_parameters.rb +0 -11
- data/lib/grape/exceptions/too_many_multipart_files.rb +0 -11
- data/lib/grape/validations/validator_factory.rb +0 -15
|
@@ -4,22 +4,27 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class CoerceValidator < Base
|
|
7
|
+
default_message_key :coerce
|
|
8
|
+
|
|
7
9
|
def initialize(attrs, options, required, scope, opts)
|
|
8
10
|
super
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
raw_type = @options[:type]
|
|
13
|
+
type = hash_like?(raw_type) ? raw_type[:value] : raw_type
|
|
14
|
+
@converter =
|
|
15
|
+
if type.is_a?(Grape::Validations::Types::VariantCollectionCoercer)
|
|
16
|
+
type
|
|
17
|
+
else
|
|
18
|
+
Types.build_coercer(type, method: @options[:method])
|
|
19
|
+
end
|
|
15
20
|
end
|
|
16
21
|
|
|
17
22
|
def validate_param!(attr_name, params)
|
|
18
|
-
|
|
23
|
+
validation_error!(attr_name) unless hash_like?(params)
|
|
19
24
|
|
|
20
25
|
new_value = coerce_value(params[attr_name])
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
validation_error!(attr_name, new_value.message || @exception_message) if new_value.is_a?(Types::InvalidValue)
|
|
23
28
|
|
|
24
29
|
# Don't assign a value if it is identical. It fixes a problem with Hashie::Mash
|
|
25
30
|
# which looses wrappers for hashes and arrays after reassigning values
|
|
@@ -37,38 +42,13 @@ module Grape
|
|
|
37
42
|
|
|
38
43
|
private
|
|
39
44
|
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
# See {Types.build_coercer}
|
|
44
|
-
#
|
|
45
|
-
# @return [Object]
|
|
46
|
-
attr_reader :converter
|
|
47
|
-
|
|
48
|
-
def valid_type?(val)
|
|
49
|
-
!val.is_a?(Types::InvalidValue)
|
|
50
|
-
end
|
|
51
|
-
|
|
45
|
+
# Calls the converter built at definition time.
|
|
46
|
+
# Custom coercers may raise; any StandardError is treated as an invalid value.
|
|
52
47
|
def coerce_value(val)
|
|
53
|
-
converter.call(val)
|
|
54
|
-
# Some custom types might fail, so it should be treated as an invalid value
|
|
48
|
+
@converter.call(val)
|
|
55
49
|
rescue StandardError
|
|
56
50
|
Types::InvalidValue.new
|
|
57
51
|
end
|
|
58
|
-
|
|
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
|
|
72
52
|
end
|
|
73
53
|
end
|
|
74
54
|
end
|
|
@@ -3,12 +3,10 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
|
-
class ContractScopeValidator
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
super
|
|
11
|
-
@schema = opts.fetch(:schema)
|
|
6
|
+
class ContractScopeValidator
|
|
7
|
+
def initialize(schema:)
|
|
8
|
+
@schema = schema
|
|
9
|
+
freeze
|
|
12
10
|
end
|
|
13
11
|
|
|
14
12
|
# Validates a given request.
|
|
@@ -16,7 +14,7 @@ module Grape
|
|
|
16
14
|
# @raise [Grape::Exceptions::ValidationArrayErrors] if validation failed
|
|
17
15
|
# @return [void]
|
|
18
16
|
def validate(request)
|
|
19
|
-
res = schema.call(request.params)
|
|
17
|
+
res = @schema.call(request.params)
|
|
20
18
|
|
|
21
19
|
if res.success?
|
|
22
20
|
request.params.deep_merge!(res.to_h)
|
|
@@ -26,13 +24,17 @@ module Grape
|
|
|
26
24
|
raise Grape::Exceptions::ValidationArrayErrors.new(build_errors_from_messages(res.errors.messages))
|
|
27
25
|
end
|
|
28
26
|
|
|
27
|
+
def fail_fast?
|
|
28
|
+
false
|
|
29
|
+
end
|
|
30
|
+
|
|
29
31
|
private
|
|
30
32
|
|
|
31
33
|
def build_errors_from_messages(messages)
|
|
32
34
|
messages.map do |message|
|
|
33
35
|
full_name = message.path.first.to_s
|
|
34
36
|
full_name << "[#{message.path[1..].join('][')}]" if message.path.size > 1
|
|
35
|
-
Grape::Exceptions::Validation.new(params:
|
|
37
|
+
Grape::Exceptions::Validation.new(params: full_name, message: message.text)
|
|
36
38
|
end
|
|
37
39
|
end
|
|
38
40
|
end
|
|
@@ -4,31 +4,25 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class DefaultValidator < Base
|
|
7
|
-
def initialize(attrs, options, required, scope, opts
|
|
8
|
-
@default = options
|
|
7
|
+
def initialize(attrs, options, required, scope, opts)
|
|
9
8
|
super
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
elsif @default.frozen? || !@default.duplicable?
|
|
20
|
-
@default
|
|
21
|
-
else
|
|
22
|
-
@default.dup
|
|
23
|
-
end
|
|
9
|
+
# !important, lazy call at runtime
|
|
10
|
+
@default_call =
|
|
11
|
+
if @options.is_a?(Proc)
|
|
12
|
+
@options.arity.zero? ? proc { @options.call } : @options
|
|
13
|
+
elsif @options.duplicable?
|
|
14
|
+
proc { @options.dup }
|
|
15
|
+
else
|
|
16
|
+
proc { @options }
|
|
17
|
+
end
|
|
24
18
|
end
|
|
25
19
|
|
|
26
20
|
def validate!(params)
|
|
27
|
-
attrs = SingleAttributeIterator.new(
|
|
21
|
+
attrs = SingleAttributeIterator.new(@attrs, @scope, params)
|
|
28
22
|
attrs.each do |resource_params, attr_name|
|
|
29
23
|
next unless @scope.meets_dependency?(resource_params, params)
|
|
30
24
|
|
|
31
|
-
|
|
25
|
+
resource_params[attr_name] = @default_call.call(resource_params) if hash_like?(resource_params) && resource_params[attr_name].nil?
|
|
32
26
|
end
|
|
33
27
|
end
|
|
34
28
|
end
|
|
@@ -4,12 +4,19 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class ExactlyOneOfValidator < MultipleParamsBase
|
|
7
|
+
def initialize(attrs, options, required, scope, opts)
|
|
8
|
+
super
|
|
9
|
+
@exactly_one_exception_message = message(:exactly_one)
|
|
10
|
+
@mutual_exclusion_exception_message = message(:mutual_exclusion)
|
|
11
|
+
end
|
|
12
|
+
|
|
7
13
|
def validate_params!(params)
|
|
8
|
-
|
|
14
|
+
known_keys = all_keys
|
|
15
|
+
keys = keys_in_common(params, known_keys)
|
|
9
16
|
return if keys.length == 1
|
|
10
|
-
raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:exactly_one)) if keys.empty?
|
|
11
17
|
|
|
12
|
-
|
|
18
|
+
validation_error!(known_keys, @exactly_one_exception_message) if keys.empty?
|
|
19
|
+
validation_error!(keys, @mutual_exclusion_exception_message)
|
|
13
20
|
end
|
|
14
21
|
end
|
|
15
22
|
end
|
|
@@ -4,19 +4,28 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class ExceptValuesValidator < Base
|
|
7
|
+
default_message_key :except_values
|
|
8
|
+
|
|
7
9
|
def initialize(attrs, options, required, scope, opts)
|
|
8
|
-
@except = options.is_a?(Hash) ? options[:value] : options
|
|
9
10
|
super
|
|
11
|
+
except = option_value
|
|
12
|
+
raise ArgumentError, 'except_values Proc must have arity of zero (use values: with a one-arity predicate for per-element checks)' if except.is_a?(Proc) && !except.arity.zero?
|
|
13
|
+
|
|
14
|
+
# Zero-arity procs (e.g. -> { User.pluck(:role) }) must be called per-request,
|
|
15
|
+
# not at definition time, so they are wrapped in a lambda to defer execution.
|
|
16
|
+
@excepts_call = except.is_a?(Proc) ? except : -> { except }
|
|
10
17
|
end
|
|
11
18
|
|
|
12
19
|
def validate_param!(attr_name, params)
|
|
13
|
-
return unless
|
|
20
|
+
return unless hash_like?(params) && params.key?(attr_name)
|
|
14
21
|
|
|
15
|
-
excepts = @
|
|
22
|
+
excepts = @excepts_call.call
|
|
16
23
|
return if excepts.nil?
|
|
17
24
|
|
|
18
25
|
param_array = params[attr_name].nil? ? [nil] : Array.wrap(params[attr_name])
|
|
19
|
-
|
|
26
|
+
return if param_array.none? { |param| excepts.include?(param) }
|
|
27
|
+
|
|
28
|
+
validation_error!(attr_name)
|
|
20
29
|
end
|
|
21
30
|
end
|
|
22
31
|
end
|
|
@@ -5,19 +5,16 @@ module Grape
|
|
|
5
5
|
module Validators
|
|
6
6
|
class LengthValidator < Base
|
|
7
7
|
def initialize(attrs, options, required, scope, opts)
|
|
8
|
-
@min = options[:min]
|
|
9
|
-
@max = options[:max]
|
|
10
|
-
@is = options[:is]
|
|
11
|
-
|
|
12
8
|
super
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
@min, @max, @is = @options.values_at(:min, :max, :is)
|
|
11
|
+
validate_boundary!(:min, @min)
|
|
12
|
+
validate_boundary!(:max, @max)
|
|
13
|
+
raise ArgumentError, "min #{@min} cannot be greater than max #{@max}" if @min && @max && @min > @max
|
|
17
14
|
|
|
18
15
|
return if @is.nil?
|
|
19
|
-
raise ArgumentError, 'is must be an integer greater than zero'
|
|
20
|
-
raise ArgumentError, 'is cannot be combined with min or max'
|
|
16
|
+
raise ArgumentError, 'is must be an integer greater than zero' unless @is.is_a?(Integer) && @is.positive?
|
|
17
|
+
raise ArgumentError, 'is cannot be combined with min or max' unless @min.nil? && @max.nil?
|
|
21
18
|
end
|
|
22
19
|
|
|
23
20
|
def validate_param!(attr_name, params)
|
|
@@ -27,21 +24,23 @@ module Grape
|
|
|
27
24
|
|
|
28
25
|
return unless (!@min.nil? && param.length < @min) || (!@max.nil? && param.length > @max) || (!@is.nil? && param.length != @is)
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
validation_error!(attr_name, message do
|
|
28
|
+
if @min && @max
|
|
29
|
+
translate(:length, min: @min, max: @max)
|
|
30
|
+
elsif @min
|
|
31
|
+
translate(:length_min, min: @min)
|
|
32
|
+
elsif @max
|
|
33
|
+
translate(:length_max, max: @max)
|
|
34
|
+
else
|
|
35
|
+
translate(:length_is, is: @is)
|
|
36
|
+
end
|
|
37
|
+
end)
|
|
31
38
|
end
|
|
32
39
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
format I18n.t(:length, scope: 'grape.errors.messages'), min: @min, max: @max
|
|
38
|
-
elsif @min
|
|
39
|
-
format I18n.t(:length_min, scope: 'grape.errors.messages'), min: @min
|
|
40
|
-
elsif @max
|
|
41
|
-
format I18n.t(:length_max, scope: 'grape.errors.messages'), max: @max
|
|
42
|
-
else
|
|
43
|
-
format I18n.t(:length_is, scope: 'grape.errors.messages'), is: @is
|
|
44
|
-
end
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def validate_boundary!(name, val)
|
|
43
|
+
raise ArgumentError, "#{name} must be an integer greater than or equal to zero" if !val.nil? && (!val.is_a?(Integer) || val.negative?)
|
|
45
44
|
end
|
|
46
45
|
end
|
|
47
46
|
end
|
|
@@ -5,7 +5,7 @@ module Grape
|
|
|
5
5
|
module Validators
|
|
6
6
|
class MultipleParamsBase < Base
|
|
7
7
|
def validate!(params)
|
|
8
|
-
attributes = MultipleAttributesIterator.new(
|
|
8
|
+
attributes = MultipleAttributesIterator.new(@attrs, @scope, params)
|
|
9
9
|
array_errors = []
|
|
10
10
|
|
|
11
11
|
attributes.each do |resource_params|
|
|
@@ -19,14 +19,14 @@ module Grape
|
|
|
19
19
|
|
|
20
20
|
private
|
|
21
21
|
|
|
22
|
-
def keys_in_common(resource_params)
|
|
23
|
-
return [] unless
|
|
22
|
+
def keys_in_common(resource_params, known_keys = all_keys)
|
|
23
|
+
return [] unless hash_like?(resource_params)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
known_keys & resource_params.keys.map! { |attr| @scope.full_name(attr) }
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def all_keys
|
|
29
|
-
attrs.map { |attr| @scope.full_name(attr) }
|
|
29
|
+
@attrs.map { |attr| @scope.full_name(attr) }
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -4,11 +4,13 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class MutuallyExclusiveValidator < MultipleParamsBase
|
|
7
|
+
default_message_key :mutual_exclusion
|
|
8
|
+
|
|
7
9
|
def validate_params!(params)
|
|
8
10
|
keys = keys_in_common(params)
|
|
9
11
|
return if keys.length <= 1
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
validation_error!(keys)
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
end
|
|
@@ -4,10 +4,12 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class PresenceValidator < Base
|
|
7
|
+
default_message_key :presence
|
|
8
|
+
|
|
7
9
|
def validate_param!(attr_name, params)
|
|
8
|
-
return if
|
|
10
|
+
return if hash_like?(params) && params.key?(attr_name)
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
validation_error!(attr_name)
|
|
11
13
|
end
|
|
12
14
|
end
|
|
13
15
|
end
|
|
@@ -4,21 +4,19 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class RegexpValidator < Base
|
|
7
|
-
|
|
8
|
-
return unless params.respond_to?(:key) && params.key?(attr_name)
|
|
9
|
-
|
|
10
|
-
value = options_key?(:value) ? @option[:value] : @option
|
|
11
|
-
return if Array.wrap(params[attr_name]).all? { |param| param.nil? || scrub(param.to_s).match?(value) }
|
|
7
|
+
default_message_key :regexp
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
def initialize(attrs, options, required, scope, opts)
|
|
10
|
+
super
|
|
11
|
+
@value = option_value
|
|
14
12
|
end
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
def validate_param!(attr_name, params)
|
|
15
|
+
return unless hash_like?(params) && params.key?(attr_name)
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
return param if param.valid_encoding?
|
|
17
|
+
return if Array.wrap(params[attr_name]).all? { |param| param.nil? || scrub(param.to_s).match?(@value) }
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
validation_error!(attr_name)
|
|
22
20
|
end
|
|
23
21
|
end
|
|
24
22
|
end
|
|
@@ -4,24 +4,15 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class SameAsValidator < Base
|
|
7
|
-
def
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
raise Grape::Exceptions::Validation.new(
|
|
12
|
-
params: [@scope.full_name(attr_name)],
|
|
13
|
-
message: build_message
|
|
14
|
-
)
|
|
7
|
+
def initialize(attrs, options, required, scope, opts)
|
|
8
|
+
super
|
|
9
|
+
@value = option_value
|
|
15
10
|
end
|
|
16
11
|
|
|
17
|
-
|
|
12
|
+
def validate_param!(attr_name, params)
|
|
13
|
+
return if params[attr_name] == params[@value]
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
if options_key?(:message)
|
|
21
|
-
@option[:message]
|
|
22
|
-
else
|
|
23
|
-
format I18n.t(:same_as, scope: 'grape.errors.messages'), parameter: @option
|
|
24
|
-
end
|
|
15
|
+
validation_error!(attr_name, message { translate(:same_as, parameter: @value) })
|
|
25
16
|
end
|
|
26
17
|
end
|
|
27
18
|
end
|
|
@@ -4,45 +4,53 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class ValuesValidator < Base
|
|
7
|
+
default_message_key :values
|
|
8
|
+
|
|
7
9
|
def initialize(attrs, options, required, scope, opts)
|
|
8
|
-
@values = options.is_a?(Hash) ? options[:value] : options
|
|
9
10
|
super
|
|
11
|
+
values = option_value
|
|
12
|
+
|
|
13
|
+
# Zero-arity procs return a collection per-request (e.g. DB-backed lists).
|
|
14
|
+
# Non-zero-arity procs are per-element predicates, called directly at validation time.
|
|
15
|
+
# Non-Proc values are wrapped in a zero-arity lambda for a uniform call interface.
|
|
16
|
+
if values.is_a?(Proc)
|
|
17
|
+
@values_call = values
|
|
18
|
+
@values_is_predicate = !values.arity.zero?
|
|
19
|
+
else
|
|
20
|
+
@values_call = -> { values }
|
|
21
|
+
@values_is_predicate = false
|
|
22
|
+
end
|
|
10
23
|
end
|
|
11
24
|
|
|
12
25
|
def validate_param!(attr_name, params)
|
|
13
|
-
return unless
|
|
26
|
+
return unless hash_like?(params)
|
|
14
27
|
|
|
15
|
-
val = params[attr_name]
|
|
28
|
+
val = scrub(params[attr_name])
|
|
16
29
|
|
|
17
30
|
return if val.nil? && !required_for_root_scope?
|
|
18
|
-
|
|
19
|
-
val = val.scrub if val.respond_to?(:valid_encoding?) && !val.valid_encoding?
|
|
20
|
-
|
|
21
|
-
# don't forget that +false.blank?+ is true
|
|
22
31
|
return if val != false && val.blank? && @allow_blank
|
|
23
|
-
|
|
24
32
|
return if check_values?(val, attr_name)
|
|
25
33
|
|
|
26
|
-
|
|
27
|
-
params: [@scope.full_name(attr_name)],
|
|
28
|
-
message: message(:values)
|
|
29
|
-
)
|
|
34
|
+
validation_error!(attr_name)
|
|
30
35
|
end
|
|
31
36
|
|
|
32
37
|
private
|
|
33
38
|
|
|
34
39
|
def check_values?(val, attr_name)
|
|
35
|
-
values = @values.is_a?(Proc) && @values.arity.zero? ? @values.call : @values
|
|
36
|
-
return true if values.nil?
|
|
37
|
-
|
|
38
40
|
param_array = val.nil? ? [nil] : Array.wrap(val)
|
|
39
|
-
return param_array.all? { |param| values.include?(param) } unless values.is_a?(Proc)
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
if @values_is_predicate
|
|
43
|
+
begin
|
|
44
|
+
param_array.all? { |param| @values_call.call(param) }
|
|
45
|
+
rescue StandardError => e
|
|
46
|
+
warn "Error '#{e}' raised while validating attribute '#{attr_name}'"
|
|
47
|
+
false
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
values = @values_call.call
|
|
51
|
+
return true if values.nil?
|
|
52
|
+
|
|
53
|
+
param_array.all? { |param| values.include?(param) }
|
|
46
54
|
end
|
|
47
55
|
end
|
|
48
56
|
|
data/lib/grape/version.rb
CHANGED
data/lib/grape.rb
CHANGED
|
@@ -33,7 +33,6 @@ require 'rack'
|
|
|
33
33
|
require 'rack/auth/basic'
|
|
34
34
|
require 'rack/builder'
|
|
35
35
|
require 'rack/head'
|
|
36
|
-
require 'set'
|
|
37
36
|
require 'singleton'
|
|
38
37
|
require 'zeitwerk'
|
|
39
38
|
|
|
@@ -64,6 +63,24 @@ module Grape
|
|
|
64
63
|
Rack::OPTIONS
|
|
65
64
|
].freeze
|
|
66
65
|
|
|
66
|
+
# Rack errors that should be rescued and wrapped as Grape::Exceptions::RequestError.
|
|
67
|
+
# Rack 3.1.0 introduced Rack::BadRequest as a marker module included by all bad request
|
|
68
|
+
# exception classes, allowing a single rescue entry to cover them all.
|
|
69
|
+
# Before, these errors are raised as individual exception classes.
|
|
70
|
+
RACK_ERRORS =
|
|
71
|
+
if Gem::Version.new(Rack.release) >= Gem::Version.new('3.1.0')
|
|
72
|
+
[EOFError, Rack::BadRequest]
|
|
73
|
+
else
|
|
74
|
+
[
|
|
75
|
+
EOFError,
|
|
76
|
+
Rack::Multipart::MultipartPartLimitError,
|
|
77
|
+
Rack::Multipart::MultipartTotalPartLimitError,
|
|
78
|
+
Rack::Utils::ParameterTypeError,
|
|
79
|
+
Rack::Utils::InvalidParameterError,
|
|
80
|
+
Rack::QueryParser::ParamsTooDeepError
|
|
81
|
+
]
|
|
82
|
+
end.freeze
|
|
83
|
+
|
|
67
84
|
def self.deprecator
|
|
68
85
|
@deprecator ||= ActiveSupport::Deprecation.new('2.0', 'Grape')
|
|
69
86
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: grape
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Bleigh
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '7.
|
|
18
|
+
version: '7.2'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '7.
|
|
25
|
+
version: '7.2'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: dry-configurable
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -136,13 +136,10 @@ files:
|
|
|
136
136
|
- lib/grape/error_formatter/txt.rb
|
|
137
137
|
- lib/grape/error_formatter/xml.rb
|
|
138
138
|
- lib/grape/exceptions/base.rb
|
|
139
|
-
- lib/grape/exceptions/conflicting_types.rb
|
|
140
|
-
- lib/grape/exceptions/empty_message_body.rb
|
|
141
139
|
- lib/grape/exceptions/incompatible_option_values.rb
|
|
142
140
|
- lib/grape/exceptions/invalid_accept_header.rb
|
|
143
141
|
- lib/grape/exceptions/invalid_formatter.rb
|
|
144
142
|
- lib/grape/exceptions/invalid_message_body.rb
|
|
145
|
-
- lib/grape/exceptions/invalid_parameters.rb
|
|
146
143
|
- lib/grape/exceptions/invalid_response.rb
|
|
147
144
|
- lib/grape/exceptions/invalid_version_header.rb
|
|
148
145
|
- lib/grape/exceptions/invalid_versioner_option.rb
|
|
@@ -151,8 +148,7 @@ files:
|
|
|
151
148
|
- lib/grape/exceptions/missing_group_type.rb
|
|
152
149
|
- lib/grape/exceptions/missing_mime_type.rb
|
|
153
150
|
- lib/grape/exceptions/missing_vendor_option.rb
|
|
154
|
-
- lib/grape/exceptions/
|
|
155
|
-
- lib/grape/exceptions/too_many_multipart_files.rb
|
|
151
|
+
- lib/grape/exceptions/request_error.rb
|
|
156
152
|
- lib/grape/exceptions/unknown_auth_strategy.rb
|
|
157
153
|
- lib/grape/exceptions/unknown_parameter.rb
|
|
158
154
|
- lib/grape/exceptions/unknown_params_builder.rb
|
|
@@ -210,6 +206,7 @@ files:
|
|
|
210
206
|
- lib/grape/util/api_description.rb
|
|
211
207
|
- lib/grape/util/base_inheritable.rb
|
|
212
208
|
- lib/grape/util/cache.rb
|
|
209
|
+
- lib/grape/util/deep_freeze.rb
|
|
213
210
|
- lib/grape/util/endpoint_configuration.rb
|
|
214
211
|
- lib/grape/util/header.rb
|
|
215
212
|
- lib/grape/util/inheritable_setting.rb
|
|
@@ -223,10 +220,12 @@ files:
|
|
|
223
220
|
- lib/grape/util/registry.rb
|
|
224
221
|
- lib/grape/util/reverse_stackable_values.rb
|
|
225
222
|
- lib/grape/util/stackable_values.rb
|
|
223
|
+
- lib/grape/util/translation.rb
|
|
226
224
|
- lib/grape/validations.rb
|
|
227
225
|
- lib/grape/validations/attributes_iterator.rb
|
|
228
226
|
- lib/grape/validations/contract_scope.rb
|
|
229
227
|
- lib/grape/validations/multiple_attributes_iterator.rb
|
|
228
|
+
- lib/grape/validations/param_scope_tracker.rb
|
|
230
229
|
- lib/grape/validations/params_documentation.rb
|
|
231
230
|
- lib/grape/validations/params_scope.rb
|
|
232
231
|
- lib/grape/validations/single_attribute_iterator.rb
|
|
@@ -242,7 +241,6 @@ files:
|
|
|
242
241
|
- lib/grape/validations/types/primitive_coercer.rb
|
|
243
242
|
- lib/grape/validations/types/set_coercer.rb
|
|
244
243
|
- lib/grape/validations/types/variant_collection_coercer.rb
|
|
245
|
-
- lib/grape/validations/validator_factory.rb
|
|
246
244
|
- lib/grape/validations/validators/all_or_none_of_validator.rb
|
|
247
245
|
- lib/grape/validations/validators/allow_blank_validator.rb
|
|
248
246
|
- lib/grape/validations/validators/as_validator.rb
|
|
@@ -267,9 +265,9 @@ licenses:
|
|
|
267
265
|
- MIT
|
|
268
266
|
metadata:
|
|
269
267
|
bug_tracker_uri: https://github.com/ruby-grape/grape/issues
|
|
270
|
-
changelog_uri: https://github.com/ruby-grape/grape/blob/v3.
|
|
271
|
-
documentation_uri: https://www.rubydoc.info/gems/grape/3.
|
|
272
|
-
source_code_uri: https://github.com/ruby-grape/grape/tree/v3.
|
|
268
|
+
changelog_uri: https://github.com/ruby-grape/grape/blob/v3.2.0/CHANGELOG.md
|
|
269
|
+
documentation_uri: https://www.rubydoc.info/gems/grape/3.2.0
|
|
270
|
+
source_code_uri: https://github.com/ruby-grape/grape/tree/v3.2.0
|
|
273
271
|
rubygems_mfa_required: 'true'
|
|
274
272
|
rdoc_options: []
|
|
275
273
|
require_paths:
|
|
@@ -278,7 +276,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
278
276
|
requirements:
|
|
279
277
|
- - ">="
|
|
280
278
|
- !ruby/object:Gem::Version
|
|
281
|
-
version: '3.
|
|
279
|
+
version: '3.2'
|
|
282
280
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
283
281
|
requirements:
|
|
284
282
|
- - ">="
|