grape 1.8.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 +517 -1
- data/CONTRIBUTING.md +19 -11
- data/README.md +841 -545
- data/UPGRADING.md +1553 -7
- data/grape.gemspec +11 -14
- data/lib/grape/api/instance.rb +77 -160
- data/lib/grape/api.rb +75 -107
- data/lib/grape/content_types.rb +67 -9
- data/lib/grape/cookies.rb +28 -25
- data/lib/grape/declared_params_handler.rb +116 -0
- data/lib/grape/dry_types.rb +48 -6
- data/lib/grape/dsl/callbacks.rb +8 -58
- data/lib/grape/dsl/declared.rb +35 -0
- data/lib/grape/dsl/desc.rb +25 -63
- data/lib/grape/dsl/entity.rb +106 -0
- data/lib/grape/dsl/headers.rb +2 -2
- data/lib/grape/dsl/helpers.rb +83 -64
- data/lib/grape/dsl/inside_route.rb +69 -296
- data/lib/grape/dsl/logger.rb +4 -9
- data/lib/grape/dsl/middleware.rb +22 -40
- data/lib/grape/dsl/parameters.rb +88 -94
- data/lib/grape/dsl/request_response.rb +143 -147
- data/lib/grape/dsl/rescue_options.rb +25 -0
- data/lib/grape/dsl/routing.rb +333 -191
- data/lib/grape/dsl/settings.rb +29 -135
- data/lib/grape/dsl/validations.rb +39 -32
- data/lib/grape/dsl/version_options.rb +23 -0
- data/lib/grape/endpoint/options.rb +25 -0
- data/lib/grape/endpoint.rb +319 -269
- data/lib/grape/{util/env.rb → env.rb} +8 -8
- data/lib/grape/error_formatter/base.rb +57 -21
- data/lib/grape/error_formatter/json.rb +13 -15
- data/lib/grape/error_formatter/serializable_hash.rb +7 -0
- data/lib/grape/error_formatter/txt.rb +12 -18
- data/lib/grape/error_formatter/xml.rb +3 -13
- data/lib/grape/error_formatter.rb +9 -25
- data/lib/grape/exceptions/base.rb +22 -58
- 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 +11 -0
- 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 +11 -0
- 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 +28 -11
- data/lib/grape/exceptions/validation_array_errors.rb +5 -0
- data/lib/grape/exceptions/validation_errors.rb +22 -26
- data/lib/grape/formatter/base.rb +16 -0
- data/lib/grape/formatter/json.rb +5 -6
- data/lib/grape/formatter/serializable_hash.rb +7 -10
- data/lib/grape/formatter/txt.rb +3 -5
- data/lib/grape/formatter/xml.rb +4 -6
- data/lib/grape/formatter.rb +7 -25
- data/lib/grape/json.rb +46 -0
- data/lib/grape/locale/en.yml +44 -42
- data/lib/grape/middleware/auth/base.rb +11 -33
- data/lib/grape/middleware/auth/dsl.rb +12 -34
- data/lib/grape/middleware/auth/strategies.rb +1 -2
- data/lib/grape/middleware/base.rb +56 -33
- data/lib/grape/middleware/error.rb +290 -91
- data/lib/grape/middleware/formatter.rb +164 -106
- data/lib/grape/middleware/precomputed_content_types.rb +51 -0
- data/lib/grape/middleware/stack.rb +38 -40
- data/lib/grape/middleware/versioner/accept_version_header.rb +6 -33
- data/lib/grape/middleware/versioner/base.rb +66 -0
- data/lib/grape/middleware/versioner/header.rb +44 -129
- data/lib/grape/middleware/versioner/param.rb +4 -25
- data/lib/grape/middleware/versioner/path.rb +48 -25
- data/lib/grape/middleware/versioner.rb +7 -14
- data/lib/grape/mountable.rb +22 -0
- data/lib/grape/namespace.rb +21 -14
- data/lib/grape/params_builder/base.rb +20 -0
- data/lib/grape/params_builder/hash.rb +11 -0
- data/lib/grape/params_builder/hash_with_indifferent_access.rb +11 -0
- data/lib/grape/params_builder/hashie_mash.rb +11 -0
- data/lib/grape/params_builder.rb +15 -0
- data/lib/grape/parser/base.rb +16 -0
- data/lib/grape/parser/json.rb +6 -8
- data/lib/grape/parser/xml.rb +6 -8
- data/lib/grape/parser.rb +5 -23
- data/lib/grape/path.rb +8 -94
- data/lib/grape/precompiled_json.rb +50 -0
- data/lib/grape/railtie.rb +9 -0
- data/lib/grape/request.rb +200 -26
- data/lib/grape/router/base_route.rb +85 -0
- data/lib/grape/router/greedy_route.rb +30 -0
- data/lib/grape/router/mustermann_pattern.rb +44 -0
- data/lib/grape/router/pattern/path.rb +78 -0
- data/lib/grape/router/pattern.rb +77 -35
- data/lib/grape/router/route.rb +79 -60
- data/lib/grape/router.rb +128 -104
- 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 -5
- data/lib/grape/util/deep_freeze.rb +34 -0
- data/lib/grape/util/endpoint_configuration.rb +1 -1
- data/lib/grape/util/freeze_on_new.rb +20 -0
- data/lib/grape/util/header.rb +13 -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 +22 -0
- data/lib/grape/util/lazy/value.rb +31 -0
- data/lib/grape/util/lazy/value_array.rb +21 -0
- data/lib/grape/util/lazy/value_enumerable.rb +31 -0
- data/lib/grape/util/lazy/value_hash.rb +21 -0
- data/lib/grape/util/media_type.rb +74 -0
- data/lib/grape/util/path_normalizer.rb +37 -0
- data/lib/grape/util/registry.rb +37 -0
- data/lib/grape/util/shadowed_rescue_handlers.rb +49 -0
- data/lib/grape/util/stackable_values.rb +40 -16
- data/lib/grape/util/translation.rb +42 -0
- data/lib/grape/validations/attributes_iterator.rb +61 -28
- data/lib/grape/validations/coerce_options.rb +21 -0
- data/lib/grape/validations/contract_scope.rb +29 -0
- 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 +223 -306
- 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 -12
- 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 +17 -28
- data/lib/grape/validations/types/json.rb +1 -5
- data/lib/grape/validations/types/multiple_type_coercer.rb +5 -3
- data/lib/grape/validations/types/primitive_coercer.rb +14 -35
- data/lib/grape/validations/types/set_coercer.rb +1 -4
- data/lib/grape/validations/types/variant_collection_coercer.rb +16 -3
- data/lib/grape/validations/types.rb +29 -54
- 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 -37
- data/lib/grape/validations/validators/coerce_validator.rb +26 -38
- data/lib/grape/validations/validators/contract_scope_validator.rb +46 -0
- data/lib/grape/validations/validators/default_validator.rb +13 -16
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
- data/lib/grape/validations/validators/except_values_validator.rb +15 -5
- data/lib/grape/validations/validators/length_validator.rb +50 -0
- 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 +36 -65
- data/lib/grape/validations.rb +8 -21
- data/lib/grape/version.rb +1 -2
- data/lib/grape/xml.rb +17 -0
- data/lib/grape.rb +96 -288
- metadata +83 -294
- data/lib/grape/api/helpers.rb +0 -9
- data/lib/grape/dsl/api.rb +0 -19
- data/lib/grape/dsl/configuration.rb +0 -15
- data/lib/grape/eager_load.rb +0 -20
- data/lib/grape/exceptions/empty_message_body.rb +0 -11
- data/lib/grape/exceptions/missing_option.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 -27
- data/lib/grape/extensions/hash.rb +0 -22
- data/lib/grape/extensions/hashie/mash.rb +0 -26
- data/lib/grape/http/headers.rb +0 -61
- data/lib/grape/middleware/globals.rb +0 -16
- data/lib/grape/middleware/helpers.rb +0 -12
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +0 -24
- data/lib/grape/router/attribute_translator.rb +0 -63
- 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 -31
- data/lib/grape/util/json.rb +0 -12
- data/lib/grape/util/lazy_block.rb +0 -27
- data/lib/grape/util/lazy_object.rb +0 -43
- data/lib/grape/util/lazy_value.rb +0 -91
- data/lib/grape/util/registrable.rb +0 -15
- data/lib/grape/util/reverse_stackable_values.rb +0 -20
- data/lib/grape/util/strict_hash_configuration.rb +0 -108
- data/lib/grape/util/xml.rb +0 -10
- data/lib/grape/validations/attributes_doc.rb +0 -58
- data/lib/grape/validations/types/build_coercer.rb +0 -94
- data/lib/grape/validations/validator_factory.rb +0 -15
- data/spec/grape/api/custom_validations_spec.rb +0 -213
- data/spec/grape/api/deeply_included_options_spec.rb +0 -56
- data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
- data/spec/grape/api/documentation_spec.rb +0 -59
- data/spec/grape/api/inherited_helpers_spec.rb +0 -114
- data/spec/grape/api/instance_spec.rb +0 -103
- data/spec/grape/api/invalid_format_spec.rb +0 -45
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
- data/spec/grape/api/nested_helpers_spec.rb +0 -50
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
- data/spec/grape/api/parameters_modification_spec.rb +0 -41
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
- data/spec/grape/api/recognize_path_spec.rb +0 -21
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
- data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
- data/spec/grape/api/shared_helpers_spec.rb +0 -36
- data/spec/grape/api_remount_spec.rb +0 -509
- data/spec/grape/api_spec.rb +0 -4356
- data/spec/grape/dsl/callbacks_spec.rb +0 -45
- data/spec/grape/dsl/desc_spec.rb +0 -98
- data/spec/grape/dsl/headers_spec.rb +0 -62
- data/spec/grape/dsl/helpers_spec.rb +0 -100
- data/spec/grape/dsl/inside_route_spec.rb +0 -531
- data/spec/grape/dsl/logger_spec.rb +0 -24
- data/spec/grape/dsl/middleware_spec.rb +0 -60
- data/spec/grape/dsl/parameters_spec.rb +0 -180
- data/spec/grape/dsl/request_response_spec.rb +0 -225
- data/spec/grape/dsl/routing_spec.rb +0 -275
- data/spec/grape/dsl/settings_spec.rb +0 -261
- data/spec/grape/dsl/validations_spec.rb +0 -55
- data/spec/grape/endpoint/declared_spec.rb +0 -846
- data/spec/grape/endpoint_spec.rb +0 -1085
- data/spec/grape/entity_spec.rb +0 -336
- data/spec/grape/exceptions/base_spec.rb +0 -81
- data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -185
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
- data/spec/grape/exceptions/missing_group_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_option_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -19
- data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
- data/spec/grape/exceptions/validation_spec.rb +0 -19
- data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
- data/spec/grape/grape_spec.rb +0 -9
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
- data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
- data/spec/grape/integration/rack_spec.rb +0 -51
- data/spec/grape/loading_spec.rb +0 -44
- data/spec/grape/middleware/auth/base_spec.rb +0 -31
- data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
- data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
- data/spec/grape/middleware/base_spec.rb +0 -221
- data/spec/grape/middleware/error_spec.rb +0 -85
- data/spec/grape/middleware/exception_spec.rb +0 -294
- data/spec/grape/middleware/formatter_spec.rb +0 -461
- data/spec/grape/middleware/globals_spec.rb +0 -30
- data/spec/grape/middleware/stack_spec.rb +0 -155
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
- data/spec/grape/middleware/versioner/header_spec.rb +0 -345
- data/spec/grape/middleware/versioner/param_spec.rb +0 -171
- data/spec/grape/middleware/versioner/path_spec.rb +0 -62
- data/spec/grape/middleware/versioner_spec.rb +0 -21
- data/spec/grape/named_api_spec.rb +0 -19
- data/spec/grape/parser_spec.rb +0 -86
- data/spec/grape/path_spec.rb +0 -252
- data/spec/grape/presenters/presenter_spec.rb +0 -71
- data/spec/grape/request_spec.rb +0 -126
- data/spec/grape/util/inheritable_setting_spec.rb +0 -242
- data/spec/grape/util/inheritable_values_spec.rb +0 -79
- data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
- data/spec/grape/util/stackable_values_spec.rb +0 -128
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
- data/spec/grape/validations/attributes_doc_spec.rb +0 -153
- data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -38
- data/spec/grape/validations/params_scope_spec.rb +0 -1420
- data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -56
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
- data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
- data/spec/grape/validations/types_spec.rb +0 -111
- data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
- data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
- data/spec/grape/validations/validators/base_spec.rb +0 -38
- data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
- data/spec/grape/validations/validators/default_spec.rb +0 -463
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
- data/spec/grape/validations/validators/except_values_spec.rb +0 -192
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
- data/spec/grape/validations/validators/presence_spec.rb +0 -315
- data/spec/grape/validations/validators/regexp_spec.rb +0 -161
- data/spec/grape/validations/validators/same_as_spec.rb +0 -57
- data/spec/grape/validations/validators/values_spec.rb +0 -733
- data/spec/grape/validations/validators/zh-CN.yml +0 -10
- data/spec/grape/validations_spec.rb +0 -2030
- data/spec/integration/eager_load/eager_load_spec.rb +0 -15
- data/spec/integration/multi_json/json_spec.rb +0 -7
- data/spec/integration/multi_xml/xml_spec.rb +0 -7
- data/spec/shared/deprecated_class_examples.rb +0 -16
- data/spec/shared/versioning_examples.rb +0 -215
- data/spec/spec_helper.rb +0 -52
- data/spec/support/basic_auth_encode_helpers.rb +0 -11
- data/spec/support/chunks.rb +0 -14
- data/spec/support/content_type_helpers.rb +0 -15
- data/spec/support/endpoint_faker.rb +0 -25
- data/spec/support/file_streamer.rb +0 -13
- data/spec/support/integer_helpers.rb +0 -13
- data/spec/support/versioned_helpers.rb +0 -55
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
4
|
+
module Validations
|
|
5
|
+
module Validators
|
|
6
|
+
class ContractScopeValidator
|
|
7
|
+
extend Grape::Util::FreezeOnNew
|
|
8
|
+
|
|
9
|
+
attr_reader :schema
|
|
10
|
+
|
|
11
|
+
def initialize(schema:)
|
|
12
|
+
@schema = schema
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Validates a given request.
|
|
16
|
+
# @param request [Grape::Request] the request currently being handled
|
|
17
|
+
# @raise [Grape::Exceptions::ValidationArrayErrors] if validation failed
|
|
18
|
+
# @return [void]
|
|
19
|
+
def validate(request)
|
|
20
|
+
res = schema.call(request.params)
|
|
21
|
+
|
|
22
|
+
if res.success?
|
|
23
|
+
request.params.deep_merge!(res.to_h)
|
|
24
|
+
return
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
raise Grape::Exceptions::ValidationArrayErrors.new(build_errors_from_messages(res.errors.messages))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def fail_fast?
|
|
31
|
+
false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def build_errors_from_messages(messages)
|
|
37
|
+
messages.map do |message|
|
|
38
|
+
full_name = message.path.first.to_s
|
|
39
|
+
full_name << "[#{message.path[1..].join('][')}]" if message.path.size > 1
|
|
40
|
+
Grape::Exceptions::Validation.new(params: full_name, message: message.text)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -4,27 +4,24 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class DefaultValidator < Base
|
|
7
|
-
def initialize(attrs, options, required, scope,
|
|
8
|
-
@default = options
|
|
7
|
+
def initialize(attrs, options, required, scope, opts)
|
|
9
8
|
super
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
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
|
|
20
18
|
end
|
|
21
19
|
|
|
22
20
|
def validate!(params)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
next unless @scope.meets_dependency?(resource_params, params)
|
|
21
|
+
@iterator.each(params) do |resource_params, attr_name|
|
|
22
|
+
next unless scope.meets_dependency?(resource_params, params)
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
resource_params[attr_name] = @default_call.call(resource_params) if hash_like?(resource_params) && resource_params[attr_name].nil?
|
|
28
25
|
end
|
|
29
26
|
end
|
|
30
27
|
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.length.zero?
|
|
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,29 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class ExceptValuesValidator < Base
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
default_message_key :except_values
|
|
8
|
+
|
|
9
|
+
def initialize(attrs, options, required, scope, opts)
|
|
9
10
|
super
|
|
11
|
+
except = option_value
|
|
12
|
+
except_proc = except.is_a?(Proc)
|
|
13
|
+
raise ArgumentError, 'except_values Proc must have arity of zero (use values: with a one-arity predicate for per-element checks)' if except_proc && !except.arity.zero?
|
|
14
|
+
|
|
15
|
+
# Zero-arity procs (e.g. -> { User.pluck(:role) }) must be called per-request,
|
|
16
|
+
# not at definition time, so they are wrapped in a lambda to defer execution.
|
|
17
|
+
@excepts_call = except_proc ? except : -> { except }
|
|
10
18
|
end
|
|
11
19
|
|
|
12
20
|
def validate_param!(attr_name, params)
|
|
13
|
-
return unless
|
|
21
|
+
return unless hash_like?(params) && params.key?(attr_name)
|
|
14
22
|
|
|
15
|
-
excepts = @
|
|
23
|
+
excepts = @excepts_call.call
|
|
16
24
|
return if excepts.nil?
|
|
17
25
|
|
|
18
26
|
param_array = params[attr_name].nil? ? [nil] : Array.wrap(params[attr_name])
|
|
19
|
-
|
|
27
|
+
return if param_array.none? { |param| excepts.include?(param) }
|
|
28
|
+
|
|
29
|
+
validation_error!(attr_name)
|
|
20
30
|
end
|
|
21
31
|
end
|
|
22
32
|
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
4
|
+
module Validations
|
|
5
|
+
module Validators
|
|
6
|
+
class LengthValidator < Base
|
|
7
|
+
def initialize(attrs, options, required, scope, opts)
|
|
8
|
+
super
|
|
9
|
+
|
|
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
|
|
14
|
+
|
|
15
|
+
return if @is.nil?
|
|
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?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def validate_param!(attr_name, params)
|
|
21
|
+
return unless hash_like?(params)
|
|
22
|
+
|
|
23
|
+
param = params[attr_name]
|
|
24
|
+
|
|
25
|
+
return unless param.respond_to?(:length)
|
|
26
|
+
|
|
27
|
+
return unless (!@min.nil? && param.length < @min) || (!@max.nil? && param.length > @max) || (!@is.nil? && param.length != @is)
|
|
28
|
+
|
|
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)
|
|
40
|
+
end
|
|
41
|
+
|
|
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?)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
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
|
|
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
|
|
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,92 +4,63 @@ module Grape
|
|
|
4
4
|
module Validations
|
|
5
5
|
module Validators
|
|
6
6
|
class ValuesValidator < Base
|
|
7
|
-
|
|
8
|
-
if options.is_a?(Hash)
|
|
9
|
-
@excepts = options[:except]
|
|
10
|
-
@values = options[:value]
|
|
11
|
-
@proc = options[:proc]
|
|
7
|
+
default_message_key :values
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
def initialize(attrs, options, required, scope, opts)
|
|
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?
|
|
18
19
|
else
|
|
19
|
-
@
|
|
20
|
-
@
|
|
21
|
-
@proc = nil
|
|
22
|
-
@values = options
|
|
20
|
+
@values_call = -> { values }
|
|
21
|
+
@values_is_predicate = false
|
|
23
22
|
end
|
|
24
|
-
super
|
|
25
23
|
end
|
|
26
24
|
|
|
27
25
|
def validate_param!(attr_name, params)
|
|
28
|
-
return unless
|
|
26
|
+
return unless hash_like?(params)
|
|
29
27
|
|
|
30
|
-
val = params[attr_name]
|
|
28
|
+
val = scrub(params[attr_name])
|
|
31
29
|
|
|
32
30
|
return if val.nil? && !required_for_root_scope?
|
|
31
|
+
return if val != false && val.blank? && allow_blank?
|
|
32
|
+
return if check_values?(val, attr_name)
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
return if val != false && val.blank? && @allow_blank
|
|
36
|
-
|
|
37
|
-
param_array = val.nil? ? [nil] : Array.wrap(val)
|
|
38
|
-
|
|
39
|
-
raise validation_exception(attr_name, except_message) \
|
|
40
|
-
unless check_excepts(param_array)
|
|
41
|
-
|
|
42
|
-
raise validation_exception(attr_name, message(:values)) \
|
|
43
|
-
unless check_values(param_array, attr_name)
|
|
44
|
-
|
|
45
|
-
raise validation_exception(attr_name, message(:values)) \
|
|
46
|
-
if @proc && !validate_proc(@proc, param_array)
|
|
34
|
+
validation_error!(attr_name)
|
|
47
35
|
end
|
|
48
36
|
|
|
49
37
|
private
|
|
50
38
|
|
|
51
|
-
def check_values(
|
|
52
|
-
|
|
53
|
-
return true if values.nil?
|
|
54
|
-
|
|
55
|
-
begin
|
|
56
|
-
return param_array.all? { |param| values.call(param) } if values.is_a? Proc
|
|
57
|
-
rescue StandardError => e
|
|
58
|
-
warn "Error '#{e}' raised while validating attribute '#{attr_name}'"
|
|
59
|
-
return false
|
|
60
|
-
end
|
|
61
|
-
param_array.all? { |param| values.include?(param) }
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def check_excepts(param_array)
|
|
65
|
-
excepts = @excepts.is_a?(Proc) ? @excepts.call : @excepts
|
|
66
|
-
return true if excepts.nil?
|
|
67
|
-
|
|
68
|
-
param_array.none? { |param| excepts.include?(param) }
|
|
69
|
-
end
|
|
39
|
+
def check_values?(val, attr_name)
|
|
40
|
+
param_array = val.nil? ? [nil] : Array.wrap(val)
|
|
70
41
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
77
49
|
else
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
end
|
|
50
|
+
values = @values_call.call
|
|
51
|
+
return true if values.nil?
|
|
81
52
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
options_key?(:except_message) ? options[:except_message] : message(:except_values)
|
|
53
|
+
param_array.all? { |param| values.include?(param) }
|
|
54
|
+
end
|
|
85
55
|
end
|
|
86
56
|
|
|
87
57
|
def required_for_root_scope?
|
|
88
|
-
|
|
89
|
-
|
|
58
|
+
return false unless required?
|
|
59
|
+
|
|
60
|
+
current_scope = scope
|
|
61
|
+
current_scope = current_scope.parent while current_scope.lateral?
|
|
90
62
|
|
|
91
|
-
|
|
92
|
-
Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message)
|
|
63
|
+
current_scope.root?
|
|
93
64
|
end
|
|
94
65
|
end
|
|
95
66
|
end
|
data/lib/grape/validations.rb
CHANGED
|
@@ -1,34 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Grape
|
|
4
|
-
# Registry to store and locate known Validators.
|
|
5
4
|
module Validations
|
|
5
|
+
extend Grape::Util::Registry
|
|
6
|
+
|
|
6
7
|
module_function
|
|
7
8
|
|
|
8
|
-
def
|
|
9
|
-
|
|
10
|
-
end
|
|
9
|
+
def require_validator(short_name)
|
|
10
|
+
raise Grape::Exceptions::UnknownValidator, short_name unless registry.key?(short_name)
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
# @param short_name [String] all lower-case, no spaces
|
|
14
|
-
# @param klass [Class] the validator class. Should inherit from
|
|
15
|
-
# Validations::Base.
|
|
16
|
-
def register_validator(short_name, klass)
|
|
17
|
-
validators[short_name] = klass
|
|
12
|
+
registry[short_name]
|
|
18
13
|
end
|
|
19
14
|
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
end
|
|
15
|
+
def build_short_name(klass)
|
|
16
|
+
return if klass.name.blank?
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
def require_validator(short_name)
|
|
26
|
-
str_name = short_name.to_s
|
|
27
|
-
validators.fetch(str_name) do
|
|
28
|
-
Grape::Validations::Validators.const_get("#{str_name.camelize}Validator")
|
|
29
|
-
end
|
|
30
|
-
rescue NameError
|
|
31
|
-
raise Grape::Exceptions::UnknownValidator.new(short_name)
|
|
18
|
+
klass.name.demodulize.underscore.delete_suffix('_validator')
|
|
32
19
|
end
|
|
33
20
|
end
|
|
34
21
|
end
|
data/lib/grape/version.rb
CHANGED
data/lib/grape/xml.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
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)
|
|
12
|
+
Xml = ::MultiXml
|
|
13
|
+
else
|
|
14
|
+
Xml = ::ActiveSupport::XmlMini
|
|
15
|
+
Xml::ParseError = StandardError
|
|
16
|
+
end
|
|
17
|
+
end
|