grape 1.2.5 → 1.4.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 +97 -0
- data/LICENSE +1 -1
- data/README.md +53 -16
- data/UPGRADING.md +231 -23
- data/grape.gemspec +10 -1
- data/lib/grape.rb +6 -7
- data/lib/grape/api.rb +4 -2
- data/lib/grape/api/helpers.rb +2 -0
- data/lib/grape/api/instance.rb +36 -33
- data/lib/grape/config.rb +2 -0
- data/lib/grape/content_types.rb +34 -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 +4 -2
- data/lib/grape/dsl/inside_route.rb +83 -34
- data/lib/grape/dsl/logger.rb +2 -0
- data/lib/grape/dsl/middleware.rb +2 -0
- data/lib/grape/dsl/parameters.rb +8 -6
- data/lib/grape/dsl/request_response.rb +4 -2
- data/lib/grape/dsl/routing.rb +9 -5
- data/lib/grape/dsl/settings.rb +7 -1
- data/lib/grape/dsl/validations.rb +20 -1
- data/lib/grape/eager_load.rb +3 -1
- data/lib/grape/endpoint.rb +21 -13
- 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 -13
- 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 +13 -12
- 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 +50 -18
- 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 +7 -7
- data/lib/grape/middleware/error.rb +3 -1
- data/lib/grape/middleware/filter.rb +2 -0
- data/lib/grape/middleware/formatter.rb +8 -6
- data/lib/grape/middleware/globals.rb +2 -0
- data/lib/grape/middleware/helpers.rb +2 -0
- data/lib/grape/middleware/stack.rb +4 -1
- 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 +6 -4
- data/lib/grape/middleware/versioner/param.rb +3 -1
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +4 -1
- data/lib/grape/middleware/versioner/path.rb +3 -1
- data/lib/grape/namespace.rb +14 -2
- 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 +15 -3
- data/lib/grape/presenters/presenter.rb +2 -0
- data/lib/grape/request.rb +15 -8
- data/lib/grape/router.rb +30 -29
- data/lib/grape/router/attribute_translator.rb +39 -8
- data/lib/grape/router/pattern.rb +20 -16
- data/lib/grape/router/route.rb +12 -26
- data/lib/grape/{serve_file → serve_stream}/file_body.rb +3 -1
- data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +3 -1
- data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +10 -8
- data/lib/grape/util/base_inheritable.rb +15 -6
- data/lib/grape/util/cache.rb +20 -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_object.rb +43 -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 +4 -0
- data/lib/grape/util/stackable_values.rb +10 -20
- 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 +27 -14
- data/lib/grape/validations/single_attribute_iterator.rb +13 -2
- data/lib/grape/validations/types.rb +12 -34
- data/lib/grape/validations/types/array_coercer.rb +65 -0
- data/lib/grape/validations/types/build_coercer.rb +47 -49
- 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 +76 -0
- data/lib/grape/validations/types/file.rb +22 -18
- data/lib/grape/validations/types/json.rb +46 -39
- data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
- data/lib/grape/validations/types/primitive_coercer.rb +67 -0
- data/lib/grape/validations/types/set_coercer.rb +40 -0
- data/lib/grape/validations/types/variant_collection_coercer.rb +5 -13
- 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 +39 -29
- data/lib/grape/validations/validators/default.rb +2 -1
- data/lib/grape/validations/validators/exactly_one_of.rb +6 -2
- 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 +4 -2
- 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 +104 -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 +99 -11
- 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 +177 -33
- 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 +21 -6
- 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 +4 -2
- 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 +14 -8
- 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 +3 -1
- 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 +19 -12
- data/spec/grape/middleware/globals_spec.rb +2 -0
- data/spec/grape/middleware/stack_spec.rb +11 -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 +6 -4
- 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 +5 -3
- 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/array_coercer_spec.rb +35 -0
- data/spec/grape/validations/types/primitive_coercer_spec.rb +135 -0
- data/spec/grape/validations/types/set_coercer_spec.rb +34 -0
- data/spec/grape/validations/types_spec.rb +9 -36
- 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 +341 -136
- data/spec/grape/validations/validators/default_spec.rb +123 -0
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +14 -12
- 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 +30 -5
- data/spec/grape/validations_spec.rb +91 -33
- data/spec/integration/eager_load/eager_load_spec.rb +15 -0
- 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 +18 -0
- data/spec/support/basic_auth_encode_helpers.rb +2 -0
- data/spec/support/content_type_helpers.rb +2 -0
- data/spec/support/eager_load.rb +19 -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 +48 -28
- data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
- data/lib/grape/util/content_types.rb +0 -26
- data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
@@ -0,0 +1,67 @@
|
|
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. When +strict+ is true, it doesn't coerce a value but check
|
10
|
+
# that it has the proper type.
|
11
|
+
class PrimitiveCoercer < DryTypeCoercer
|
12
|
+
MAPPING = {
|
13
|
+
Grape::API::Boolean => DryTypes::Params::Bool,
|
14
|
+
BigDecimal => DryTypes::Params::Decimal,
|
15
|
+
|
16
|
+
# unfortunately, a +Params+ scope doesn't contain String
|
17
|
+
String => DryTypes::Coercible::String
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
STRICT_MAPPING = {
|
21
|
+
Grape::API::Boolean => DryTypes::Strict::Bool,
|
22
|
+
BigDecimal => DryTypes::Strict::Decimal
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
def initialize(type, strict = false)
|
26
|
+
super
|
27
|
+
|
28
|
+
@type = type
|
29
|
+
|
30
|
+
@coercer = if strict
|
31
|
+
STRICT_MAPPING.fetch(type) { scope.const_get(type.name) }
|
32
|
+
else
|
33
|
+
MAPPING.fetch(type) { scope.const_get(type.name) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(val)
|
38
|
+
return InvalidValue.new if reject?(val)
|
39
|
+
return nil if val.nil? || treat_as_nil?(val)
|
40
|
+
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
attr_reader :type
|
47
|
+
|
48
|
+
# This method maintains logic which was defined by Virtus. For example,
|
49
|
+
# dry-types is ok to convert an array or a hash to a string, it is supported,
|
50
|
+
# but Virtus wouldn't accept it. So, this method only exists to not introduce
|
51
|
+
# breaking changes.
|
52
|
+
def reject?(val)
|
53
|
+
(val.is_a?(Array) && type == String) ||
|
54
|
+
(val.is_a?(String) && type == Hash) ||
|
55
|
+
(val.is_a?(Hash) && type == String)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Dry-Types treats an empty string as invalid. However, Grape considers an empty string as
|
59
|
+
# absence of a value and coerces it into nil. See a discussion there
|
60
|
+
# https://github.com/ruby-grape/grape/pull/2045
|
61
|
+
def treat_as_nil?(val)
|
62
|
+
val == '' && type != String
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
require_relative 'array_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 < ArrayCoercer
|
12
|
+
register_collection Set
|
13
|
+
|
14
|
+
def initialize(type, strict = false)
|
15
|
+
super
|
16
|
+
|
17
|
+
@coercer = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(value)
|
21
|
+
return InvalidValue.new unless value.is_a?(Array)
|
22
|
+
|
23
|
+
coerce_elements(value)
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def coerce_elements(collection)
|
29
|
+
collection.each_with_object(Set.new) do |elem, memo|
|
30
|
+
coerced_elem = elem_coercer.call(elem)
|
31
|
+
|
32
|
+
return coerced_elem if coerced_elem.is_a?(InvalidValue)
|
33
|
+
|
34
|
+
memo.add(coerced_elem)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
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,8 +32,8 @@ 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
|
34
|
-
return
|
35
|
+
def call(value)
|
36
|
+
return unless value.is_a? Array
|
35
37
|
|
36
38
|
value =
|
37
39
|
if @method
|
@@ -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
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
class Base
|
@@ -17,6 +19,7 @@ module Grape
|
|
17
19
|
@required = required
|
18
20
|
@scope = scope
|
19
21
|
@fail_fast = opts[:fail_fast] || false
|
22
|
+
@allow_blank = opts[:allow_blank] || false
|
20
23
|
end
|
21
24
|
|
22
25
|
# Validates a given request.
|
@@ -40,12 +43,12 @@ module Grape
|
|
40
43
|
# there may be more than one error per field
|
41
44
|
array_errors = []
|
42
45
|
|
43
|
-
attributes.each do |
|
44
|
-
next if !@scope.required? &&
|
45
|
-
next unless @scope.meets_dependency?(
|
46
|
+
attributes.each do |val, attr_name, empty_val|
|
47
|
+
next if !@scope.required? && empty_val
|
48
|
+
next unless @scope.meets_dependency?(val, params)
|
46
49
|
begin
|
47
|
-
if @required ||
|
48
|
-
validate_param!(attr_name,
|
50
|
+
if @required || val.respond_to?(:key?) && val.key?(attr_name)
|
51
|
+
validate_param!(attr_name, val)
|
49
52
|
end
|
50
53
|
rescue Grape::Exceptions::Validation => e
|
51
54
|
array_errors << e
|
@@ -1,9 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
class API
|
3
|
-
|
5
|
+
class Boolean
|
6
|
+
def self.build(val)
|
7
|
+
return nil if val != true && val != false
|
8
|
+
|
9
|
+
new
|
10
|
+
end
|
11
|
+
end
|
4
12
|
|
5
13
|
class Instance
|
6
|
-
Boolean =
|
14
|
+
Boolean = Grape::API::Boolean
|
7
15
|
end
|
8
16
|
end
|
9
17
|
|
@@ -11,7 +19,12 @@ module Grape
|
|
11
19
|
class CoerceValidator < Base
|
12
20
|
def initialize(*_args)
|
13
21
|
super
|
14
|
-
|
22
|
+
|
23
|
+
@converter = if type.is_a?(Grape::Validations::Types::VariantCollectionCoercer)
|
24
|
+
type
|
25
|
+
else
|
26
|
+
Types.build_coercer(type, method: @option[:method])
|
27
|
+
end
|
15
28
|
end
|
16
29
|
|
17
30
|
def validate(request)
|
@@ -19,10 +32,23 @@ module Grape
|
|
19
32
|
end
|
20
33
|
|
21
34
|
def validate_param!(attr_name, params)
|
22
|
-
raise
|
23
|
-
|
35
|
+
raise validation_exception(attr_name) unless params.is_a? Hash
|
36
|
+
|
24
37
|
new_value = coerce_value(params[attr_name])
|
25
|
-
|
38
|
+
|
39
|
+
raise validation_exception(attr_name) unless valid_type?(new_value)
|
40
|
+
|
41
|
+
# Don't assign a value if it is identical. It fixes a problem with Hashie::Mash
|
42
|
+
# which looses wrappers for hashes and arrays after reassigning values
|
43
|
+
#
|
44
|
+
# h = Hashie::Mash.new(list: [1, 2, 3, 4])
|
45
|
+
# => #<Hashie::Mash list=#<Hashie::Array [1, 2, 3, 4]>>
|
46
|
+
# list = h.list
|
47
|
+
# h[:list] = list
|
48
|
+
# h
|
49
|
+
# => #<Hashie::Mash list=[1, 2, 3, 4]>
|
50
|
+
return if params[attr_name].class == new_value.class && params[attr_name] == new_value
|
51
|
+
|
26
52
|
params[attr_name] = new_value
|
27
53
|
end
|
28
54
|
|
@@ -33,32 +59,17 @@ module Grape
|
|
33
59
|
#
|
34
60
|
# See {Types.build_coercer}
|
35
61
|
#
|
36
|
-
# @return [
|
62
|
+
# @return [Object]
|
37
63
|
attr_reader :converter
|
38
64
|
|
39
65
|
def valid_type?(val)
|
40
|
-
|
41
|
-
return false if val.instance_of?(Types::InvalidValue)
|
42
|
-
|
43
|
-
# Allow nil, to ignore when a parameter is absent
|
44
|
-
return true if val.nil?
|
45
|
-
|
46
|
-
converter.value_coerced? val
|
66
|
+
!val.is_a?(Types::InvalidValue)
|
47
67
|
end
|
48
68
|
|
49
69
|
def coerce_value(val)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
return val || Set.new if type == Set
|
54
|
-
return val || {} if type == Hash
|
55
|
-
end
|
56
|
-
|
57
|
-
converter.coerce(val)
|
58
|
-
|
59
|
-
# not the prettiest but some invalid coercion can currently trigger
|
60
|
-
# errors in Virtus (see coerce_spec.rb:75)
|
61
|
-
rescue
|
70
|
+
converter.call(val)
|
71
|
+
# Some custom types might fail, so it should be treated as an invalid value
|
72
|
+
rescue StandardError
|
62
73
|
Types::InvalidValue.new
|
63
74
|
end
|
64
75
|
|
@@ -69,9 +80,8 @@ module Grape
|
|
69
80
|
@option[:type].is_a?(Hash) ? @option[:type][:value] : @option[:type]
|
70
81
|
end
|
71
82
|
|
72
|
-
def
|
73
|
-
|
74
|
-
!valid_type?(value) || converter.coercer.respond_to?(:method) && !converter.is_a?(Grape::Validations::Types::Json)
|
83
|
+
def validation_exception(attr_name)
|
84
|
+
Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:coerce))
|
75
85
|
end
|
76
86
|
end
|
77
87
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
class DefaultValidator < Base
|
@@ -7,7 +9,6 @@ module Grape
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def validate_param!(attr_name, params)
|
10
|
-
return if params.key? attr_name
|
11
12
|
params[attr_name] = if @default.is_a? Proc
|
12
13
|
@default.call
|
13
14
|
elsif @default.frozen? || !duplicatable?(@default)
|
@@ -1,11 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'grape/validations/validators/multiple_params_base'
|
2
4
|
|
3
5
|
module Grape
|
4
6
|
module Validations
|
5
7
|
class ExactlyOneOfValidator < MultipleParamsBase
|
6
8
|
def validate_params!(params)
|
7
|
-
|
8
|
-
|
9
|
+
keys = keys_in_common(params)
|
10
|
+
return if keys.length == 1
|
11
|
+
raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:exactly_one)) if keys.length.zero?
|
12
|
+
raise Grape::Exceptions::Validation.new(params: keys, message: message(:mutual_exclusion))
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
class ExceptValuesValidator < Base
|
@@ -13,7 +15,7 @@ module Grape
|
|
13
15
|
return if excepts.nil?
|
14
16
|
|
15
17
|
param_array = params[attr_name].nil? ? [nil] : Array.wrap(params[attr_name])
|
16
|
-
raise Grape::Exceptions::Validation
|
18
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:except_values)) if param_array.any? { |param| excepts.include?(param) }
|
17
19
|
end
|
18
20
|
end
|
19
21
|
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.length <= 1
|
9
|
-
raise Grape::Exceptions::Validation
|
11
|
+
raise Grape::Exceptions::Validation.new(params: keys, message: message(:mutual_exclusion))
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
class PresenceValidator < Base
|
4
6
|
def validate_param!(attr_name, params)
|
5
7
|
return if params.respond_to?(:key?) && params.key?(attr_name)
|
6
|
-
raise Grape::Exceptions::Validation
|
8
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:presence))
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
5
|
class RegexpValidator < Base
|
4
6
|
def validate_param!(attr_name, params)
|
5
7
|
return unless params.respond_to?(:key?) && params.key?(attr_name)
|
6
|
-
return if Array.wrap(params[attr_name]).all? { |param| param.nil? ||
|
7
|
-
raise Grape::Exceptions::Validation
|
8
|
+
return if Array.wrap(params[attr_name]).all? { |param| param.nil? || param.to_s.match?((options_key?(:value) ? @option[:value] : @option)) }
|
9
|
+
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:regexp))
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|