grape 1.2.5 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/README.md +5 -3
- data/UPGRADING.md +43 -0
- data/grape.gemspec +10 -1
- data/lib/grape.rb +2 -2
- data/lib/grape/api.rb +2 -0
- data/lib/grape/api/helpers.rb +2 -0
- data/lib/grape/api/instance.rb +4 -2
- data/lib/grape/config.rb +2 -0
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dsl/api.rb +2 -0
- data/lib/grape/dsl/callbacks.rb +2 -0
- data/lib/grape/dsl/configuration.rb +2 -0
- data/lib/grape/dsl/desc.rb +2 -0
- data/lib/grape/dsl/headers.rb +2 -0
- data/lib/grape/dsl/helpers.rb +3 -1
- data/lib/grape/dsl/inside_route.rb +7 -4
- data/lib/grape/dsl/logger.rb +2 -0
- data/lib/grape/dsl/middleware.rb +2 -0
- data/lib/grape/dsl/parameters.rb +4 -2
- data/lib/grape/dsl/request_response.rb +4 -2
- data/lib/grape/dsl/routing.rb +3 -1
- data/lib/grape/dsl/settings.rb +7 -1
- data/lib/grape/dsl/validations.rb +2 -0
- data/lib/grape/eager_load.rb +2 -0
- data/lib/grape/endpoint.rb +13 -7
- data/lib/grape/error_formatter.rb +3 -1
- data/lib/grape/error_formatter/base.rb +2 -0
- data/lib/grape/error_formatter/json.rb +2 -0
- data/lib/grape/error_formatter/txt.rb +2 -0
- data/lib/grape/error_formatter/xml.rb +2 -0
- data/lib/grape/exceptions/base.rb +11 -9
- data/lib/grape/exceptions/incompatible_option_values.rb +2 -0
- data/lib/grape/exceptions/invalid_accept_header.rb +2 -0
- data/lib/grape/exceptions/invalid_formatter.rb +2 -0
- data/lib/grape/exceptions/invalid_message_body.rb +2 -0
- data/lib/grape/exceptions/invalid_response.rb +2 -0
- data/lib/grape/exceptions/invalid_version_header.rb +2 -0
- data/lib/grape/exceptions/invalid_versioner_option.rb +2 -0
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +2 -0
- data/lib/grape/exceptions/method_not_allowed.rb +2 -0
- data/lib/grape/exceptions/missing_group_type.rb +2 -0
- data/lib/grape/exceptions/missing_mime_type.rb +2 -0
- data/lib/grape/exceptions/missing_option.rb +2 -0
- data/lib/grape/exceptions/missing_vendor_option.rb +2 -0
- data/lib/grape/exceptions/unknown_options.rb +2 -0
- data/lib/grape/exceptions/unknown_parameter.rb +2 -0
- data/lib/grape/exceptions/unknown_validator.rb +2 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +2 -0
- data/lib/grape/exceptions/validation.rb +3 -1
- data/lib/grape/exceptions/validation_array_errors.rb +2 -0
- data/lib/grape/exceptions/validation_errors.rb +2 -0
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +4 -3
- data/lib/grape/extensions/deep_mergeable_hash.rb +2 -0
- data/lib/grape/extensions/deep_symbolize_hash.rb +2 -0
- data/lib/grape/extensions/hash.rb +2 -0
- data/lib/grape/extensions/hashie/mash.rb +2 -0
- data/lib/grape/formatter.rb +5 -3
- data/lib/grape/formatter/json.rb +2 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -0
- data/lib/grape/formatter/txt.rb +2 -0
- data/lib/grape/formatter/xml.rb +2 -0
- data/lib/grape/http/headers.rb +23 -17
- data/lib/grape/middleware/auth/base.rb +2 -0
- data/lib/grape/middleware/auth/dsl.rb +2 -0
- data/lib/grape/middleware/auth/strategies.rb +2 -0
- data/lib/grape/middleware/auth/strategy_info.rb +2 -0
- data/lib/grape/middleware/base.rb +4 -2
- data/lib/grape/middleware/error.rb +3 -1
- data/lib/grape/middleware/filter.rb +2 -0
- data/lib/grape/middleware/formatter.rb +5 -3
- data/lib/grape/middleware/globals.rb +2 -0
- data/lib/grape/middleware/helpers.rb +2 -0
- data/lib/grape/middleware/stack.rb +2 -0
- data/lib/grape/middleware/versioner.rb +2 -0
- data/lib/grape/middleware/versioner/accept_version_header.rb +2 -0
- data/lib/grape/middleware/versioner/header.rb +2 -0
- data/lib/grape/middleware/versioner/param.rb +3 -1
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -0
- data/lib/grape/middleware/versioner/path.rb +2 -0
- data/lib/grape/namespace.rb +2 -0
- data/lib/grape/parser.rb +3 -1
- data/lib/grape/parser/json.rb +2 -0
- data/lib/grape/parser/xml.rb +2 -0
- data/lib/grape/path.rb +2 -0
- data/lib/grape/presenters/presenter.rb +2 -0
- data/lib/grape/request.rb +3 -1
- data/lib/grape/router.rb +11 -6
- data/lib/grape/router/attribute_translator.rb +18 -8
- data/lib/grape/router/pattern.rb +6 -3
- data/lib/grape/router/route.rb +7 -2
- data/lib/grape/serve_file/file_body.rb +2 -0
- data/lib/grape/serve_file/file_response.rb +2 -0
- data/lib/grape/serve_file/sendfile_response.rb +2 -0
- data/lib/grape/util/base_inheritable.rb +2 -0
- data/lib/grape/util/content_types.rb +2 -0
- data/lib/grape/util/endpoint_configuration.rb +2 -0
- data/lib/grape/util/env.rb +19 -17
- data/lib/grape/util/inheritable_setting.rb +2 -0
- data/lib/grape/util/inheritable_values.rb +2 -0
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_block.rb +2 -0
- data/lib/grape/util/lazy_value.rb +2 -0
- data/lib/grape/util/registrable.rb +2 -0
- data/lib/grape/util/reverse_stackable_values.rb +2 -0
- data/lib/grape/util/stackable_values.rb +3 -0
- data/lib/grape/util/strict_hash_configuration.rb +2 -0
- data/lib/grape/util/xml.rb +2 -0
- data/lib/grape/validations.rb +2 -0
- data/lib/grape/validations/attributes_iterator.rb +3 -3
- data/lib/grape/validations/multiple_attributes_iterator.rb +2 -0
- data/lib/grape/validations/params_scope.rb +23 -10
- data/lib/grape/validations/single_attribute_iterator.rb +13 -2
- data/lib/grape/validations/types.rb +7 -30
- data/lib/grape/validations/types/array_coercer.rb +56 -0
- data/lib/grape/validations/types/build_coercer.rb +49 -48
- data/lib/grape/validations/types/custom_type_coercer.rb +15 -49
- data/lib/grape/validations/types/custom_type_collection_coercer.rb +10 -25
- data/lib/grape/validations/types/dry_type_coercer.rb +41 -0
- data/lib/grape/validations/types/file.rb +10 -9
- data/lib/grape/validations/types/json.rb +11 -8
- data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
- data/lib/grape/validations/types/primitive_coercer.rb +58 -0
- data/lib/grape/validations/types/set_coercer.rb +38 -0
- data/lib/grape/validations/types/variant_collection_coercer.rb +4 -12
- data/lib/grape/validations/validator_factory.rb +2 -0
- data/lib/grape/validations/validators/all_or_none.rb +3 -1
- data/lib/grape/validations/validators/allow_blank.rb +3 -1
- data/lib/grape/validations/validators/as.rb +2 -0
- data/lib/grape/validations/validators/at_least_one_of.rb +3 -1
- data/lib/grape/validations/validators/base.rb +8 -5
- data/lib/grape/validations/validators/coerce.rb +43 -26
- data/lib/grape/validations/validators/default.rb +2 -0
- data/lib/grape/validations/validators/exactly_one_of.rb +3 -1
- data/lib/grape/validations/validators/except_values.rb +3 -1
- data/lib/grape/validations/validators/multiple_params_base.rb +2 -0
- data/lib/grape/validations/validators/mutual_exclusion.rb +3 -1
- data/lib/grape/validations/validators/presence.rb +3 -1
- data/lib/grape/validations/validators/regexp.rb +3 -1
- data/lib/grape/validations/validators/same_as.rb +6 -3
- data/lib/grape/validations/validators/values.rb +17 -5
- data/lib/grape/version.rb +3 -1
- data/spec/grape/api/custom_validations_spec.rb +5 -3
- data/spec/grape/api/deeply_included_options_spec.rb +2 -0
- data/spec/grape/api/defines_boolean_in_params_spec.rb +5 -3
- data/spec/grape/api/inherited_helpers_spec.rb +2 -0
- data/spec/grape/api/instance_spec.rb +54 -0
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/nested_helpers_spec.rb +2 -0
- data/spec/grape/api/optional_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/parameters_modification_spec.rb +3 -1
- data/spec/grape/api/patch_method_helpers_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +2 -0
- data/spec/grape/api/required_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +2 -0
- data/spec/grape/api/routes_with_requirements_spec.rb +2 -0
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +2 -0
- data/spec/grape/api/shared_helpers_spec.rb +2 -0
- data/spec/grape/api_remount_spec.rb +2 -0
- data/spec/grape/api_spec.rb +27 -5
- data/spec/grape/config_spec.rb +2 -0
- data/spec/grape/dsl/callbacks_spec.rb +2 -0
- data/spec/grape/dsl/configuration_spec.rb +2 -0
- data/spec/grape/dsl/desc_spec.rb +2 -0
- data/spec/grape/dsl/headers_spec.rb +2 -0
- data/spec/grape/dsl/helpers_spec.rb +4 -2
- data/spec/grape/dsl/inside_route_spec.rb +2 -0
- data/spec/grape/dsl/logger_spec.rb +2 -0
- data/spec/grape/dsl/middleware_spec.rb +2 -0
- data/spec/grape/dsl/parameters_spec.rb +2 -0
- data/spec/grape/dsl/request_response_spec.rb +2 -0
- data/spec/grape/dsl/routing_spec.rb +2 -0
- data/spec/grape/dsl/settings_spec.rb +2 -0
- data/spec/grape/dsl/validations_spec.rb +2 -0
- data/spec/grape/endpoint_spec.rb +3 -1
- data/spec/grape/entity_spec.rb +2 -0
- data/spec/grape/exceptions/base_spec.rb +3 -1
- data/spec/grape/exceptions/body_parse_errors_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_formatter_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_response_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +2 -0
- data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -0
- data/spec/grape/exceptions/missing_option_spec.rb +2 -0
- data/spec/grape/exceptions/unknown_options_spec.rb +2 -0
- data/spec/grape/exceptions/unknown_validator_spec.rb +2 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +2 -0
- data/spec/grape/exceptions/validation_spec.rb +3 -1
- data/spec/grape/extensions/param_builders/hash_spec.rb +2 -0
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +2 -0
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +2 -0
- data/spec/grape/integration/global_namespace_function_spec.rb +2 -0
- data/spec/grape/integration/rack_sendfile_spec.rb +2 -0
- data/spec/grape/integration/rack_spec.rb +3 -1
- data/spec/grape/loading_spec.rb +2 -0
- data/spec/grape/middleware/auth/base_spec.rb +2 -0
- data/spec/grape/middleware/auth/dsl_spec.rb +2 -0
- data/spec/grape/middleware/auth/strategies_spec.rb +2 -0
- data/spec/grape/middleware/base_spec.rb +2 -0
- data/spec/grape/middleware/error_spec.rb +2 -0
- data/spec/grape/middleware/exception_spec.rb +3 -1
- data/spec/grape/middleware/formatter_spec.rb +17 -10
- data/spec/grape/middleware/globals_spec.rb +2 -0
- data/spec/grape/middleware/stack_spec.rb +2 -0
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
- data/spec/grape/middleware/versioner/header_spec.rb +3 -1
- data/spec/grape/middleware/versioner/param_spec.rb +3 -1
- data/spec/grape/middleware/versioner/path_spec.rb +3 -1
- data/spec/grape/middleware/versioner_spec.rb +2 -0
- data/spec/grape/named_api_spec.rb +2 -0
- data/spec/grape/parser_spec.rb +7 -5
- data/spec/grape/path_spec.rb +2 -0
- data/spec/grape/presenters/presenter_spec.rb +2 -0
- data/spec/grape/request_spec.rb +2 -0
- data/spec/grape/util/inheritable_setting_spec.rb +2 -0
- data/spec/grape/util/inheritable_values_spec.rb +2 -0
- data/spec/grape/util/reverse_stackable_values_spec.rb +2 -0
- data/spec/grape/util/stackable_values_spec.rb +3 -1
- data/spec/grape/util/strict_hash_configuration_spec.rb +2 -0
- data/spec/grape/validations/attributes_iterator_spec.rb +2 -0
- data/spec/grape/validations/instance_behaivour_spec.rb +4 -2
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +2 -0
- data/spec/grape/validations/params_scope_spec.rb +3 -1
- data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -4
- data/spec/grape/validations/types_spec.rb +8 -35
- data/spec/grape/validations/validators/all_or_none_spec.rb +2 -0
- data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +2 -0
- data/spec/grape/validations/validators/coerce_spec.rb +43 -66
- data/spec/grape/validations/validators/default_spec.rb +2 -0
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +2 -0
- data/spec/grape/validations/validators/except_values_spec.rb +3 -1
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +2 -0
- data/spec/grape/validations/validators/presence_spec.rb +30 -0
- data/spec/grape/validations/validators/regexp_spec.rb +2 -0
- data/spec/grape/validations/validators/same_as_spec.rb +2 -0
- data/spec/grape/validations/validators/values_spec.rb +29 -4
- data/spec/grape/validations_spec.rb +61 -3
- data/spec/integration/multi_json/json_spec.rb +2 -0
- data/spec/integration/multi_xml/xml_spec.rb +2 -0
- data/spec/shared/versioning_examples.rb +2 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/basic_auth_encode_helpers.rb +2 -0
- data/spec/support/content_type_helpers.rb +2 -0
- data/spec/support/endpoint_faker.rb +2 -0
- data/spec/support/file_streamer.rb +2 -0
- data/spec/support/integer_helpers.rb +2 -0
- data/spec/support/versioned_helpers.rb +4 -2
- metadata +119 -111
- data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
- data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
@@ -1,12 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
module Types
|
4
|
-
# Instances of this class may be passed to
|
5
|
-
# +Virtus::Attribute.build+ as the +:coercer+
|
6
|
-
# option, to handle collections of types that
|
7
|
-
# provide their own parsing (and optionally,
|
8
|
-
# type-checking) functionality.
|
9
|
-
#
|
10
6
|
# See {CustomTypeCoercer} for details on types
|
11
7
|
# that will be supported by this by this coercer.
|
12
8
|
# This coercer works in the same way as +CustomTypeCoercer+
|
@@ -38,32 +34,21 @@ module Grape
|
|
38
34
|
@set = set
|
39
35
|
end
|
40
36
|
|
41
|
-
#
|
42
|
-
# +Virtus::Attribute::coerce+ in order to coerce
|
43
|
-
# the given value.
|
37
|
+
# Coerces the given value.
|
44
38
|
#
|
45
39
|
# @param value [Array<String>] an array of values to be coerced
|
46
40
|
# @return [Array,Set] the coerced result. May be an +Array+ or a
|
47
41
|
# +Set+ depending on the setting given to the constructor
|
48
42
|
def call(value)
|
49
|
-
coerced = value.map
|
43
|
+
coerced = value.map do |item|
|
44
|
+
coerced_item = super(item)
|
50
45
|
|
51
|
-
|
52
|
-
end
|
46
|
+
return coerced_item if coerced_item.is_a?(InvalidValue)
|
53
47
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
#
|
59
|
-
# @param primitive [Axiom::Types::Type] primitive type for
|
60
|
-
# the coercion as deteced by axiom-types' inference system.
|
61
|
-
# @param value [Enumerable] a coerced result returned from {#call}
|
62
|
-
# @return [true,false] whether or not all of the coerced values in
|
63
|
-
# the collection satisfy type requirements.
|
64
|
-
def success?(primitive, value)
|
65
|
-
value.is_a?(@set ? Set : Array) &&
|
66
|
-
value.all? { |item| super(primitive, item) }
|
48
|
+
coerced_item
|
49
|
+
end
|
50
|
+
|
51
|
+
@set ? Set.new(coerced) : coerced
|
67
52
|
end
|
68
53
|
end
|
69
54
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry-types'
|
4
|
+
|
5
|
+
module DryTypes
|
6
|
+
# Call +Dry.Types()+ to add all registered types to +DryTypes+ which is
|
7
|
+
# a container in this case. Check documentation for more information
|
8
|
+
# https://dry-rb.org/gems/dry-types/1.2/getting-started/
|
9
|
+
include Dry.Types()
|
10
|
+
end
|
11
|
+
|
12
|
+
module Grape
|
13
|
+
module Validations
|
14
|
+
module Types
|
15
|
+
# A base class for classes which must identify a coercer to be used.
|
16
|
+
# If the +strict+ argument is true, it won't coerce the given value
|
17
|
+
# but check its type. More information there
|
18
|
+
# https://dry-rb.org/gems/dry-types/1.2/built-in-types/
|
19
|
+
class DryTypeCoercer
|
20
|
+
def initialize(type, strict = false)
|
21
|
+
@type = type
|
22
|
+
@scope = strict ? DryTypes::Strict : DryTypes::Params
|
23
|
+
end
|
24
|
+
|
25
|
+
# Coerces the given value to a type which was specified during
|
26
|
+
# initialization as a type argument.
|
27
|
+
#
|
28
|
+
# @param val [Object]
|
29
|
+
def call(val)
|
30
|
+
@coercer[val]
|
31
|
+
rescue Dry::Types::CoercionError => _e
|
32
|
+
InvalidValue.new
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
attr_reader :scope, :type
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,21 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
module Types
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def coerce(input)
|
6
|
+
# Implementation for parameters that are multipart file objects.
|
7
|
+
# Actual handling of these objects is provided by +Rack::Request+;
|
8
|
+
# this class is here only to assert that rack's handling has succeeded.
|
9
|
+
class File
|
10
|
+
def call(input)
|
11
|
+
return InvalidValue.new unless coerced?(input)
|
12
|
+
|
12
13
|
# Processing of multipart file objects
|
13
14
|
# is already taken care of by Rack::Request.
|
14
15
|
# Nothing to do here.
|
15
16
|
input
|
16
17
|
end
|
17
18
|
|
18
|
-
def
|
19
|
+
def coerced?(value)
|
19
20
|
# Rack::Request creates a Hash with filename,
|
20
21
|
# content type and an IO object. Do a bit of basic
|
21
22
|
# duck-typing.
|
@@ -1,21 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module Grape
|
4
6
|
module Validations
|
5
7
|
module Types
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# given as JSON-encoded strings. It accepts both JSON objects
|
8
|
+
# Handles coercion and type checking for parameters that are complex
|
9
|
+
# types given as JSON-encoded strings. It accepts both JSON objects
|
9
10
|
# and arrays of objects, and will coerce the input to a +Hash+
|
10
11
|
# or +Array+ object respectively. In either case the Grape
|
11
12
|
# validation system will apply nested validation rules to
|
12
13
|
# all returned objects.
|
13
|
-
class Json
|
14
|
+
class Json
|
14
15
|
# Coerce the input into a JSON-like data structure.
|
15
16
|
#
|
16
17
|
# @param input [String] a JSON-encoded parameter value
|
17
18
|
# @return [Hash,Array<Hash>,nil]
|
18
|
-
def
|
19
|
+
def call(input)
|
20
|
+
return input if coerced?(input)
|
21
|
+
|
19
22
|
# Allow nulls and blank strings
|
20
23
|
return if input.nil? || input =~ /^\s*$/
|
21
24
|
JSON.parse(input, symbolize_names: true)
|
@@ -26,7 +29,7 @@ module Grape
|
|
26
29
|
#
|
27
30
|
# @param value [Object] result of {#coerce}
|
28
31
|
# @return [true,false]
|
29
|
-
def
|
32
|
+
def coerced?(value)
|
30
33
|
value.is_a?(::Hash) || coerced_collection?(value)
|
31
34
|
end
|
32
35
|
|
@@ -50,13 +53,13 @@ module Grape
|
|
50
53
|
#
|
51
54
|
# @param input [String] JSON-encoded parameter value
|
52
55
|
# @return [Array<Hash>]
|
53
|
-
def
|
56
|
+
def call(input)
|
54
57
|
json = super
|
55
58
|
Array.wrap(json) unless json.nil?
|
56
59
|
end
|
57
60
|
|
58
61
|
# See {Json#coerced_collection?}
|
59
|
-
def
|
62
|
+
def coerced?(value)
|
60
63
|
coerced_collection? value
|
61
64
|
end
|
62
65
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
module Types
|
@@ -22,53 +24,32 @@ module Grape
|
|
22
24
|
|
23
25
|
@type_coercers = types.map do |type|
|
24
26
|
if Types.multiple? type
|
25
|
-
VariantCollectionCoercer.new type
|
27
|
+
VariantCollectionCoercer.new type, @method
|
26
28
|
else
|
27
|
-
Types.build_coercer type
|
29
|
+
Types.build_coercer type, strict: !@method.nil?
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
#
|
33
|
-
# +Virtus::Attribute::coerce+ in order to coerce
|
34
|
-
# the given value.
|
34
|
+
# Coerces the given value.
|
35
35
|
#
|
36
|
-
# @param
|
36
|
+
# @param val [String] value to be coerced, in grape
|
37
37
|
# this should always be a string.
|
38
38
|
# @return [Object,InvalidValue] the coerced result, or an instance
|
39
39
|
# of {InvalidValue} if the value could not be coerced.
|
40
|
-
def call(
|
41
|
-
|
40
|
+
def call(val)
|
41
|
+
# once the value is coerced by the custom method, its type should be checked
|
42
|
+
val = @method.call(val) if @method
|
43
|
+
|
44
|
+
coerced_val = InvalidValue.new
|
42
45
|
|
43
46
|
@type_coercers.each do |coercer|
|
44
|
-
|
47
|
+
coerced_val = coercer.call(val)
|
45
48
|
|
46
|
-
return
|
49
|
+
return coerced_val unless coerced_val.is_a?(InvalidValue)
|
47
50
|
end
|
48
51
|
|
49
|
-
|
50
|
-
# that Grape won't ask us again if the value is valid
|
51
|
-
InvalidValue.new
|
52
|
-
end
|
53
|
-
|
54
|
-
# This method is called from somewhere within
|
55
|
-
# +Virtus::Attribute::value_coerced?+ in order to
|
56
|
-
# assert that the value has been coerced successfully.
|
57
|
-
# Due to Grape's design this will in fact only be called
|
58
|
-
# if a custom coercion method is being used, since {#call}
|
59
|
-
# returns an {InvalidValue} object if the value could not
|
60
|
-
# be coerced.
|
61
|
-
#
|
62
|
-
# @param _primitive [Axiom::Types::Type] primitive type
|
63
|
-
# for the coercion as detected by axiom-types' inference
|
64
|
-
# system. For custom types this is typically not much use
|
65
|
-
# (i.e. it is +Axiom::Types::Object+) unless special
|
66
|
-
# inference rules have been declared for the type.
|
67
|
-
# @param value [Object] a coerced result returned from {#call}
|
68
|
-
# @return [true,false] whether or not the coerced value
|
69
|
-
# satisfies type requirements.
|
70
|
-
def success?(_primitive, value)
|
71
|
-
@type_coercers.any? { |coercer| coercer.value_coerced? value }
|
52
|
+
coerced_val
|
72
53
|
end
|
73
54
|
end
|
74
55
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'dry_type_coercer'
|
4
|
+
|
5
|
+
module Grape
|
6
|
+
module Validations
|
7
|
+
module Types
|
8
|
+
# Coerces the given value to a type defined via a +type+ argument during
|
9
|
+
# initialization.
|
10
|
+
class PrimitiveCoercer < DryTypeCoercer
|
11
|
+
MAPPING = {
|
12
|
+
Grape::API::Boolean => DryTypes::Params::Bool,
|
13
|
+
|
14
|
+
# unfortunatelly, a +Params+ scope doesn't contain String
|
15
|
+
String => DryTypes::Coercible::String
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
STRICT_MAPPING = {
|
19
|
+
Grape::API::Boolean => DryTypes::Strict::Bool
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
def initialize(type, strict = false)
|
23
|
+
super
|
24
|
+
|
25
|
+
@type = type
|
26
|
+
|
27
|
+
@coercer = if strict
|
28
|
+
STRICT_MAPPING.fetch(type) { scope.const_get(type.name) }
|
29
|
+
else
|
30
|
+
MAPPING.fetch(type) { scope.const_get(type.name) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def call(val)
|
35
|
+
return InvalidValue.new if reject?(val)
|
36
|
+
return nil if val.nil?
|
37
|
+
return '' if val == ''
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
attr_reader :type
|
45
|
+
|
46
|
+
# This method maintaine logic which was defined by Virtus. For example,
|
47
|
+
# dry-types is ok to convert an array or a hash to a string, it is supported,
|
48
|
+
# but Virtus wouldn't accept it. So, this method only exists to not introduce
|
49
|
+
# breaking changes.
|
50
|
+
def reject?(val)
|
51
|
+
(val.is_a?(Array) && type == String) ||
|
52
|
+
(val.is_a?(String) && type == Hash) ||
|
53
|
+
(val.is_a?(Hash) && type == String)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
require_relative 'dry_type_coercer'
|
5
|
+
|
6
|
+
module Grape
|
7
|
+
module Validations
|
8
|
+
module Types
|
9
|
+
# Takes the given array and converts it to a set. Every element of the set
|
10
|
+
# is also coerced.
|
11
|
+
class SetCoercer < DryTypeCoercer
|
12
|
+
def initialize(type, strict = false)
|
13
|
+
super
|
14
|
+
|
15
|
+
@elem_coercer = PrimitiveCoercer.new(type.first, strict)
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(value)
|
19
|
+
return InvalidValue.new unless value.is_a?(Array)
|
20
|
+
|
21
|
+
coerce_elements(value)
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def coerce_elements(collection)
|
27
|
+
collection.each_with_object(Set.new) do |elem, memo|
|
28
|
+
coerced_elem = @elem_coercer.call(elem)
|
29
|
+
|
30
|
+
return coerced_elem if coerced_elem.is_a?(InvalidValue)
|
31
|
+
|
32
|
+
memo.add(coerced_elem)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
module Types
|
4
6
|
# This class wraps {MultipleTypeCoercer}, for use with collections
|
5
7
|
# that allow members of more than one type.
|
6
|
-
class VariantCollectionCoercer
|
8
|
+
class VariantCollectionCoercer
|
7
9
|
# Construct a new coercer that will attempt to coerce
|
8
10
|
# a list of values such that all members are of one of
|
9
11
|
# the given types. The container may also optionally be
|
@@ -30,7 +32,7 @@ module Grape
|
|
30
32
|
# @return [Array<Object>,Set<Object>,InvalidValue]
|
31
33
|
# the coerced result, or an instance
|
32
34
|
# of {InvalidValue} if the value could not be coerced.
|
33
|
-
def
|
35
|
+
def call(value)
|
34
36
|
return InvalidValue.new unless value.is_a? Array
|
35
37
|
|
36
38
|
value =
|
@@ -43,16 +45,6 @@ module Grape
|
|
43
45
|
|
44
46
|
value
|
45
47
|
end
|
46
|
-
|
47
|
-
# Assert that the value has been coerced successfully.
|
48
|
-
#
|
49
|
-
# @param value [Object] a coerced result returned from {#coerce}
|
50
|
-
# @return [true,false] whether or not the coerced value
|
51
|
-
# satisfies type requirements.
|
52
|
-
def value_coerced?(value)
|
53
|
-
value.is_a?(@types.class) &&
|
54
|
-
value.all? { |v| @member_coercer.success?(@types, v) }
|
55
|
-
end
|
56
48
|
end
|
57
49
|
end
|
58
50
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'grape/validations/validators/multiple_params_base'
|
2
4
|
|
3
5
|
module Grape
|
@@ -6,7 +8,7 @@ module Grape
|
|
6
8
|
def validate_params!(params)
|
7
9
|
keys = keys_in_common(params)
|
8
10
|
return if keys.empty? || keys.length == all_keys.length
|
9
|
-
raise Grape::Exceptions::Validation
|
11
|
+
raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:all_or_none))
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
class AllowBlankValidator < Base
|
@@ -9,7 +11,7 @@ module Grape
|
|
9
11
|
|
10
12
|
return if value == false || value.present?
|
11
13
|
|
12
|
-
raise Grape::Exceptions::Validation
|
14
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:blank))
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'grape/validations/validators/multiple_params_base'
|
2
4
|
|
3
5
|
module Grape
|
@@ -5,7 +7,7 @@ module Grape
|
|
5
7
|
class AtLeastOneOfValidator < MultipleParamsBase
|
6
8
|
def validate_params!(params)
|
7
9
|
return unless keys_in_common(params).empty?
|
8
|
-
raise Grape::Exceptions::Validation
|
10
|
+
raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:at_least_one))
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|