grape 1.8.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +517 -1
- data/CONTRIBUTING.md +19 -11
- data/README.md +841 -545
- data/UPGRADING.md +1553 -7
- data/grape.gemspec +11 -14
- data/lib/grape/api/instance.rb +77 -160
- data/lib/grape/api.rb +75 -107
- data/lib/grape/content_types.rb +67 -9
- data/lib/grape/cookies.rb +28 -25
- data/lib/grape/declared_params_handler.rb +116 -0
- data/lib/grape/dry_types.rb +48 -6
- data/lib/grape/dsl/callbacks.rb +8 -58
- data/lib/grape/dsl/declared.rb +35 -0
- data/lib/grape/dsl/desc.rb +25 -63
- data/lib/grape/dsl/entity.rb +106 -0
- data/lib/grape/dsl/headers.rb +2 -2
- data/lib/grape/dsl/helpers.rb +83 -64
- data/lib/grape/dsl/inside_route.rb +69 -296
- data/lib/grape/dsl/logger.rb +4 -9
- data/lib/grape/dsl/middleware.rb +22 -40
- data/lib/grape/dsl/parameters.rb +88 -94
- data/lib/grape/dsl/request_response.rb +143 -147
- data/lib/grape/dsl/rescue_options.rb +25 -0
- data/lib/grape/dsl/routing.rb +333 -191
- data/lib/grape/dsl/settings.rb +29 -135
- data/lib/grape/dsl/validations.rb +39 -32
- data/lib/grape/dsl/version_options.rb +23 -0
- data/lib/grape/endpoint/options.rb +25 -0
- data/lib/grape/endpoint.rb +319 -269
- data/lib/grape/{util/env.rb → env.rb} +8 -8
- data/lib/grape/error_formatter/base.rb +57 -21
- data/lib/grape/error_formatter/json.rb +13 -15
- data/lib/grape/error_formatter/serializable_hash.rb +7 -0
- data/lib/grape/error_formatter/txt.rb +12 -18
- data/lib/grape/error_formatter/xml.rb +3 -13
- data/lib/grape/error_formatter.rb +9 -25
- data/lib/grape/exceptions/base.rb +22 -58
- data/lib/grape/exceptions/error_response.rb +48 -0
- data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
- data/lib/grape/exceptions/internal_server_error.rb +16 -0
- data/lib/grape/exceptions/invalid_accept_header.rb +1 -1
- data/lib/grape/exceptions/invalid_formatter.rb +1 -1
- data/lib/grape/exceptions/invalid_message_body.rb +1 -1
- data/lib/grape/exceptions/invalid_version_header.rb +1 -1
- data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
- data/lib/grape/exceptions/method_not_allowed.rb +1 -1
- data/lib/grape/exceptions/missing_group_type.rb +0 -2
- data/lib/grape/exceptions/missing_mime_type.rb +1 -1
- data/lib/grape/exceptions/request_error.rb +11 -0
- data/lib/grape/exceptions/unknown_auth_strategy.rb +11 -0
- data/lib/grape/exceptions/unknown_error_formatter.rb +11 -0
- data/lib/grape/exceptions/unknown_parameter.rb +1 -1
- data/lib/grape/exceptions/unknown_params_builder.rb +11 -0
- data/lib/grape/exceptions/unknown_validator.rb +1 -1
- data/lib/grape/exceptions/unsupported_group_type.rb +0 -2
- data/lib/grape/exceptions/validation.rb +28 -11
- data/lib/grape/exceptions/validation_array_errors.rb +5 -0
- data/lib/grape/exceptions/validation_errors.rb +22 -26
- data/lib/grape/formatter/base.rb +16 -0
- data/lib/grape/formatter/json.rb +5 -6
- data/lib/grape/formatter/serializable_hash.rb +7 -10
- data/lib/grape/formatter/txt.rb +3 -5
- data/lib/grape/formatter/xml.rb +4 -6
- data/lib/grape/formatter.rb +7 -25
- data/lib/grape/json.rb +46 -0
- data/lib/grape/locale/en.yml +44 -42
- data/lib/grape/middleware/auth/base.rb +11 -33
- data/lib/grape/middleware/auth/dsl.rb +12 -34
- data/lib/grape/middleware/auth/strategies.rb +1 -2
- data/lib/grape/middleware/base.rb +56 -33
- data/lib/grape/middleware/error.rb +290 -91
- data/lib/grape/middleware/formatter.rb +164 -106
- data/lib/grape/middleware/precomputed_content_types.rb +51 -0
- data/lib/grape/middleware/stack.rb +38 -40
- data/lib/grape/middleware/versioner/accept_version_header.rb +6 -33
- data/lib/grape/middleware/versioner/base.rb +66 -0
- data/lib/grape/middleware/versioner/header.rb +44 -129
- data/lib/grape/middleware/versioner/param.rb +4 -25
- data/lib/grape/middleware/versioner/path.rb +48 -25
- data/lib/grape/middleware/versioner.rb +7 -14
- data/lib/grape/mountable.rb +22 -0
- data/lib/grape/namespace.rb +21 -14
- data/lib/grape/params_builder/base.rb +20 -0
- data/lib/grape/params_builder/hash.rb +11 -0
- data/lib/grape/params_builder/hash_with_indifferent_access.rb +11 -0
- data/lib/grape/params_builder/hashie_mash.rb +11 -0
- data/lib/grape/params_builder.rb +15 -0
- data/lib/grape/parser/base.rb +16 -0
- data/lib/grape/parser/json.rb +6 -8
- data/lib/grape/parser/xml.rb +6 -8
- data/lib/grape/parser.rb +5 -23
- data/lib/grape/path.rb +8 -94
- data/lib/grape/precompiled_json.rb +50 -0
- data/lib/grape/railtie.rb +9 -0
- data/lib/grape/request.rb +200 -26
- data/lib/grape/router/base_route.rb +85 -0
- data/lib/grape/router/greedy_route.rb +30 -0
- data/lib/grape/router/mustermann_pattern.rb +44 -0
- data/lib/grape/router/pattern/path.rb +78 -0
- data/lib/grape/router/pattern.rb +77 -35
- data/lib/grape/router/route.rb +79 -60
- data/lib/grape/router.rb +128 -104
- data/lib/grape/serve_stream/file_body.rb +7 -0
- data/lib/grape/serve_stream/sendfile_response.rb +3 -5
- data/lib/grape/serve_stream/stream_response.rb +7 -0
- data/lib/grape/testing.rb +33 -0
- data/lib/grape/util/api_description.rb +67 -0
- data/lib/grape/util/cache.rb +22 -5
- data/lib/grape/util/deep_freeze.rb +34 -0
- data/lib/grape/util/endpoint_configuration.rb +1 -1
- data/lib/grape/util/freeze_on_new.rb +20 -0
- data/lib/grape/util/header.rb +13 -0
- data/lib/grape/util/inheritable_setting.rb +777 -39
- data/lib/grape/util/lazy/base.rb +16 -0
- data/lib/grape/util/lazy/block.rb +22 -0
- data/lib/grape/util/lazy/value.rb +31 -0
- data/lib/grape/util/lazy/value_array.rb +21 -0
- data/lib/grape/util/lazy/value_enumerable.rb +31 -0
- data/lib/grape/util/lazy/value_hash.rb +21 -0
- data/lib/grape/util/media_type.rb +74 -0
- data/lib/grape/util/path_normalizer.rb +37 -0
- data/lib/grape/util/registry.rb +37 -0
- data/lib/grape/util/shadowed_rescue_handlers.rb +49 -0
- data/lib/grape/util/stackable_values.rb +40 -16
- data/lib/grape/util/translation.rb +42 -0
- data/lib/grape/validations/attributes_iterator.rb +61 -28
- data/lib/grape/validations/coerce_options.rb +21 -0
- data/lib/grape/validations/contract_scope.rb +29 -0
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/oneof_collector.rb +35 -0
- data/lib/grape/validations/param_scope_tracker.rb +62 -0
- data/lib/grape/validations/params_documentation.rb +52 -0
- data/lib/grape/validations/params_scope.rb +223 -306
- data/lib/grape/validations/shared_options.rb +19 -0
- data/lib/grape/validations/single_attribute_iterator.rb +6 -4
- data/lib/grape/validations/types/array_coercer.rb +7 -12
- data/lib/grape/validations/types/custom_type_coercer.rb +47 -85
- data/lib/grape/validations/types/custom_type_collection_coercer.rb +1 -1
- data/lib/grape/validations/types/dry_type_coercer.rb +17 -28
- data/lib/grape/validations/types/json.rb +1 -5
- data/lib/grape/validations/types/multiple_type_coercer.rb +5 -3
- data/lib/grape/validations/types/primitive_coercer.rb +14 -35
- data/lib/grape/validations/types/set_coercer.rb +1 -4
- data/lib/grape/validations/types/variant_collection_coercer.rb +16 -3
- data/lib/grape/validations/types.rb +29 -54
- data/lib/grape/validations/validations_spec.rb +164 -0
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +6 -3
- data/lib/grape/validations/validators/allow_blank_validator.rb +10 -5
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +5 -2
- data/lib/grape/validations/validators/base.rb +118 -37
- data/lib/grape/validations/validators/coerce_validator.rb +26 -38
- data/lib/grape/validations/validators/contract_scope_validator.rb +46 -0
- data/lib/grape/validations/validators/default_validator.rb +13 -16
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
- data/lib/grape/validations/validators/except_values_validator.rb +15 -5
- data/lib/grape/validations/validators/length_validator.rb +50 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +12 -9
- data/lib/grape/validations/validators/{mutual_exclusion_validator.rb → mutually_exclusive_validator.rb} +4 -2
- data/lib/grape/validations/validators/oneof_validator.rb +51 -0
- data/lib/grape/validations/validators/presence_validator.rb +4 -2
- data/lib/grape/validations/validators/regexp_validator.rb +11 -3
- data/lib/grape/validations/validators/same_as_validator.rb +7 -15
- data/lib/grape/validations/validators/values_validator.rb +36 -65
- data/lib/grape/validations.rb +8 -21
- data/lib/grape/version.rb +1 -2
- data/lib/grape/xml.rb +17 -0
- data/lib/grape.rb +96 -288
- metadata +83 -294
- data/lib/grape/api/helpers.rb +0 -9
- data/lib/grape/dsl/api.rb +0 -19
- data/lib/grape/dsl/configuration.rb +0 -15
- data/lib/grape/eager_load.rb +0 -20
- data/lib/grape/exceptions/empty_message_body.rb +0 -11
- data/lib/grape/exceptions/missing_option.rb +0 -11
- data/lib/grape/exceptions/too_many_multipart_files.rb +0 -11
- data/lib/grape/exceptions/unknown_options.rb +0 -11
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +0 -27
- data/lib/grape/extensions/hash.rb +0 -22
- data/lib/grape/extensions/hashie/mash.rb +0 -26
- data/lib/grape/http/headers.rb +0 -61
- data/lib/grape/middleware/globals.rb +0 -16
- data/lib/grape/middleware/helpers.rb +0 -12
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +0 -24
- data/lib/grape/router/attribute_translator.rb +0 -63
- data/lib/grape/types/invalid_value.rb +0 -8
- data/lib/grape/util/base_inheritable.rb +0 -43
- data/lib/grape/util/inheritable_values.rb +0 -31
- data/lib/grape/util/json.rb +0 -12
- data/lib/grape/util/lazy_block.rb +0 -27
- data/lib/grape/util/lazy_object.rb +0 -43
- data/lib/grape/util/lazy_value.rb +0 -91
- data/lib/grape/util/registrable.rb +0 -15
- data/lib/grape/util/reverse_stackable_values.rb +0 -20
- data/lib/grape/util/strict_hash_configuration.rb +0 -108
- data/lib/grape/util/xml.rb +0 -10
- data/lib/grape/validations/attributes_doc.rb +0 -58
- data/lib/grape/validations/types/build_coercer.rb +0 -94
- data/lib/grape/validations/validator_factory.rb +0 -15
- data/spec/grape/api/custom_validations_spec.rb +0 -213
- data/spec/grape/api/deeply_included_options_spec.rb +0 -56
- data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
- data/spec/grape/api/documentation_spec.rb +0 -59
- data/spec/grape/api/inherited_helpers_spec.rb +0 -114
- data/spec/grape/api/instance_spec.rb +0 -103
- data/spec/grape/api/invalid_format_spec.rb +0 -45
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
- data/spec/grape/api/nested_helpers_spec.rb +0 -50
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
- data/spec/grape/api/parameters_modification_spec.rb +0 -41
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
- data/spec/grape/api/recognize_path_spec.rb +0 -21
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
- data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
- data/spec/grape/api/shared_helpers_spec.rb +0 -36
- data/spec/grape/api_remount_spec.rb +0 -509
- data/spec/grape/api_spec.rb +0 -4356
- data/spec/grape/dsl/callbacks_spec.rb +0 -45
- data/spec/grape/dsl/desc_spec.rb +0 -98
- data/spec/grape/dsl/headers_spec.rb +0 -62
- data/spec/grape/dsl/helpers_spec.rb +0 -100
- data/spec/grape/dsl/inside_route_spec.rb +0 -531
- data/spec/grape/dsl/logger_spec.rb +0 -24
- data/spec/grape/dsl/middleware_spec.rb +0 -60
- data/spec/grape/dsl/parameters_spec.rb +0 -180
- data/spec/grape/dsl/request_response_spec.rb +0 -225
- data/spec/grape/dsl/routing_spec.rb +0 -275
- data/spec/grape/dsl/settings_spec.rb +0 -261
- data/spec/grape/dsl/validations_spec.rb +0 -55
- data/spec/grape/endpoint/declared_spec.rb +0 -846
- data/spec/grape/endpoint_spec.rb +0 -1085
- data/spec/grape/entity_spec.rb +0 -336
- data/spec/grape/exceptions/base_spec.rb +0 -81
- data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -185
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
- data/spec/grape/exceptions/missing_group_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_option_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -19
- data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
- data/spec/grape/exceptions/validation_spec.rb +0 -19
- data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
- data/spec/grape/grape_spec.rb +0 -9
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
- data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
- data/spec/grape/integration/rack_spec.rb +0 -51
- data/spec/grape/loading_spec.rb +0 -44
- data/spec/grape/middleware/auth/base_spec.rb +0 -31
- data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
- data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
- data/spec/grape/middleware/base_spec.rb +0 -221
- data/spec/grape/middleware/error_spec.rb +0 -85
- data/spec/grape/middleware/exception_spec.rb +0 -294
- data/spec/grape/middleware/formatter_spec.rb +0 -461
- data/spec/grape/middleware/globals_spec.rb +0 -30
- data/spec/grape/middleware/stack_spec.rb +0 -155
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
- data/spec/grape/middleware/versioner/header_spec.rb +0 -345
- data/spec/grape/middleware/versioner/param_spec.rb +0 -171
- data/spec/grape/middleware/versioner/path_spec.rb +0 -62
- data/spec/grape/middleware/versioner_spec.rb +0 -21
- data/spec/grape/named_api_spec.rb +0 -19
- data/spec/grape/parser_spec.rb +0 -86
- data/spec/grape/path_spec.rb +0 -252
- data/spec/grape/presenters/presenter_spec.rb +0 -71
- data/spec/grape/request_spec.rb +0 -126
- data/spec/grape/util/inheritable_setting_spec.rb +0 -242
- data/spec/grape/util/inheritable_values_spec.rb +0 -79
- data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
- data/spec/grape/util/stackable_values_spec.rb +0 -128
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
- data/spec/grape/validations/attributes_doc_spec.rb +0 -153
- data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -38
- data/spec/grape/validations/params_scope_spec.rb +0 -1420
- data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -56
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
- data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
- data/spec/grape/validations/types_spec.rb +0 -111
- data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
- data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
- data/spec/grape/validations/validators/base_spec.rb +0 -38
- data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
- data/spec/grape/validations/validators/default_spec.rb +0 -463
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
- data/spec/grape/validations/validators/except_values_spec.rb +0 -192
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
- data/spec/grape/validations/validators/presence_spec.rb +0 -315
- data/spec/grape/validations/validators/regexp_spec.rb +0 -161
- data/spec/grape/validations/validators/same_as_spec.rb +0 -57
- data/spec/grape/validations/validators/values_spec.rb +0 -733
- data/spec/grape/validations/validators/zh-CN.yml +0 -10
- data/spec/grape/validations_spec.rb +0 -2030
- data/spec/integration/eager_load/eager_load_spec.rb +0 -15
- data/spec/integration/multi_json/json_spec.rb +0 -7
- data/spec/integration/multi_xml/xml_spec.rb +0 -7
- data/spec/shared/deprecated_class_examples.rb +0 -16
- data/spec/shared/versioning_examples.rb +0 -215
- data/spec/spec_helper.rb +0 -52
- data/spec/support/basic_auth_encode_helpers.rb +0 -11
- data/spec/support/chunks.rb +0 -14
- data/spec/support/content_type_helpers.rb +0 -15
- data/spec/support/endpoint_faker.rb +0 -25
- data/spec/support/file_streamer.rb +0 -13
- data/spec/support/integer_helpers.rb +0 -13
- data/spec/support/versioned_helpers.rb +0 -55
data/lib/grape/dsl/middleware.rb
CHANGED
|
@@ -3,51 +3,33 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
5
|
module Middleware
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
arr = [:use, middleware_class, *args]
|
|
19
|
-
arr << block if block
|
|
20
|
-
|
|
21
|
-
namespace_stackable(:middleware, arr)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def insert(*args, &block)
|
|
25
|
-
arr = [:insert, *args]
|
|
26
|
-
arr << block if block
|
|
27
|
-
|
|
28
|
-
namespace_stackable(:middleware, arr)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def insert_before(*args, &block)
|
|
32
|
-
arr = [:insert_before, *args]
|
|
33
|
-
arr << block if block
|
|
34
|
-
|
|
35
|
-
namespace_stackable(:middleware, arr)
|
|
36
|
-
end
|
|
6
|
+
# Apply a custom middleware to the API. Applies
|
|
7
|
+
# to the current namespace and any children, but
|
|
8
|
+
# not parents.
|
|
9
|
+
#
|
|
10
|
+
# @param middleware_class [Class] The class of the middleware you'd like
|
|
11
|
+
# to inject.
|
|
12
|
+
def use(middleware_class, *args, &block)
|
|
13
|
+
arr = [:use, middleware_class, *args]
|
|
14
|
+
arr << block if block
|
|
15
|
+
|
|
16
|
+
inheritable_setting.add_middleware(arr)
|
|
17
|
+
end
|
|
37
18
|
|
|
38
|
-
|
|
39
|
-
|
|
19
|
+
%i[insert insert_before insert_after].each do |method_name|
|
|
20
|
+
define_method method_name do |*args, &block|
|
|
21
|
+
arr = [method_name, *args]
|
|
40
22
|
arr << block if block
|
|
41
23
|
|
|
42
|
-
|
|
24
|
+
inheritable_setting.add_middleware(arr)
|
|
43
25
|
end
|
|
26
|
+
end
|
|
44
27
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
end
|
|
28
|
+
# Retrieve an array of the middleware classes
|
|
29
|
+
# and arguments that are currently applied to the
|
|
30
|
+
# application.
|
|
31
|
+
def middleware
|
|
32
|
+
inheritable_setting.middleware
|
|
51
33
|
end
|
|
52
34
|
end
|
|
53
35
|
end
|
data/lib/grape/dsl/parameters.rb
CHANGED
|
@@ -6,8 +6,6 @@ module Grape
|
|
|
6
6
|
# and describe the parameters accepted by an endpoint, or all endpoints
|
|
7
7
|
# within a namespace.
|
|
8
8
|
module Parameters
|
|
9
|
-
extend ActiveSupport::Concern
|
|
10
|
-
|
|
11
9
|
# Set the module used to build the request.params.
|
|
12
10
|
#
|
|
13
11
|
# @param build_with the ParamBuilder module to use when building request.params
|
|
@@ -23,15 +21,15 @@ module Grape
|
|
|
23
21
|
# class API < Grape::API
|
|
24
22
|
# desc "Get collection"
|
|
25
23
|
# params do
|
|
26
|
-
# build_with
|
|
24
|
+
# build_with :hashie_mash
|
|
27
25
|
# requires :user_id, type: Integer
|
|
28
26
|
# end
|
|
29
27
|
# get do
|
|
30
28
|
# params['user_id']
|
|
31
29
|
# end
|
|
32
30
|
# end
|
|
33
|
-
def build_with(build_with
|
|
34
|
-
@api.
|
|
31
|
+
def build_with(build_with)
|
|
32
|
+
@api.inheritable_setting.build_params_with = build_with
|
|
35
33
|
end
|
|
36
34
|
|
|
37
35
|
# Include reusable params rules among current.
|
|
@@ -55,9 +53,10 @@ module Grape
|
|
|
55
53
|
# Collection.page(params[:page]).per(params[:per_page])
|
|
56
54
|
# end
|
|
57
55
|
# end
|
|
58
|
-
def use(*names)
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
def use(*names, **options)
|
|
57
|
+
return redispatch_legacy_options(:use, names, options) if legacy_options?(names)
|
|
58
|
+
|
|
59
|
+
named_params = @api.inheritable_setting.named_params || {}
|
|
61
60
|
names.each do |name|
|
|
62
61
|
params_block = named_params.fetch(name) do
|
|
63
62
|
raise "Params :#{name} not found!"
|
|
@@ -77,8 +76,8 @@ module Grape
|
|
|
77
76
|
#
|
|
78
77
|
# @param attrs list of parameters names, or, if :using is
|
|
79
78
|
# passed as an option, which keys to include (:all or :none) from
|
|
80
|
-
# the :using hash.
|
|
81
|
-
#
|
|
79
|
+
# the :using hash. Passing the options as a trailing positional Hash
|
|
80
|
+
# is deprecated; pass them as keyword arguments instead.
|
|
82
81
|
# @option attrs :type [Class] the type to coerce this parameter to before
|
|
83
82
|
# passing it to the endpoint. See {Grape::Validations::Types} for a list of
|
|
84
83
|
# types that are supported automatically. Custom classes may be used
|
|
@@ -125,76 +124,34 @@ module Grape
|
|
|
125
124
|
# requires :name, type: String
|
|
126
125
|
# end
|
|
127
126
|
# end
|
|
128
|
-
def requires(*attrs, &
|
|
129
|
-
|
|
127
|
+
def requires(*attrs, using: nil, except: nil, as: nil, **opts, &)
|
|
128
|
+
return redispatch_legacy_options(:requires, attrs, { using:, except:, as: }.compact.merge(opts), &) if legacy_options?(attrs)
|
|
130
129
|
|
|
131
|
-
opts
|
|
132
|
-
opts[:presence] = { value: true, message: opts[:message] }
|
|
133
|
-
opts = @group.merge(opts) if instance_variable_defined?(:@group) && @group
|
|
134
|
-
|
|
135
|
-
if opts[:using]
|
|
136
|
-
require_required_and_optional_fields(attrs.first, opts)
|
|
137
|
-
else
|
|
138
|
-
validate_attributes(attrs, opts, &block)
|
|
139
|
-
block ? new_scope(orig_attrs, &block) : push_declared_params(attrs, **opts.slice(:as))
|
|
140
|
-
end
|
|
130
|
+
declare(attrs, opts, required: true, using:, except:, as:, &)
|
|
141
131
|
end
|
|
142
132
|
|
|
143
133
|
# Allow, but don't require, one or more parameters for the current
|
|
144
134
|
# endpoint.
|
|
145
135
|
# @param (see #requires)
|
|
146
136
|
# @option (see #requires)
|
|
147
|
-
def optional(*attrs, &
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
opts = attrs.extract_options!.clone
|
|
151
|
-
type = opts[:type]
|
|
152
|
-
opts = @group.merge(opts) if instance_variable_defined?(:@group) && @group
|
|
137
|
+
def optional(*attrs, using: nil, except: nil, as: nil, **opts, &)
|
|
138
|
+
return redispatch_legacy_options(:optional, attrs, { using:, except:, as: }.compact.merge(opts), &) if legacy_options?(attrs)
|
|
153
139
|
|
|
154
|
-
|
|
155
|
-
if attrs && block
|
|
156
|
-
raise Grape::Exceptions::MissingGroupType if type.nil?
|
|
157
|
-
raise Grape::Exceptions::UnsupportedGroupType unless Grape::Validations::Types.group?(type)
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
if opts[:using]
|
|
161
|
-
require_optional_fields(attrs.first, opts)
|
|
162
|
-
else
|
|
163
|
-
validate_attributes(attrs, opts, &block)
|
|
164
|
-
|
|
165
|
-
block ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, **opts.slice(:as))
|
|
166
|
-
end
|
|
140
|
+
declare(attrs, opts, required: false, using:, except:, as:, &)
|
|
167
141
|
end
|
|
168
142
|
|
|
169
143
|
# Define common settings for one or more parameters
|
|
170
144
|
# @param (see #requires)
|
|
171
145
|
# @option (see #requires)
|
|
172
|
-
def with(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
# Disallow the given parameters to be present in the same request.
|
|
177
|
-
# @param attrs [*Symbol] parameters to validate
|
|
178
|
-
def mutually_exclusive(*attrs)
|
|
179
|
-
validates(attrs, mutual_exclusion: { value: true, message: extract_message_option(attrs) })
|
|
146
|
+
def with(**opts, &)
|
|
147
|
+
new_group_attrs = @group&.deep_merge(opts) || opts
|
|
148
|
+
new_group_scope(new_group_attrs, &)
|
|
180
149
|
end
|
|
181
150
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
# Require at least one of the given parameters to be present.
|
|
189
|
-
# @param (see #mutually_exclusive)
|
|
190
|
-
def at_least_one_of(*attrs)
|
|
191
|
-
validates(attrs, at_least_one_of: { value: true, message: extract_message_option(attrs) })
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
# Require that either all given params are present, or none are.
|
|
195
|
-
# @param (see #mutually_exclusive)
|
|
196
|
-
def all_or_none_of(*attrs)
|
|
197
|
-
validates(attrs, all_or_none_of: { value: true, message: extract_message_option(attrs) })
|
|
151
|
+
%i[mutually_exclusive exactly_one_of at_least_one_of all_or_none_of].each do |validator|
|
|
152
|
+
define_method validator do |*attrs, message: nil|
|
|
153
|
+
validates(attrs, { validator => { value: true, message: } })
|
|
154
|
+
end
|
|
198
155
|
end
|
|
199
156
|
|
|
200
157
|
# Define a block of validations which should be applied if and only if
|
|
@@ -204,62 +161,99 @@ module Grape
|
|
|
204
161
|
# @raise Grape::Exceptions::UnknownParameter if `attr` has not been
|
|
205
162
|
# defined in this scope yet
|
|
206
163
|
# @yield a parameter definition DSL
|
|
207
|
-
def given(*attrs, &
|
|
164
|
+
def given(*attrs, &)
|
|
208
165
|
attrs.each do |attr|
|
|
209
166
|
proxy_attr = first_hash_key_or_param(attr)
|
|
210
167
|
raise Grape::Exceptions::UnknownParameter.new(proxy_attr) unless declared_param?(proxy_attr)
|
|
211
168
|
end
|
|
212
|
-
new_lateral_scope(dependent_on: attrs, &
|
|
169
|
+
new_lateral_scope(dependent_on: attrs, &)
|
|
213
170
|
end
|
|
214
171
|
|
|
215
172
|
# Test for whether a certain parameter has been defined in this params
|
|
216
173
|
# block yet.
|
|
217
174
|
# @return [Boolean] whether the parameter has been defined
|
|
218
175
|
def declared_param?(param)
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
first_hash_key_or_param(declared_param_attr.key) == param
|
|
227
|
-
end
|
|
176
|
+
# Elements of @declared_params of lateral scope are pushed in @parent. So check them in @parent.
|
|
177
|
+
return @parent.declared_param?(param) if lateral?
|
|
178
|
+
|
|
179
|
+
# @declared_params also includes hashes of options and such, but those
|
|
180
|
+
# won't be flattened out.
|
|
181
|
+
@declared_params.flatten.any? do |declared_param_attr|
|
|
182
|
+
first_hash_key_or_param(declared_param_attr.key) == param
|
|
228
183
|
end
|
|
229
184
|
end
|
|
230
185
|
|
|
231
186
|
alias group requires
|
|
232
187
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
def map_params(params, element, is_array = false)
|
|
236
|
-
if params.is_a?(Array)
|
|
237
|
-
params.map do |el|
|
|
238
|
-
map_params(el, element, true)
|
|
239
|
-
end
|
|
240
|
-
elsif params.is_a?(Hash)
|
|
241
|
-
params[element] || (@optional && is_array ? EmptyOptionalValue : {})
|
|
242
|
-
elsif params == EmptyOptionalValue
|
|
243
|
-
EmptyOptionalValue
|
|
244
|
-
else
|
|
245
|
-
{}
|
|
246
|
-
end
|
|
247
|
-
end
|
|
188
|
+
EmptyOptionalValue = Object.new.freeze
|
|
248
189
|
|
|
249
190
|
# @param params [Hash] initial hash of parameters
|
|
250
191
|
# @return hash of parameters relevant for the current scope
|
|
251
192
|
# @api private
|
|
252
193
|
def params(params)
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
params
|
|
194
|
+
scoped = @parent ? (@parent.qualifying_params.presence || @parent.params(params)) : params
|
|
195
|
+
@element ? map_params(scoped, @element) : scoped
|
|
256
196
|
end
|
|
257
197
|
|
|
258
198
|
private
|
|
259
199
|
|
|
200
|
+
# @deprecated A trailing positional options Hash is deprecated; pass keyword
|
|
201
|
+
# arguments instead. Before Ruby 3 keyword separation this Hash was pulled
|
|
202
|
+
# off the argument list by `extract_options!`; now it lands in the splat and
|
|
203
|
+
# would silently be treated as a parameter name.
|
|
204
|
+
# +requires+ and +optional+ differ only in whether what they declare is
|
|
205
|
+
# required, so the declaration itself lives here.
|
|
206
|
+
#
|
|
207
|
+
# The two +using:+ helpers stay separate. They are not one computation
|
|
208
|
+
# with a flag flipped: +requires+ treats +except+ as "these go in the
|
|
209
|
+
# other bucket", while +optional+ has no other bucket — +:all+ ignores
|
|
210
|
+
# +except+ and +:none+ uses it to drop fields entirely.
|
|
211
|
+
def declare(attrs, opts, required:, using:, except:, as:, &block)
|
|
212
|
+
merged_opts = @group&.deep_merge(opts) || opts
|
|
213
|
+
declared_as = as || merged_opts[:as]
|
|
214
|
+
|
|
215
|
+
if using
|
|
216
|
+
return require_required_and_optional_fields(attrs.first, using:, except:) if required
|
|
217
|
+
|
|
218
|
+
return require_optional_fields(attrs.first, using:, except:)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
validates(attrs, merged_opts, required:)
|
|
222
|
+
return push_declared_params(attrs, as: declared_as) unless block
|
|
223
|
+
|
|
224
|
+
new_scope(attrs.first, type: merged_opts[:type], as: declared_as, optional: !required, &block)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def legacy_options?(args)
|
|
228
|
+
args.size > 1 && args.last.is_a?(Hash)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Re-invokes +method_name+ with the trailing Hash splatted as keyword
|
|
232
|
+
# arguments, so Ruby routes its keys to the same place they would have
|
|
233
|
+
# reached had the caller omitted the braces.
|
|
234
|
+
def redispatch_legacy_options(method_name, args, opts, &)
|
|
235
|
+
Grape.deprecator.warn("Passing a positional options Hash to `#{method_name}` is deprecated. Pass keyword arguments instead.")
|
|
236
|
+
__send__(method_name, *args[0..-2], **args.last.merge(opts), &)
|
|
237
|
+
end
|
|
238
|
+
|
|
260
239
|
def first_hash_key_or_param(parameter)
|
|
261
240
|
parameter.is_a?(Hash) ? parameter.keys.first : parameter
|
|
262
241
|
end
|
|
242
|
+
|
|
243
|
+
def map_params(params, element, is_array: false)
|
|
244
|
+
case params
|
|
245
|
+
when Array
|
|
246
|
+
params.map do |el|
|
|
247
|
+
map_params(el, element, is_array: true)
|
|
248
|
+
end
|
|
249
|
+
when Hash
|
|
250
|
+
params[element] || (@optional && is_array ? EmptyOptionalValue : {})
|
|
251
|
+
when EmptyOptionalValue
|
|
252
|
+
EmptyOptionalValue
|
|
253
|
+
else
|
|
254
|
+
{}
|
|
255
|
+
end
|
|
256
|
+
end
|
|
263
257
|
end
|
|
264
258
|
end
|
|
265
259
|
end
|
|
@@ -3,171 +3,167 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
5
|
module RequestResponse
|
|
6
|
-
|
|
6
|
+
# Specify the default format for the API's serializers.
|
|
7
|
+
# May be `:json` or `:txt` (default).
|
|
8
|
+
def default_format(new_format = nil)
|
|
9
|
+
return inheritable_setting.default_format if new_format.nil?
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
inheritable_setting.default_format = new_format.to_sym
|
|
12
|
+
end
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
namespace_inheritable(:default_format, new_format.nil? ? nil : new_format.to_sym)
|
|
15
|
-
end
|
|
14
|
+
# Specify the format for the API's serializers.
|
|
15
|
+
# May be `:json`, `:xml`, `:txt`, etc.
|
|
16
|
+
def format(new_format = nil)
|
|
17
|
+
return inheritable_setting.format if new_format.nil?
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if new_format
|
|
21
|
-
namespace_inheritable(:format, new_format.to_sym)
|
|
22
|
-
# define the default error formatters
|
|
23
|
-
namespace_inheritable(:default_error_formatter, Grape::ErrorFormatter.formatter_for(new_format, **{}))
|
|
24
|
-
# define a single mime type
|
|
25
|
-
mime_type = content_types[new_format.to_sym]
|
|
26
|
-
raise Grape::Exceptions::MissingMimeType.new(new_format) unless mime_type
|
|
27
|
-
|
|
28
|
-
namespace_stackable(:content_types, new_format.to_sym => mime_type)
|
|
29
|
-
else
|
|
30
|
-
namespace_inheritable(:format)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
19
|
+
symbolic_new_format = new_format.to_sym
|
|
20
|
+
inheritable_setting.format = symbolic_new_format
|
|
21
|
+
inheritable_setting.default_error_formatter = Grape::ErrorFormatter.formatter_for(symbolic_new_format)
|
|
33
22
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
namespace_stackable(:formatters, content_type.to_sym => new_formatter)
|
|
37
|
-
end
|
|
23
|
+
content_type = content_types[symbolic_new_format]
|
|
24
|
+
raise Grape::Exceptions::MissingMimeType.new(new_format) unless content_type
|
|
38
25
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
namespace_stackable(:parsers, content_type.to_sym => new_parser)
|
|
42
|
-
end
|
|
26
|
+
inheritable_setting.add_content_type(symbolic_new_format, content_type)
|
|
27
|
+
end
|
|
43
28
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
namespace_inheritable(:default_error_formatter, new_formatter)
|
|
49
|
-
else
|
|
50
|
-
namespace_inheritable(:default_error_formatter)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
29
|
+
# Specify a custom formatter for a content-type.
|
|
30
|
+
def formatter(content_type, new_formatter)
|
|
31
|
+
inheritable_setting.add_formatter(content_type.to_sym, new_formatter)
|
|
32
|
+
end
|
|
53
33
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
options
|
|
59
|
-
end
|
|
34
|
+
# Specify a custom parser for a content-type.
|
|
35
|
+
def parser(content_type, new_parser)
|
|
36
|
+
inheritable_setting.add_parser(content_type.to_sym, new_parser)
|
|
37
|
+
end
|
|
60
38
|
|
|
61
|
-
|
|
62
|
-
|
|
39
|
+
# Specify a default error formatter, by the name it is registered under.
|
|
40
|
+
# A name nothing is registered for used to be stored as
|
|
41
|
+
# +ErrorFormatter::Txt+ — the fallback the lookup applied — so a typo
|
|
42
|
+
# read back as a working setting and silently rendered errors as text.
|
|
43
|
+
def default_error_formatter(new_formatter_name = nil)
|
|
44
|
+
return inheritable_setting.default_error_formatter if new_formatter_name.nil?
|
|
63
45
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def content_type(key, val)
|
|
67
|
-
namespace_stackable(:content_types, key.to_sym => val)
|
|
68
|
-
end
|
|
46
|
+
formatter = Grape::ErrorFormatter.formatter_for(new_formatter_name)
|
|
47
|
+
raise Grape::Exceptions::UnknownErrorFormatter.new(new_formatter_name) if formatter.nil?
|
|
69
48
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
c_types = namespace_stackable_with_hash(:content_types)
|
|
73
|
-
Grape::ContentTypes.content_types_for c_types
|
|
74
|
-
end
|
|
49
|
+
inheritable_setting.default_error_formatter = formatter
|
|
50
|
+
end
|
|
75
51
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
52
|
+
# Specify a custom error formatter for a format, passed positionally or
|
|
53
|
+
# as +with:+. A nil formatter used to be registered as-is, which is the
|
|
54
|
+
# one thing the registration cannot mean: the format then resolves as if
|
|
55
|
+
# the call had never been made. Reject it here, where the mistake is.
|
|
56
|
+
def error_formatter(format, options = nil, with: nil)
|
|
57
|
+
formatter = with || options
|
|
58
|
+
raise ArgumentError, "error_formatter `#{format.inspect}` requires a formatter, given positionally or as `with:`" if formatter.nil?
|
|
80
59
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
# @option options [Boolean] :rescue_subclasses Also rescue subclasses of exception classes
|
|
99
|
-
# @param [Proc] handler Execution proc to handle the given exception as an
|
|
100
|
-
# alternative to passing a block.
|
|
101
|
-
def rescue_from(*args, &block)
|
|
102
|
-
if args.last.is_a?(Proc)
|
|
103
|
-
handler = args.pop
|
|
104
|
-
elsif block
|
|
105
|
-
handler = block
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
options = args.extract_options!
|
|
109
|
-
raise ArgumentError, 'both :with option and block cannot be passed' if block && options.key?(:with)
|
|
110
|
-
|
|
111
|
-
handler ||= extract_with(options)
|
|
112
|
-
|
|
113
|
-
if args.include?(:all)
|
|
114
|
-
namespace_inheritable(:rescue_all, true)
|
|
115
|
-
namespace_inheritable(:all_rescue_handler, handler)
|
|
116
|
-
elsif args.include?(:grape_exceptions)
|
|
117
|
-
namespace_inheritable(:rescue_all, true)
|
|
118
|
-
namespace_inheritable(:rescue_grape_exceptions, true)
|
|
119
|
-
namespace_inheritable(:grape_exceptions_rescue_handler, handler)
|
|
120
|
-
else
|
|
121
|
-
handler_type =
|
|
122
|
-
case options[:rescue_subclasses]
|
|
123
|
-
when nil, true
|
|
124
|
-
:rescue_handlers
|
|
125
|
-
else
|
|
126
|
-
:base_only_rescue_handlers
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
namespace_reverse_stackable(handler_type, args.to_h { |arg| [arg, handler] })
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
namespace_stackable(:rescue_options, options)
|
|
133
|
-
end
|
|
60
|
+
inheritable_setting.add_error_formatter(format.to_sym, formatter)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Specify additional content-types, e.g.:
|
|
64
|
+
# content_type :xls, 'application/vnd.ms-excel'
|
|
65
|
+
def content_type(key, val)
|
|
66
|
+
inheritable_setting.add_content_type(key.to_sym, val)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# All available content types.
|
|
70
|
+
def content_types
|
|
71
|
+
Grape::ContentTypes.content_types_for(inheritable_setting.content_types)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Specify the default status code for errors.
|
|
75
|
+
def default_error_status(new_status = nil)
|
|
76
|
+
return inheritable_setting.default_error_status if new_status.nil?
|
|
134
77
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
78
|
+
inheritable_setting.default_error_status = new_status
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Allows you to rescue certain exceptions that occur to return
|
|
82
|
+
# a grape error rather than raising all the way to the
|
|
83
|
+
# server level.
|
|
84
|
+
#
|
|
85
|
+
# @example Rescue from custom exceptions
|
|
86
|
+
# class ExampleAPI < Grape::API
|
|
87
|
+
# class CustomError < StandardError; end
|
|
88
|
+
#
|
|
89
|
+
# rescue_from CustomError
|
|
90
|
+
# end
|
|
91
|
+
#
|
|
92
|
+
META_RESCUE_SELECTORS = %i[all grape_exceptions internal_grape_exceptions].freeze
|
|
93
|
+
private_constant :META_RESCUE_SELECTORS
|
|
94
|
+
|
|
95
|
+
# @overload rescue_from(*exception_classes, **options)
|
|
96
|
+
# @param [Array] exception_classes A list of classes that you want to rescue, or
|
|
97
|
+
# one of the meta selectors +:all+, +:grape_exceptions+,
|
|
98
|
+
# +:internal_grape_exceptions+. Meta selectors must be used alone;
|
|
99
|
+
# mixing with exception classes raises +ArgumentError+.
|
|
100
|
+
# @param [Block] block Execution block to handle the given exception.
|
|
101
|
+
# @param [Proc] with Execution proc to handle the given exception as an alternative
|
|
102
|
+
# to passing a block.
|
|
103
|
+
# @param [Boolean] rescue_subclasses Also rescue subclasses of exception classes;
|
|
104
|
+
# defaults to +true+.
|
|
105
|
+
# @param [Boolean] backtrace Include the rescued exception's backtrace in the
|
|
106
|
+
# rescue response body.
|
|
107
|
+
# @param [Boolean] original_exception Include +inspect+ of the rescued exception
|
|
108
|
+
# in the rescue response body.
|
|
109
|
+
def rescue_from(*args, with: nil, rescue_subclasses: true, backtrace: false, original_exception: false, &block)
|
|
110
|
+
handler = extract_handler(args, with:, block:)
|
|
111
|
+
meta_selector = (args & META_RESCUE_SELECTORS).first
|
|
112
|
+
raise ArgumentError, "rescue_from `#{meta_selector.inspect}` does not accept additional arguments" if meta_selector && args.size > 1
|
|
113
|
+
|
|
114
|
+
case meta_selector
|
|
115
|
+
when :all
|
|
116
|
+
inheritable_setting.add_all_rescue_handler(handler)
|
|
117
|
+
when :grape_exceptions
|
|
118
|
+
inheritable_setting.add_grape_exceptions_rescue_handler(handler)
|
|
119
|
+
when :internal_grape_exceptions
|
|
120
|
+
inheritable_setting.add_internal_grape_exceptions_rescue_handler(handler)
|
|
121
|
+
else
|
|
122
|
+
inheritable_setting.add_rescue_handlers(args.to_h { |klass| [klass, handler] }, subclasses: rescue_subclasses)
|
|
159
123
|
end
|
|
160
124
|
|
|
161
|
-
|
|
125
|
+
inheritable_setting.add_rescue_options(RescueOptions.new(backtrace:, original_exception:))
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Allows you to specify a default representation entity for a
|
|
129
|
+
# class. This allows you to map your models to their respective
|
|
130
|
+
# entities once and then simply call `present` with the model.
|
|
131
|
+
#
|
|
132
|
+
# @example
|
|
133
|
+
# class ExampleAPI < Grape::API
|
|
134
|
+
# represent User, with: Entity::User
|
|
135
|
+
#
|
|
136
|
+
# get '/me' do
|
|
137
|
+
# present current_user # with: Entity::User is assumed
|
|
138
|
+
# end
|
|
139
|
+
# end
|
|
140
|
+
#
|
|
141
|
+
# Note that Grape will automatically go up the class ancestry to
|
|
142
|
+
# try to find a representing entity, so if you, for example, define
|
|
143
|
+
# an entity to represent `Object` then all presented objects will
|
|
144
|
+
# bubble up and utilize the entity provided on that `represent` call.
|
|
145
|
+
#
|
|
146
|
+
# @param model_class [Class] The model class that will be represented.
|
|
147
|
+
# @option options [Class] :with The entity class that will represent the model.
|
|
148
|
+
def represent(model_class, with:)
|
|
149
|
+
raise Grape::Exceptions::InvalidWithOptionForRepresent.new unless with.is_a?(Class)
|
|
150
|
+
|
|
151
|
+
inheritable_setting.add_representation(model_class, with)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
private
|
|
162
155
|
|
|
163
|
-
|
|
164
|
-
|
|
156
|
+
def extract_handler(args, with:, block:)
|
|
157
|
+
raise ArgumentError, 'both :with option and block cannot be passed' if block && with
|
|
165
158
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
159
|
+
return args.pop if args.last.is_a?(Proc)
|
|
160
|
+
return block if block
|
|
161
|
+
return unless with
|
|
169
162
|
|
|
170
|
-
|
|
163
|
+
case with
|
|
164
|
+
when Proc, Symbol then with
|
|
165
|
+
when String then with.to_sym
|
|
166
|
+
else raise ArgumentError, "with: `#{with.class}`, expected Symbol, String or Proc"
|
|
171
167
|
end
|
|
172
168
|
end
|
|
173
169
|
end
|