grape 1.2.5 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +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
 
| 
         @@ -1,21 +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 for custom types that do not otherwise
         
     | 
| 
       7 
     | 
    
         
            -
                  # satisfy the requirements for +Virtus::Attribute::coerce+
         
     | 
| 
       8 
     | 
    
         
            -
                  # and +Virtus::Attribute::value_coerced?+ to work
         
     | 
| 
       9 
     | 
    
         
            -
                  # as expected.
         
     | 
| 
       10 
     | 
    
         
            -
                  #
         
     | 
| 
       11 
     | 
    
         
            -
                  # Subclasses of +Virtus::Attribute+ or +Axiom::Types::Type+
         
     | 
| 
       12 
     | 
    
         
            -
                  # (or for which an axiom type can be inferred, i.e. the
         
     | 
| 
       13 
     | 
    
         
            -
                  # primitives, +Date+, +Time+, etc.) do not need any such
         
     | 
| 
       14 
     | 
    
         
            -
                  # coercer to be passed with them.
         
     | 
| 
       15 
     | 
    
         
            -
                  #
         
     | 
| 
       16 
     | 
    
         
            -
                  # Coercion
         
     | 
| 
       17 
     | 
    
         
            -
                  # --------
         
     | 
| 
       18 
     | 
    
         
            -
                  #
         
     | 
| 
       19 
6 
     | 
    
         
             
                  # This class will detect type classes that implement
         
     | 
| 
       20 
7 
     | 
    
         
             
                  # a class-level +parse+ method. The method should accept one
         
     | 
| 
       21 
8 
     | 
    
         
             
                  # +String+ argument and should return the value coerced to
         
     | 
| 
         @@ -30,14 +17,14 @@ module Grape 
     | 
|
| 
       30 
17 
     | 
    
         
             
                  # Type Checking
         
     | 
| 
       31 
18 
     | 
    
         
             
                  # -------------
         
     | 
| 
       32 
19 
     | 
    
         
             
                  #
         
     | 
| 
       33 
     | 
    
         
            -
                  # Calls to + 
     | 
| 
      
 20 
     | 
    
         
            +
                  # Calls to +coerced?+ will consult this class to check
         
     | 
| 
       34 
21 
     | 
    
         
             
                  # that the coerced value produced above is in fact of the
         
     | 
| 
       35 
22 
     | 
    
         
             
                  # expected type. By default this class performs a basic check
         
     | 
| 
       36 
23 
     | 
    
         
             
                  # against the type supplied, but this behaviour will be
         
     | 
| 
       37 
24 
     | 
    
         
             
                  # overridden if the class implements a class-level
         
     | 
| 
       38 
25 
     | 
    
         
             
                  # +coerced?+ or +parsed?+ method. This method
         
     | 
| 
       39 
26 
     | 
    
         
             
                  # will receive a single parameter that is the coerced value
         
     | 
| 
       40 
     | 
    
         
            -
                  # and should return +true+  
     | 
| 
      
 27 
     | 
    
         
            +
                  # and should return +true+ if the value meets type expectations.
         
     | 
| 
       41 
28 
     | 
    
         
             
                  # Arbitrary assertions may be made here but the grape validation
         
     | 
| 
       42 
29 
     | 
    
         
             
                  # system should be preferred.
         
     | 
| 
       43 
30 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -46,15 +33,6 @@ module Grape 
     | 
|
| 
       46 
33 
     | 
    
         
             
                  # contract as +coerced?+, and must be supplied with a coercion
         
     | 
| 
       47 
34 
     | 
    
         
             
                  # +method+.
         
     | 
| 
       48 
35 
     | 
    
         
             
                  class CustomTypeCoercer
         
     | 
| 
       49 
     | 
    
         
            -
                    # Uses +Virtus::Attribute.build+ to build a new
         
     | 
| 
       50 
     | 
    
         
            -
                    # attribute that makes use of this class for
         
     | 
| 
       51 
     | 
    
         
            -
                    # coercion and type validation logic.
         
     | 
