grape 2.4.0 → 4.0.1
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 +351 -0
- data/CONTRIBUTING.md +18 -10
- data/README.md +457 -228
- data/UPGRADING.md +1240 -1
- data/grape.gemspec +7 -7
- data/lib/grape/api/instance.rb +65 -116
- data/lib/grape/api.rb +53 -62
- data/lib/grape/content_types.rb +58 -3
- data/lib/grape/cookies.rb +2 -6
- data/lib/grape/declared_params_handler.rb +116 -0
- data/lib/grape/dry_types.rb +48 -4
- data/lib/grape/dsl/callbacks.rb +8 -58
- data/lib/grape/dsl/declared.rb +35 -0
- data/lib/grape/dsl/desc.rb +24 -67
- data/lib/grape/dsl/entity.rb +106 -0
- data/lib/grape/dsl/helpers.rb +80 -65
- data/lib/grape/dsl/inside_route.rb +56 -296
- data/lib/grape/dsl/logger.rb +4 -9
- data/lib/grape/dsl/middleware.rb +22 -40
- data/lib/grape/dsl/parameters.rb +86 -93
- data/lib/grape/dsl/request_response.rb +139 -139
- data/lib/grape/dsl/rescue_options.rb +25 -0
- data/lib/grape/dsl/routing.rb +328 -203
- data/lib/grape/dsl/settings.rb +29 -135
- data/lib/grape/dsl/validations.rb +38 -44
- data/lib/grape/dsl/version_options.rb +23 -0
- data/lib/grape/endpoint/options.rb +25 -0
- data/lib/grape/endpoint.rb +285 -245
- data/lib/grape/env.rb +8 -3
- data/lib/grape/error_formatter/base.rb +27 -21
- data/lib/grape/error_formatter/json.rb +6 -0
- data/lib/grape/error_formatter/txt.rb +10 -10
- data/lib/grape/error_formatter.rb +6 -2
- data/lib/grape/exceptions/base.rb +20 -44
- data/lib/grape/exceptions/error_response.rb +48 -0
- data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
- data/lib/grape/exceptions/internal_server_error.rb +16 -0
- 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_group_type.rb +0 -2
- 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_error_formatter.rb +11 -0
- 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/unsupported_group_type.rb +0 -2
- data/lib/grape/exceptions/validation.rb +25 -7
- data/lib/grape/exceptions/validation_array_errors.rb +4 -0
- data/lib/grape/exceptions/validation_errors.rb +21 -23
- data/lib/grape/formatter/json.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +6 -9
- data/lib/grape/json.rb +38 -2
- data/lib/grape/locale/en.yml +3 -5
- data/lib/grape/middleware/auth/base.rb +4 -3
- data/lib/grape/middleware/auth/dsl.rb +9 -23
- data/lib/grape/middleware/base.rb +41 -36
- data/lib/grape/middleware/error.rb +271 -73
- data/lib/grape/middleware/formatter.rb +152 -63
- data/lib/grape/middleware/precomputed_content_types.rb +51 -0
- data/lib/grape/middleware/stack.rb +20 -11
- data/lib/grape/middleware/versioner/accept_version_header.rb +3 -3
- data/lib/grape/middleware/versioner/base.rb +40 -48
- data/lib/grape/middleware/versioner/header.rb +5 -23
- data/lib/grape/middleware/versioner/param.rb +2 -2
- data/lib/grape/middleware/versioner/path.rb +54 -7
- data/lib/grape/mountable.rb +22 -0
- data/lib/grape/namespace.rb +19 -11
- data/lib/grape/params_builder/base.rb +2 -0
- data/lib/grape/params_builder/hash_with_indifferent_access.rb +1 -1
- data/lib/grape/params_builder.rb +2 -19
- data/lib/grape/parser/json.rb +1 -1
- data/lib/grape/path.rb +8 -72
- data/lib/grape/precompiled_json.rb +50 -0
- data/lib/grape/request.rb +57 -20
- data/lib/grape/router/base_route.rb +53 -7
- data/lib/grape/router/greedy_route.rb +16 -6
- data/lib/grape/router/mustermann_pattern.rb +44 -0
- data/lib/grape/router/pattern/path.rb +78 -0
- data/lib/grape/router/pattern.rb +65 -37
- data/lib/grape/router/route.rb +66 -18
- data/lib/grape/router.rb +126 -115
- data/lib/grape/serve_stream/file_body.rb +7 -0
- data/lib/grape/serve_stream/sendfile_response.rb +3 -5
- data/lib/grape/serve_stream/stream_response.rb +7 -0
- data/lib/grape/testing.rb +33 -0
- data/lib/grape/util/api_description.rb +67 -0
- data/lib/grape/util/cache.rb +22 -2
- data/lib/grape/util/deep_freeze.rb +34 -0
- data/lib/grape/util/freeze_on_new.rb +20 -0
- data/lib/grape/util/inheritable_setting.rb +777 -39
- data/lib/grape/util/lazy/base.rb +16 -0
- data/lib/grape/util/lazy/block.rb +2 -9
- data/lib/grape/util/lazy/value.rb +2 -9
- data/lib/grape/util/lazy/value_enumerable.rb +13 -16
- data/lib/grape/util/media_type.rb +13 -9
- data/lib/grape/util/path_normalizer.rb +37 -0
- data/lib/grape/util/registry.rb +13 -3
- data/lib/grape/util/shadowed_rescue_handlers.rb +49 -0
- data/lib/grape/util/stackable_values.rb +39 -10
- data/lib/grape/util/translation.rb +42 -0
- data/lib/grape/validations/attributes_iterator.rb +61 -29
- data/lib/grape/validations/coerce_options.rb +21 -0
- data/lib/grape/validations/contract_scope.rb +8 -13
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/oneof_collector.rb +35 -0
- data/lib/grape/validations/param_scope_tracker.rb +62 -0
- data/lib/grape/validations/params_documentation.rb +52 -0
- data/lib/grape/validations/params_scope.rb +217 -304
- data/lib/grape/validations/shared_options.rb +19 -0
- data/lib/grape/validations/single_attribute_iterator.rb +6 -4
- data/lib/grape/validations/types/array_coercer.rb +7 -10
- data/lib/grape/validations/types/custom_type_coercer.rb +47 -85
- data/lib/grape/validations/types/custom_type_collection_coercer.rb +1 -1
- data/lib/grape/validations/types/dry_type_coercer.rb +10 -15
- data/lib/grape/validations/types/json.rb +1 -3
- data/lib/grape/validations/types/multiple_type_coercer.rb +5 -3
- data/lib/grape/validations/types/primitive_coercer.rb +14 -33
- data/lib/grape/validations/types/set_coercer.rb +1 -1
- data/lib/grape/validations/types/variant_collection_coercer.rb +16 -3
- data/lib/grape/validations/types.rb +29 -51
- data/lib/grape/validations/validations_spec.rb +164 -0
- 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 +118 -34
- data/lib/grape/validations/validators/coerce_validator.rb +25 -37
- data/lib/grape/validations/validators/contract_scope_validator.rb +10 -5
- data/lib/grape/validations/validators/default_validator.rb +13 -20
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
- data/lib/grape/validations/validators/except_values_validator.rb +14 -4
- data/lib/grape/validations/validators/length_validator.rb +23 -22
- data/lib/grape/validations/validators/multiple_params_base.rb +12 -9
- data/lib/grape/validations/validators/{mutual_exclusion_validator.rb → mutually_exclusive_validator.rb} +4 -2
- data/lib/grape/validations/validators/oneof_validator.rb +51 -0
- data/lib/grape/validations/validators/presence_validator.rb +4 -2
- data/lib/grape/validations/validators/regexp_validator.rb +11 -3
- data/lib/grape/validations/validators/same_as_validator.rb +7 -15
- data/lib/grape/validations/validators/values_validator.rb +34 -26
- data/lib/grape/version.rb +1 -2
- data/lib/grape/xml.rb +8 -1
- data/lib/grape.rb +58 -31
- metadata +62 -39
- data/lib/grape/api/helpers.rb +0 -9
- data/lib/grape/dsl/api.rb +0 -17
- data/lib/grape/dsl/configuration.rb +0 -15
- 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/missing_option.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/exceptions/unknown_options.rb +0 -11
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +0 -24
- data/lib/grape/extensions/hash.rb +0 -27
- data/lib/grape/extensions/hashie/mash.rb +0 -24
- data/lib/grape/middleware/globals.rb +0 -14
- data/lib/grape/types/invalid_value.rb +0 -8
- data/lib/grape/util/base_inheritable.rb +0 -43
- data/lib/grape/util/inheritable_values.rb +0 -29
- data/lib/grape/util/reverse_stackable_values.rb +0 -15
- data/lib/grape/util/strict_hash_configuration.rb +0 -108
- data/lib/grape/validations/attributes_doc.rb +0 -60
- data/lib/grape/validations/validator_factory.rb +0 -15
|
@@ -5,43 +5,44 @@ 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)
|
|
21
|
+
return unless hash_like?(params)
|
|
22
|
+
|
|
24
23
|
param = params[attr_name]
|
|
25
24
|
|
|
26
25
|
return unless param.respond_to?(:length)
|
|
27
26
|
|
|
28
27
|
return unless (!@min.nil? && param.length < @min) || (!@max.nil? && param.length > @max) || (!@is.nil? && param.length != @is)
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
validation_error!(attr_name, message do
|
|
30
|
+
if @min && @max
|
|
31
|
+
translate(:length, min: @min, max: @max)
|
|
32
|
+
elsif @min
|
|
33
|
+
translate(:length_min, min: @min)
|
|
34
|
+
elsif @max
|
|
35
|
+
translate(:length_max, max: @max)
|
|
36
|
+
else
|
|
37
|
+
translate(:length_is, is: @is)
|
|
38
|
+
end
|
|
39
|
+
end)
|
|
31
40
|
end
|
|
32
41
|
|
|
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
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def validate_boundary!(name, val)
|
|
45
|
+
raise ArgumentError, "`#{name}` must be an integer greater than or equal to zero" if !val.nil? && (!val.is_a?(Integer) || val.negative?)
|
|
45
46
|
end
|
|
46
47
|
end
|
|
47
48
|
end
|
|
@@ -5,28 +5,31 @@ module Grape
|
|
|
5
5
|
module Validators
|
|
6
6
|
class MultipleParamsBase < Base
|
|
7
7
|
def validate!(params)
|
|
8
|
-
|
|
9
|
-
array_errors = []
|
|
8
|
+
array_errors = nil
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
@iterator.each(params) do |resource_params|
|
|
12
11
|
validate_params!(resource_params)
|
|
13
12
|
rescue Grape::Exceptions::Validation => e
|
|
14
|
-
array_errors << e
|
|
13
|
+
(array_errors ||= []) << e
|
|
15
14
|
end
|
|
16
15
|
|
|
17
|
-
raise Grape::Exceptions::ValidationArrayErrors.new(array_errors) if array_errors
|
|
16
|
+
raise Grape::Exceptions::ValidationArrayErrors.new(array_errors) if array_errors
|
|
18
17
|
end
|
|
19
18
|
|
|
20
19
|
private
|
|
21
20
|
|
|
22
|
-
def
|
|
23
|
-
|
|
21
|
+
def iterator_class
|
|
22
|
+
MultipleAttributesIterator
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def keys_in_common(resource_params, known_keys = all_keys)
|
|
26
|
+
return [] unless hash_like?(resource_params)
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
known_keys & resource_params.keys.map! { |attr| scope.full_name(attr) }
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
def all_keys
|
|
29
|
-
attrs.map { |attr|
|
|
32
|
+
attrs.map { |attr| scope.full_name(attr) }
|
|
30
33
|
end
|
|
31
34
|
end
|
|
32
35
|
end
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
|
-
class
|
|
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
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
4
|
+
module Validations
|
|
5
|
+
module Validators
|
|
6
|
+
# Validates that a Hash parameter matches at least one of a set of
|
|
7
|
+
# variant schemas. Each variant is a list of pre-built validators
|
|
8
|
+
# captured by evaluating the variant's block in a {Grape::Validations::OneofCollector}-backed
|
|
9
|
+
# {ParamsScope}. At request time we try each variant in order against
|
|
10
|
+
# a deep-dup of the value; the first variant that produces no errors
|
|
11
|
+
# wins and its (possibly coerced) hash replaces the original.
|
|
12
|
+
class OneofValidator < Base
|
|
13
|
+
default_message_key :oneof
|
|
14
|
+
|
|
15
|
+
def initialize(attrs, options, required, scope, opts)
|
|
16
|
+
super
|
|
17
|
+
@variants = Array(options)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def validate_param!(attr_name, params)
|
|
21
|
+
return unless hash_like?(params)
|
|
22
|
+
|
|
23
|
+
value = params[attr_name]
|
|
24
|
+
return if value.nil? && !required?
|
|
25
|
+
|
|
26
|
+
winning_candidate = nil
|
|
27
|
+
@variants.each do |variant_validators|
|
|
28
|
+
candidate = value.deep_dup
|
|
29
|
+
if variant_matches?(variant_validators, candidate)
|
|
30
|
+
winning_candidate = candidate
|
|
31
|
+
break
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
return params[attr_name] = winning_candidate if winning_candidate
|
|
36
|
+
|
|
37
|
+
validation_error!(attr_name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def variant_matches?(variant_validators, candidate)
|
|
43
|
+
variant_validators.each { |v| v.validate!(candidate) }
|
|
44
|
+
true
|
|
45
|
+
rescue Grape::Exceptions::Validation, Grape::Exceptions::ValidationArrayErrors
|
|
46
|
+
false
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
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 params.
|
|
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,11 +4,19 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class RegexpValidator < Base
|
|
7
|
+
default_message_key :regexp
|
|
8
|
+
|
|
9
|
+
def initialize(attrs, options, required, scope, opts)
|
|
10
|
+
super
|
|
11
|
+
@value = option_value
|
|
12
|
+
end
|
|
13
|
+
|
|
7
14
|
def validate_param!(attr_name, params)
|
|
8
|
-
return unless params.
|
|
9
|
-
|
|
15
|
+
return unless hash_like?(params) && params.key?(attr_name)
|
|
16
|
+
|
|
17
|
+
return if Array.wrap(params[attr_name]).all? { |param| param.nil? || scrub(param.to_s).match?(@value) }
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
validation_error!(attr_name)
|
|
12
20
|
end
|
|
13
21
|
end
|
|
14
22
|
end
|
|
@@ -4,24 +4,16 @@ 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 unless hash_like?(params)
|
|
14
|
+
return if params[attr_name] == params[@value]
|
|
18
15
|
|
|
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
|
|
16
|
+
validation_error!(attr_name, message { translate(:same_as, parameter: @value) })
|
|
25
17
|
end
|
|
26
18
|
end
|
|
27
19
|
end
|
|
@@ -4,55 +4,63 @@ 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?(:scrub)
|
|
20
|
-
|
|
21
|
-
# don't forget that +false.blank?+ is true
|
|
22
|
-
return if val != false && val.blank? && @allow_blank
|
|
23
|
-
|
|
31
|
+
return if val != false && val.blank? && allow_blank?
|
|
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
|
|
|
49
57
|
def required_for_root_scope?
|
|
50
|
-
return false unless
|
|
58
|
+
return false unless required?
|
|
51
59
|
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
current_scope = scope
|
|
61
|
+
current_scope = current_scope.parent while current_scope.lateral?
|
|
54
62
|
|
|
55
|
-
|
|
63
|
+
current_scope.root?
|
|
56
64
|
end
|
|
57
65
|
end
|
|
58
66
|
end
|
data/lib/grape/version.rb
CHANGED
data/lib/grape/xml.rb
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Grape
|
|
4
|
-
|
|
4
|
+
# Since multi_xml 0.9.0 the canonical constant is MultiXML; MultiXml is a
|
|
5
|
+
# deprecated alias (removed in v1.0) that warns on use. Prefer MultiXML so
|
|
6
|
+
# Grape::Xml.parse doesn't trip the deprecation, falling back to the legacy
|
|
7
|
+
# constant and then ActiveSupport::XmlMini.
|
|
8
|
+
# https://github.com/sferik/multi_xml/blob/v0.9.1/CHANGELOG.md
|
|
9
|
+
if defined?(::MultiXML)
|
|
10
|
+
Xml = ::MultiXML
|
|
11
|
+
elsif defined?(::MultiXml)
|
|
5
12
|
Xml = ::MultiXml
|
|
6
13
|
else
|
|
7
14
|
Xml = ::ActiveSupport::XmlMini
|
data/lib/grape.rb
CHANGED
|
@@ -1,31 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'logger'
|
|
4
|
+
require 'monitor'
|
|
4
5
|
require 'active_support'
|
|
5
|
-
require 'active_support/
|
|
6
|
-
require 'active_support/
|
|
7
|
-
require 'active_support/version'
|
|
8
|
-
require 'active_support/isolated_execution_state' if ActiveSupport::VERSION::MAJOR > 6
|
|
9
|
-
require 'active_support/core_ext/array/conversions'
|
|
10
|
-
require 'active_support/core_ext/array/extract_options'
|
|
6
|
+
require 'active_support/isolated_execution_state'
|
|
7
|
+
require 'active_support/core_ext/array/conversions' # to_xml
|
|
11
8
|
require 'active_support/core_ext/array/wrap'
|
|
12
|
-
require 'active_support/core_ext/
|
|
13
|
-
require 'active_support/core_ext/hash/conversions'
|
|
9
|
+
require 'active_support/core_ext/hash/conversions' # to_xml
|
|
14
10
|
require 'active_support/core_ext/hash/deep_merge'
|
|
15
|
-
require 'active_support/core_ext/hash/
|
|
16
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
|
17
|
-
require 'active_support/
|
|
18
|
-
require 'active_support/core_ext/
|
|
19
|
-
require 'active_support/core_ext/hash/slice'
|
|
20
|
-
require 'active_support/core_ext/module/delegation'
|
|
11
|
+
require 'active_support/core_ext/hash/deep_transform_values'
|
|
12
|
+
require 'active_support/core_ext/hash/indifferent_access' # nested_under_indifferent_access, required by HashWithIndifferentAccess.new
|
|
13
|
+
require 'active_support/hash_with_indifferent_access'
|
|
14
|
+
require 'active_support/core_ext/module/delegation' # delegate_missing_to
|
|
21
15
|
require 'active_support/core_ext/object/blank'
|
|
22
16
|
require 'active_support/core_ext/object/deep_dup'
|
|
23
|
-
require 'active_support/core_ext/object/try'
|
|
24
17
|
require 'active_support/core_ext/object/duplicable'
|
|
25
|
-
require 'active_support/core_ext/string/
|
|
26
|
-
require 'active_support/core_ext/string/exclude'
|
|
18
|
+
require 'active_support/core_ext/string/inflections' # demodulize, underscore
|
|
27
19
|
require 'active_support/deprecation'
|
|
28
|
-
require 'active_support/inflector'
|
|
29
20
|
require 'active_support/ordered_options'
|
|
30
21
|
require 'active_support/notifications'
|
|
31
22
|
|
|
@@ -33,15 +24,15 @@ require 'English'
|
|
|
33
24
|
require 'bigdecimal'
|
|
34
25
|
require 'date'
|
|
35
26
|
require 'dry-types'
|
|
27
|
+
require 'dry-configurable'
|
|
36
28
|
require 'forwardable'
|
|
37
29
|
require 'json'
|
|
38
|
-
require 'mustermann
|
|
39
|
-
require '
|
|
30
|
+
require 'mustermann'
|
|
31
|
+
require 'mustermann/ast/pattern'
|
|
40
32
|
require 'rack'
|
|
41
33
|
require 'rack/auth/basic'
|
|
42
34
|
require 'rack/builder'
|
|
43
35
|
require 'rack/head'
|
|
44
|
-
require 'set'
|
|
45
36
|
require 'singleton'
|
|
46
37
|
require 'zeitwerk'
|
|
47
38
|
|
|
@@ -51,16 +42,33 @@ loader.inflector.inflect(
|
|
|
51
42
|
'dsl' => 'DSL'
|
|
52
43
|
)
|
|
53
44
|
railtie = "#{__dir__}/grape/railtie.rb"
|
|
54
|
-
|
|
45
|
+
# Grape::Testing is a test-environment helper -- it extends Grape::Endpoint with
|
|
46
|
+
# `before_each` and prepends a hook to Grape::Endpoint#run. It is documented as
|
|
47
|
+
# opt-in (`require 'grape/testing'`), which eager loading quietly contradicted
|
|
48
|
+
# by installing it in every process.
|
|
49
|
+
testing = "#{__dir__}/grape/testing.rb"
|
|
50
|
+
loader.do_not_eager_load(railtie, testing)
|
|
55
51
|
loader.setup
|
|
56
52
|
|
|
57
53
|
I18n.load_path << File.expand_path('grape/locale/en.yml', __dir__)
|
|
58
54
|
|
|
59
55
|
module Grape
|
|
60
|
-
|
|
56
|
+
extend Dry::Configurable
|
|
57
|
+
|
|
58
|
+
setting :param_builder, default: :hash_with_indifferent_access
|
|
59
|
+
setting :lint, default: false
|
|
60
|
+
setting :warn_on_helper_overrides, default: false
|
|
61
|
+
# Let an error response that cannot be rendered propagate out of the
|
|
62
|
+
# middleware stack instead of being answered with a failsafe 500.
|
|
63
|
+
setting :raise_rendering_errors, default: false
|
|
64
|
+
|
|
65
|
+
# The HTTP QUERY method (RFC 10008): a safe, idempotent request whose content
|
|
66
|
+
# carries the query. Rack has no constant for it yet, hence the literal.
|
|
67
|
+
QUERY = 'QUERY'
|
|
61
68
|
|
|
62
69
|
HTTP_SUPPORTED_METHODS = [
|
|
63
70
|
Rack::GET,
|
|
71
|
+
QUERY,
|
|
64
72
|
Rack::POST,
|
|
65
73
|
Rack::PUT,
|
|
66
74
|
Rack::PATCH,
|
|
@@ -69,18 +77,37 @@ module Grape
|
|
|
69
77
|
Rack::OPTIONS
|
|
70
78
|
].freeze
|
|
71
79
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
# Rack errors that should be rescued and wrapped as Grape::Exceptions::RequestError.
|
|
81
|
+
# Rack 3.1.0 introduced Rack::BadRequest as a marker module included by all bad request
|
|
82
|
+
# exception classes, allowing a single rescue entry to cover them all.
|
|
83
|
+
# Before, these errors are raised as individual exception classes.
|
|
84
|
+
RACK_ERRORS =
|
|
85
|
+
if Gem::Version.new(Rack.release) >= Gem::Version.new('3.1.0')
|
|
86
|
+
[EOFError, Rack::BadRequest]
|
|
87
|
+
else
|
|
88
|
+
[
|
|
89
|
+
EOFError,
|
|
90
|
+
Rack::Multipart::MultipartPartLimitError,
|
|
91
|
+
Rack::Multipart::MultipartTotalPartLimitError,
|
|
92
|
+
Rack::Utils::ParameterTypeError,
|
|
93
|
+
Rack::Utils::InvalidParameterError,
|
|
94
|
+
Rack::QueryParser::ParamsTooDeepError
|
|
95
|
+
]
|
|
96
|
+
end.freeze
|
|
75
97
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
98
|
+
# The deprecation horizon is the version a deprecation announces as its
|
|
99
|
+
# removal point, so it is the *next* major rather than the current one, and
|
|
100
|
+
# it is derived from VERSION rather than written out. Written out, it went
|
|
101
|
+
# stale: it said '2.0' from 2023 (#2353) through all of 2.x, 3.x and 4.x, so
|
|
102
|
+
# a method deprecated through this deprecator announced a removal version
|
|
103
|
+
# that had already shipped, and every custom `behavior` lambda -- how a Rails
|
|
104
|
+
# app consumes deprecations -- was handed the same wrong number.
|
|
105
|
+
def self.deprecator
|
|
106
|
+
@deprecator ||= ActiveSupport::Deprecation.new("#{Gem::Version.new(VERSION).segments.first + 1}.0", 'Grape')
|
|
80
107
|
end
|
|
81
108
|
end
|
|
82
109
|
|
|
83
110
|
# https://api.rubyonrails.org/classes/ActiveSupport/Deprecation.html
|
|
84
111
|
# adding Grape.deprecator to Rails App if any
|
|
85
|
-
require 'grape/railtie' if defined?(Rails::Railtie)
|
|
112
|
+
require 'grape/railtie' if defined?(Rails::Railtie)
|
|
86
113
|
loader.eager_load
|