| 
       52 
     | 
    
         
            -
                    #
         
     | 
| 
       53 
     | 
    
         
            -
                    # @return [Virtus::Attribute]
         
     | 
| 
       54 
     | 
    
         
            -
                    def self.build(type, method = nil)
         
     | 
| 
       55 
     | 
    
         
            -
                      Virtus::Attribute.build(type, coercer: new(type, method))
         
     | 
| 
       56 
     | 
    
         
            -
                    end
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
36 
     | 
    
         
             
                    # A new coercer for the given type specification
         
     | 
| 
       59 
37 
     | 
    
         
             
                    # and coercion method.
         
     | 
| 
       60 
38 
     | 
    
         
             
                    #
         
     | 
| 
         @@ -64,37 +42,25 @@ module Grape 
     | 
|
| 
       64 
42 
     | 
    
         
             
                    #   optional coercion method. See class docs.
         
     | 
| 
       65 
43 
     | 
    
         
             
                    def initialize(type, method = nil)
         
     | 
| 
       66 
44 
     | 
    
         
             
                      coercion_method = infer_coercion_method type, method
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
45 
     | 
    
         
             
                      @method = enforce_symbolized_keys type, coercion_method
         
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
46 
     | 
    
         
             
                      @type_check = infer_type_check(type)
         
     | 
| 
       71 
47 
     | 
    
         
             
                    end
         
     | 
| 
       72 
48 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
                    #  
     | 
| 
       74 
     | 
    
         
            -
                    # +Virtus::Attribute::coerce+ in order to coerce
         
     | 
| 
       75 
     | 
    
         
            -
                    # the given value.
         
     | 
| 
      
 49 
     | 
    
         
            +
                    # Coerces the given value.
         
     | 
| 
       76 
50 
     | 
    
         
             
                    #
         
     | 
| 
       77 
51 
     | 
    
         
             
                    # @param value [String] value to be coerced, in grape
         
     | 
| 
       78 
52 
     | 
    
         
             
                    #   this should always be a string.
         
     | 
| 
       79 
53 
     | 
    
         
             
                    # @return [Object] the coerced result
         
     | 
| 
       80 
     | 
    
         
            -
                    def call( 
     | 
| 
       81 
     | 
    
         
            -
                       
     | 
| 
      
 54 
     | 
    
         
            +
                    def call(val)
         
     | 
| 
      
 55 
     | 
    
         
            +
                      return if val.nil?
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                      coerced_val = @method.call(val)
         
     | 
| 
      
 58 
     | 
    
         
            +
                      return InvalidValue.new unless coerced?(coerced_val)
         
     | 
| 
      
 59 
     | 
    
         
            +
                      coerced_val
         
     | 
| 
       82 
60 
     | 
    
         
             
                    end
         
     | 
| 
       83 
61 
     | 
    
         | 
| 
       84 
     | 
    
         
            -
                     
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                    # assert that the value has been coerced successfully.
         
     | 
| 
       87 
     | 
    
         
            -
                    #
         
     | 
| 
       88 
     | 
    
         
            -
                    # @param _primitive [Axiom::Types::Type] primitive type
         
     | 
| 
       89 
     | 
    
         
            -
                    #   for the coercion as detected by axiom-types' inference
         
     | 
| 
       90 
     | 
    
         
            -
                    #   system. For custom types this is typically not much use
         
     | 
| 
       91 
     | 
    
         
            -
                    #   (i.e. it is +Axiom::Types::Object+) unless special
         
     | 
| 
       92 
     | 
    
         
            -
                    #   inference rules have been declared for the type.
         
     | 
| 
       93 
     | 
    
         
            -
                    # @param value [Object] a coerced result returned from {#call}
         
     | 
| 
       94 
     | 
    
         
            -
                    # @return [true,false] whether or not the coerced value
         
     | 
| 
       95 
     | 
    
         
            -
                    #   satisfies type requirements.
         
     | 
| 
       96 
     | 
    
         
            -
                    def success?(_primitive, value)
         
     | 
| 
       97 
     | 
    
         
            -
                      @type_check.call value
         
     | 
| 
      
 62 
     | 
    
         
            +
                    def coerced?(val)
         
     | 
| 
      
 63 
     | 
    
         
            +
                      val.nil? || @type_check.call(val)
         
     | 
| 
       98 
64 
     | 
    
         
             
                    end
         
     | 
| 
       99 
65 
     | 
    
         | 
| 
       100 
66 
     | 
    
         
             
                    private
         
     | 
| 
         @@ -160,8 +126,8 @@ module Grape 
     | 
|
| 
       160 
126 
     | 
    
         
             
                      # Collections have all values processed individually
         
     | 
| 
       161 
127 
     | 
    
         
             
                      if [Array, Set].include?(type)
         
     | 
| 
       162 
128 
     | 
    
         
             
                        lambda do |val|
         
     | 
| 
       163 
     | 
    
         
            -
                          method.call(val).tap do | 
     | 
| 
       164 
     | 
    
         
            -
                             
     | 
| 
      
 129 
     | 
    
         
            +
                          method.call(val).tap do |new_val|
         
     | 
| 
      
 130 
     | 
    
         
            +
                            new_val.map do |item|
         
     | 
| 
       165 
131 
     | 
    
         
             
                              item.is_a?(Hash) ? symbolize_keys(item) : item
         
     | 
| 
       166 
132 
     | 
    
         
             
                            end
         
     | 
| 
       167 
133 
     | 
    
         
             
                          end
         
     | 
| 
         @@ -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,76 @@ 
     | 
|
| 
      
 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 
     | 
    
         
            +
                    class << self
         
     | 
| 
      
 21 
     | 
    
         
            +
                      # Registers a collection coercer which could be found by a type,
         
     | 
| 
      
 22 
     | 
    
         
            +
                      # see +collection_coercer_for+ method below. This method is meant for inheritors.
         
     | 
| 
      
 23 
     | 
    
         
            +
                      def register_collection(type)
         
     | 
| 
      
 24 
     | 
    
         
            +
                        DryTypeCoercer.collection_coercers[type] = self
         
     | 
| 
      
 25 
     | 
    
         
            +
                      end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                      # Returns a collection coercer which corresponds to a given type.
         
     | 
| 
      
 28 
     | 
    
         
            +
                      # Example:
         
     | 
| 
      
 29 
     | 
    
         
            +
                      #
         
     | 
| 
      
 30 
     | 
    
         
            +
                      #    collection_coercer_for(Array)
         
     | 
| 
      
 31 
     | 
    
         
            +
                      #    #=> Grape::Validations::Types::ArrayCoercer
         
     | 
| 
      
 32 
     | 
    
         
            +
                      def collection_coercer_for(type)
         
     | 
| 
      
 33 
     | 
    
         
            +
                        collection_coercers[type]
         
     | 
| 
      
 34 
     | 
    
         
            +
                      end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                      # Returns an instance of a coercer for a given type
         
     | 
| 
      
 37 
     | 
    
         
            +
                      def coercer_instance_for(type, strict = false)
         
     | 
| 
      
 38 
     | 
    
         
            +
                        return PrimitiveCoercer.new(type, strict) if type.class == Class
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                        # in case of a collection (Array[Integer]) the type is an instance of a collection,
         
     | 
| 
      
 41 
     | 
    
         
            +
                        # so we need to figure out the actual type
         
     | 
| 
      
 42 
     | 
    
         
            +
                        collection_coercer_for(type.class).new(type, strict)
         
     | 
| 
      
 43 
     | 
    
         
            +
                      end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                      protected
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                      def collection_coercers
         
     | 
| 
      
 48 
     | 
    
         
            +
                        @collection_coercers ||= {}
         
     | 
| 
      
 49 
     | 
    
         
            +
                      end
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    def initialize(type, strict = false)
         
     | 
| 
      
 53 
     | 
    
         
            +
                      @type = type
         
     | 
| 
      
 54 
     | 
    
         
            +
                      @strict = strict
         
     | 
| 
      
 55 
     | 
    
         
            +
                      @scope = strict ? DryTypes::Strict : DryTypes::Params
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    # Coerces the given value to a type which was specified during
         
     | 
| 
      
 59 
     | 
    
         
            +
                    # initialization as a type argument.
         
     | 
| 
      
 60 
     | 
    
         
            +
                    #
         
     | 
| 
      
 61 
     | 
    
         
            +
                    # @param val [Object]
         
     | 
| 
      
 62 
     | 
    
         
            +
                    def call(val)
         
     | 
| 
      
 63 
     | 
    
         
            +
                      return if val.nil?
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                      @coercer[val]
         
     | 
| 
      
 66 
     | 
    
         
            +
                    rescue Dry::Types::CoercionError => _e
         
     | 
| 
      
 67 
     | 
    
         
            +
                      InvalidValue.new
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    protected
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                    attr_reader :scope, :type, :strict
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,25 +1,29 @@ 
     | 
|
| 
      
 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 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
      
 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 
     | 
    
         
            +
                    class << self
         
     | 
| 
      
 11 
     | 
    
         
            +
                      def parse(input)
         
     | 
| 
      
 12 
     | 
    
         
            +
                        return if input.nil?
         
     | 
| 
      
 13 
     | 
    
         
            +
                        return InvalidValue.new unless parsed?(input)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                        # Processing of multipart file objects
         
     | 
| 
      
 16 
     | 
    
         
            +
                        # is already taken care of by Rack::Request.
         
     | 
| 
      
 17 
     | 
    
         
            +
                        # Nothing to do here.
         
     | 
| 
      
 18 
     | 
    
         
            +
                        input
         
     | 
| 
      
 19 
     | 
    
         
            +
                      end
         
     | 
| 
       17 
20 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
                      def parsed?(value)
         
     | 
| 
      
 22 
     | 
    
         
            +
                        # Rack::Request creates a Hash with filename,
         
     | 
| 
      
 23 
     | 
    
         
            +
                        # content type and an IO object. Do a bit of basic
         
     | 
| 
      
 24 
     | 
    
         
            +
                        # duck-typing.
         
     | 
| 
      
 25 
     | 
    
         
            +
                        value.is_a?(::Hash) && value.key?(:tempfile) && value[:tempfile].is_a?(Tempfile)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
       23 
27 
     | 
    
         
             
                    end
         
     | 
| 
       24 
28 
     | 
    
         
             
                  end
         
     | 
| 
       25 
29 
     | 
    
         
             
                end
         
     | 
| 
         @@ -1,43 +1,48 @@ 
     | 
|
| 
      
 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 
     | 
    
         
            -
                     
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                       
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                      JSON.parse(input, symbolize_names: true)
         
     | 
| 
       22 
     | 
    
         
            -
                    end
         
     | 
| 
      
 14 
     | 
    
         
            +
                  class Json
         
     | 
| 
      
 15 
     | 
    
         
            +
                    class << self
         
     | 
| 
      
 16 
     | 
    
         
            +
                      # Coerce the input into a JSON-like data structure.
         
     | 
| 
      
 17 
     | 
    
         
            +
                      #
         
     | 
| 
      
 18 
     | 
    
         
            +
                      # @param input [String] a JSON-encoded parameter value
         
     | 
| 
      
 19 
     | 
    
         
            +
                      # @return [Hash,Array<Hash>,nil]
         
     | 
| 
      
 20 
     | 
    
         
            +
                      def parse(input)
         
     | 
| 
      
 21 
     | 
    
         
            +
                        return input if parsed?(input)
         
     | 
| 
       23 
22 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                    # @return [true,false]
         
     | 
| 
       29 
     | 
    
         
            -
                    def value_coerced?(value)
         
     | 
| 
       30 
     | 
    
         
            -
                      value.is_a?(::Hash) || coerced_collection?(value)
         
     | 
| 
       31 
     | 
    
         
            -
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                        # Allow nulls and blank strings
         
     | 
| 
      
 24 
     | 
    
         
            +
                        return if input.nil? || input.match?(/^\s*$/)
         
     | 
| 
      
 25 
     | 
    
         
            +
                        JSON.parse(input, symbolize_names: true)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
       32 
27 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
      
 28 
     | 
    
         
            +
                      # Checks that the input was parsed successfully
         
     | 
| 
      
 29 
     | 
    
         
            +
                      # and isn't something odd such as an array of primitives.
         
     | 
| 
      
 30 
     | 
    
         
            +
                      #
         
     | 
| 
      
 31 
     | 
    
         
            +
                      # @param value [Object] result of {#parse}
         
     | 
| 
      
 32 
     | 
    
         
            +
                      # @return [true,false]
         
     | 
| 
      
 33 
     | 
    
         
            +
                      def parsed?(value)
         
     | 
| 
      
 34 
     | 
    
         
            +
                        value.is_a?(::Hash) || coerced_collection?(value)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      end
         
     | 
| 
       34 
36 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                       
     | 
| 
      
 37 
     | 
    
         
            +
                      protected
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                      # Is the value an array of JSON-like objects?
         
     | 
| 
      
 40 
     | 
    
         
            +
                      #
         
     | 
| 
      
 41 
     | 
    
         
            +
                      # @param value [Object] result of {#parse}
         
     | 
| 
      
 42 
     | 
    
         
            +
                      # @return [true,false]
         
     | 
| 
      
 43 
     | 
    
         
            +
                      def coerced_collection?(value)
         
     | 
| 
      
 44 
     | 
    
         
            +
                        value.is_a?(::Array) && value.all? { |i| i.is_a? ::Hash }
         
     | 
| 
      
 45 
     | 
    
         
            +
                      end
         
     | 
| 
       41 
46 
     | 
    
         
             
                    end
         
     | 
| 
       42 
47 
     | 
    
         
             
                  end
         
     | 
| 
       43 
48 
     | 
    
         | 
| 
         @@ -46,18 +51,20 @@ module Grape 
     | 
|
| 
       46 
51 
     | 
    
         
             
                  # objects and arrays of objects, but wraps single objects
         
     | 
| 
       47 
52 
     | 
    
         
             
                  # in an Array.
         
     | 
| 
       48 
53 
     | 
    
         
             
                  class JsonArray < Json
         
     | 
| 
       49 
     | 
    
         
            -
                     
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                       
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
      
 54 
     | 
    
         
            +
                    class << self
         
     | 
| 
      
 55 
     | 
    
         
            +
                      # See {Json#parse}. Wraps single objects in an array.
         
     | 
| 
      
 56 
     | 
    
         
            +
                      #
         
     | 
| 
      
 57 
     | 
    
         
            +
                      # @param input [String] JSON-encoded parameter value
         
     | 
| 
      
 58 
     | 
    
         
            +
                      # @return [Array<Hash>]
         
     | 
| 
      
 59 
     | 
    
         
            +
                      def parse(input)
         
     | 
| 
      
 60 
     | 
    
         
            +
                        json = super
         
     | 
| 
      
 61 
     | 
    
         
            +
                        Array.wrap(json) unless json.nil?
         
     | 
| 
      
 62 
     | 
    
         
            +
                      end
         
     | 
| 
       57 
63 
     | 
    
         | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
      
 64 
     | 
    
         
            +
                      # See {Json#coerced_collection?}
         
     | 
| 
      
 65 
     | 
    
         
            +
                      def parsed?(value)
         
     | 
| 
      
 66 
     | 
    
         
            +
                        coerced_collection? value
         
     | 
| 
      
 67 
     | 
    
         
            +
                      end
         
     | 
| 
       61 
68 
     | 
    
         
             
                    end
         
     | 
| 
       62 
69 
     | 
    
         
             
                  end
         
     | 
| 
       63 
70 
     | 
    
         
             
                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
         
     |