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/util/xml.rb
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Grape
|
|
4
|
-
module Validations
|
|
5
|
-
class ParamsScope
|
|
6
|
-
# Documents parameters of an endpoint. If documentation isn't needed (for instance, it is an
|
|
7
|
-
# internal API), the class only cleans up attributes to avoid junk in RAM.
|
|
8
|
-
class AttributesDoc
|
|
9
|
-
attr_accessor :type, :values
|
|
10
|
-
|
|
11
|
-
# @param api [Grape::API::Instance]
|
|
12
|
-
# @param scope [Validations::ParamsScope]
|
|
13
|
-
def initialize(api, scope)
|
|
14
|
-
@api = api
|
|
15
|
-
@scope = scope
|
|
16
|
-
@type = type
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def extract_details(validations)
|
|
20
|
-
details[:required] = validations.key?(:presence)
|
|
21
|
-
|
|
22
|
-
desc = validations.delete(:desc) || validations.delete(:description)
|
|
23
|
-
|
|
24
|
-
details[:desc] = desc if desc
|
|
25
|
-
|
|
26
|
-
documentation = validations.delete(:documentation)
|
|
27
|
-
|
|
28
|
-
details[:documentation] = documentation if documentation
|
|
29
|
-
|
|
30
|
-
details[:default] = validations[:default] if validations.key?(:default)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def document(attrs)
|
|
34
|
-
return if @api.namespace_inheritable(:do_not_document)
|
|
35
|
-
|
|
36
|
-
details[:type] = type.to_s if type
|
|
37
|
-
details[:values] = values if values
|
|
38
|
-
|
|
39
|
-
documented_attrs = attrs.each_with_object({}) do |name, memo|
|
|
40
|
-
memo[@scope.full_name(name)] = details
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
@api.namespace_stackable(:params, documented_attrs)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def required
|
|
47
|
-
details[:required]
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
protected
|
|
51
|
-
|
|
52
|
-
def details
|
|
53
|
-
@details ||= {}
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'array_coercer'
|
|
4
|
-
require_relative 'set_coercer'
|
|
5
|
-
require_relative 'primitive_coercer'
|
|
6
|
-
|
|
7
|
-
module Grape
|
|
8
|
-
module Validations
|
|
9
|
-
module Types
|
|
10
|
-
# Chooses the best coercer for the given type. For example, if the type
|
|
11
|
-
# is Integer, it will return a coercer which will be able to coerce a value
|
|
12
|
-
# to the integer.
|
|
13
|
-
#
|
|
14
|
-
# There are a few very special coercers which might be returned.
|
|
15
|
-
#
|
|
16
|
-
# +Grape::Types::MultipleTypeCoercer+ is a coercer which is returned when
|
|
17
|
-
# the given type implies values in an array with different types.
|
|
18
|
-
# For example, +[Integer, String]+ allows integer and string values in
|
|
19
|
-
# an array.
|
|
20
|
-
#
|
|
21
|
-
# +Grape::Types::CustomTypeCoercer+ is a coercer which is returned when
|
|
22
|
-
# a method is specified by a user with +coerce_with+ option or the user
|
|
23
|
-
# specifies a custom type which implements requirments of
|
|
24
|
-
# +Grape::Types::CustomTypeCoercer+.
|
|
25
|
-
#
|
|
26
|
-
# +Grape::Types::CustomTypeCollectionCoercer+ is a very similar to the
|
|
27
|
-
# previous one, but it expects an array or set of values having a custom
|
|
28
|
-
# type implemented by the user.
|
|
29
|
-
#
|
|
30
|
-
# There is also a group of custom types implemented by Grape, check
|
|
31
|
-
# +Grape::Validations::Types::SPECIAL+ to get the full list.
|
|
32
|
-
#
|
|
33
|
-
# @param type [Class] the type to which input strings
|
|
34
|
-
# should be coerced
|
|
35
|
-
# @param method [Class,#call] the coercion method to use
|
|
36
|
-
# @return [Object] object to be used
|
|
37
|
-
# for coercion and type validation
|
|
38
|
-
def self.build_coercer(type, method: nil, strict: false)
|
|
39
|
-
cache_instance(type, method, strict) do
|
|
40
|
-
create_coercer_instance(type, method, strict)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def self.create_coercer_instance(type, method, strict)
|
|
45
|
-
# Maps a custom type provided by Grape, it doesn't map types wrapped by collections!!!
|
|
46
|
-
type = Types.map_special(type)
|
|
47
|
-
|
|
48
|
-
# Use a special coercer for multiply-typed parameters.
|
|
49
|
-
if Types.multiple?(type)
|
|
50
|
-
MultipleTypeCoercer.new(type, method)
|
|
51
|
-
|
|
52
|
-
# Use a special coercer for custom types and coercion methods.
|
|
53
|
-
elsif method || Types.custom?(type)
|
|
54
|
-
CustomTypeCoercer.new(type, method)
|
|
55
|
-
|
|
56
|
-
# Special coercer for collections of types that implement a parse method.
|
|
57
|
-
# CustomTypeCoercer (above) already handles such types when an explicit coercion
|
|
58
|
-
# method is supplied.
|
|
59
|
-
elsif Types.collection_of_custom?(type)
|
|
60
|
-
Types::CustomTypeCollectionCoercer.new(
|
|
61
|
-
Types.map_special(type.first), type.is_a?(Set)
|
|
62
|
-
)
|
|
63
|
-
else
|
|
64
|
-
DryTypeCoercer.coercer_instance_for(type, strict)
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def self.cache_instance(type, method, strict, &_block)
|
|
69
|
-
key = cache_key(type, method, strict)
|
|
70
|
-
|
|
71
|
-
return @__cache[key] if @__cache.key?(key)
|
|
72
|
-
|
|
73
|
-
instance = yield
|
|
74
|
-
|
|
75
|
-
@__cache_write_lock.synchronize do
|
|
76
|
-
@__cache[key] = instance
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
instance
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def self.cache_key(type, method, strict)
|
|
83
|
-
[type, method, strict].each_with_object(+'_') do |val, memo|
|
|
84
|
-
next if val.nil?
|
|
85
|
-
|
|
86
|
-
memo << '_' << val.to_s
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
instance_variable_set(:@__cache, {})
|
|
91
|
-
instance_variable_set(:@__cache_write_lock, Mutex.new)
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Grape
|
|
4
|
-
module Validations
|
|
5
|
-
class ValidatorFactory
|
|
6
|
-
def self.create_validator(**options)
|
|
7
|
-
options[:validator_class].new(options[:attributes],
|
|
8
|
-
options[:options],
|
|
9
|
-
options[:required],
|
|
10
|
-
options[:params_scope],
|
|
11
|
-
**options[:opts])
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'shared/deprecated_class_examples'
|
|
4
|
-
|
|
5
|
-
describe Grape::Validations do
|
|
6
|
-
describe 'Grape::Validations::Base' do
|
|
7
|
-
let(:deprecated_class) do
|
|
8
|
-
Class.new(Grape::Validations::Base)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
it_behaves_like 'deprecated class'
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
describe 'using a custom length validator' do
|
|
15
|
-
subject do
|
|
16
|
-
Class.new(Grape::API) do
|
|
17
|
-
params do
|
|
18
|
-
requires :text, default_length: 140
|
|
19
|
-
end
|
|
20
|
-
get do
|
|
21
|
-
'bacon'
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
let(:default_length_validator) do
|
|
27
|
-
Class.new(Grape::Validations::Validators::Base) do
|
|
28
|
-
def validate_param!(attr_name, params)
|
|
29
|
-
@option = params[:max].to_i if params.key?(:max)
|
|
30
|
-
return if params[attr_name].length <= @option
|
|
31
|
-
|
|
32
|
-
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long")
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
let(:app) { Rack::Builder.new(subject) }
|
|
37
|
-
|
|
38
|
-
before do
|
|
39
|
-
described_class.register_validator('default_length', default_length_validator)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
after do
|
|
43
|
-
described_class.deregister_validator('default_length')
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it 'under 140 characters' do
|
|
47
|
-
get '/', text: 'abc'
|
|
48
|
-
expect(last_response.status).to eq 200
|
|
49
|
-
expect(last_response.body).to eq 'bacon'
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it 'over 140 characters' do
|
|
53
|
-
get '/', text: 'a' * 141
|
|
54
|
-
expect(last_response.status).to eq 400
|
|
55
|
-
expect(last_response.body).to eq 'text must be at the most 140 characters long'
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
it 'specified in the query string' do
|
|
59
|
-
get '/', text: 'a' * 141, max: 141
|
|
60
|
-
expect(last_response.status).to eq 200
|
|
61
|
-
expect(last_response.body).to eq 'bacon'
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
describe 'using a custom body-only validator' do
|
|
66
|
-
subject do
|
|
67
|
-
Class.new(Grape::API) do
|
|
68
|
-
params do
|
|
69
|
-
requires :text, in_body: true
|
|
70
|
-
end
|
|
71
|
-
get do
|
|
72
|
-
'bacon'
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
let(:in_body_validator) do
|
|
78
|
-
Class.new(Grape::Validations::Validators::PresenceValidator) do
|
|
79
|
-
def validate(request)
|
|
80
|
-
validate!(request.env['api.request.body'])
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
let(:app) { Rack::Builder.new(subject) }
|
|
85
|
-
|
|
86
|
-
before do
|
|
87
|
-
described_class.register_validator('in_body', in_body_validator)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
after do
|
|
91
|
-
described_class.deregister_validator('in_body')
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
it 'allows field in body' do
|
|
95
|
-
get '/', text: 'abc'
|
|
96
|
-
expect(last_response.status).to eq 200
|
|
97
|
-
expect(last_response.body).to eq 'bacon'
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
it 'ignores field in query' do
|
|
101
|
-
get '/', nil, text: 'abc'
|
|
102
|
-
expect(last_response.status).to eq 400
|
|
103
|
-
expect(last_response.body).to eq 'text is missing'
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
describe 'using a custom validator with message_key' do
|
|
108
|
-
subject do
|
|
109
|
-
Class.new(Grape::API) do
|
|
110
|
-
params do
|
|
111
|
-
requires :text, with_message_key: true
|
|
112
|
-
end
|
|
113
|
-
get do
|
|
114
|
-
'bacon'
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
let(:message_key_validator) do
|
|
120
|
-
Class.new(Grape::Validations::Validators::PresenceValidator) do
|
|
121
|
-
def validate_param!(attr_name, _params)
|
|
122
|
-
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: :presence)
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
let(:app) { Rack::Builder.new(subject) }
|
|
127
|
-
|
|
128
|
-
before do
|
|
129
|
-
described_class.register_validator('with_message_key', message_key_validator)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
after do
|
|
133
|
-
described_class.deregister_validator('with_message_key')
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
it 'fails with message' do
|
|
137
|
-
get '/', text: 'foobar'
|
|
138
|
-
expect(last_response.status).to eq 400
|
|
139
|
-
expect(last_response.body).to eq 'text is missing'
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
describe 'using a custom request/param validator' do
|
|
144
|
-
subject do
|
|
145
|
-
Class.new(Grape::API) do
|
|
146
|
-
params do
|
|
147
|
-
optional :admin_field, type: String, admin: true
|
|
148
|
-
optional :non_admin_field, type: String
|
|
149
|
-
optional :admin_false_field, type: String, admin: false
|
|
150
|
-
end
|
|
151
|
-
get do
|
|
152
|
-
'bacon'
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
let(:admin_validator) do
|
|
158
|
-
Class.new(Grape::Validations::Validators::Base) do
|
|
159
|
-
def validate(request)
|
|
160
|
-
# return if the param we are checking was not in request
|
|
161
|
-
# @attrs is a list containing the attribute we are currently validating
|
|
162
|
-
return unless request.params.key? @attrs.first
|
|
163
|
-
# check if admin flag is set to true
|
|
164
|
-
return unless @option
|
|
165
|
-
# check if user is admin or not
|
|
166
|
-
# as an example get a token from request and check if it's admin or not
|
|
167
|
-
raise Grape::Exceptions::Validation.new(params: @attrs, message: 'Can not set Admin only field.') unless request.headers['X-Access-Token'] == 'admin'
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
let(:app) { Rack::Builder.new(subject) }
|
|
172
|
-
|
|
173
|
-
before do
|
|
174
|
-
described_class.register_validator('admin', admin_validator)
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
after do
|
|
178
|
-
described_class.deregister_validator('admin')
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
it 'fail when non-admin user sets an admin field' do
|
|
182
|
-
get '/', admin_field: 'tester', non_admin_field: 'toaster'
|
|
183
|
-
expect(last_response.status).to eq 400
|
|
184
|
-
expect(last_response.body).to include 'Can not set Admin only field.'
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
it 'does not fail when we send non-admin fields only' do
|
|
188
|
-
get '/', non_admin_field: 'toaster'
|
|
189
|
-
expect(last_response.status).to eq 200
|
|
190
|
-
expect(last_response.body).to eq 'bacon'
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
it 'does not fail when we send non-admin and admin=false fields only' do
|
|
194
|
-
get '/', non_admin_field: 'toaster', admin_false_field: 'test'
|
|
195
|
-
expect(last_response.status).to eq 200
|
|
196
|
-
expect(last_response.body).to eq 'bacon'
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
it 'does not fail when we send admin fields and we are admin' do
|
|
200
|
-
header 'X-Access-Token', 'admin'
|
|
201
|
-
get '/', admin_field: 'tester', non_admin_field: 'toaster', admin_false_field: 'test'
|
|
202
|
-
expect(last_response.status).to eq 200
|
|
203
|
-
expect(last_response.body).to eq 'bacon'
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
it 'fails when we send admin fields and we are not admin' do
|
|
207
|
-
header 'X-Access-Token', 'user'
|
|
208
|
-
get '/', admin_field: 'tester', non_admin_field: 'toaster', admin_false_field: 'test'
|
|
209
|
-
expect(last_response.status).to eq 400
|
|
210
|
-
expect(last_response.body).to include 'Can not set Admin only field.'
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
end
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module DeeplyIncludedOptionsSpec
|
|
4
|
-
module Defaults
|
|
5
|
-
extend ActiveSupport::Concern
|
|
6
|
-
included do
|
|
7
|
-
format :json
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
module Admin
|
|
12
|
-
module Defaults
|
|
13
|
-
extend ActiveSupport::Concern
|
|
14
|
-
include DeeplyIncludedOptionsSpec::Defaults
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
class Users < Grape::API
|
|
18
|
-
include DeeplyIncludedOptionsSpec::Admin::Defaults
|
|
19
|
-
|
|
20
|
-
resource :users do
|
|
21
|
-
get do
|
|
22
|
-
status 200
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
class Main < Grape::API
|
|
29
|
-
mount DeeplyIncludedOptionsSpec::Admin::Users
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
describe Grape::API do
|
|
34
|
-
subject { DeeplyIncludedOptionsSpec::Main }
|
|
35
|
-
|
|
36
|
-
def app
|
|
37
|
-
subject
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it 'works for unspecified format' do
|
|
41
|
-
get '/users'
|
|
42
|
-
expect(last_response.status).to be 200
|
|
43
|
-
expect(last_response.content_type).to eql 'application/json'
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it 'works for specified format' do
|
|
47
|
-
get '/users.json'
|
|
48
|
-
expect(last_response.status).to be 200
|
|
49
|
-
expect(last_response.content_type).to eql 'application/json'
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "doesn't work for format different than specified" do
|
|
53
|
-
get '/users.txt'
|
|
54
|
-
expect(last_response.status).to be 404
|
|
55
|
-
end
|
|
56
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe Grape::API::Instance do
|
|
4
|
-
describe 'boolean constant' do
|
|
5
|
-
module DefinesBooleanInstanceSpec
|
|
6
|
-
class API < Grape::API
|
|
7
|
-
params do
|
|
8
|
-
requires :message, type: Boolean
|
|
9
|
-
end
|
|
10
|
-
post :echo do
|
|
11
|
-
{ class: params[:message].class.name, value: params[:message] }
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def app
|
|
17
|
-
DefinesBooleanInstanceSpec::API
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
let(:expected_body) do
|
|
21
|
-
{ class: 'TrueClass', value: true }.to_s
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
it 'sets Boolean as a type' do
|
|
25
|
-
post '/echo?message=true'
|
|
26
|
-
expect(last_response.status).to eq(201)
|
|
27
|
-
expect(last_response.body).to eq expected_body
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
context 'Params endpoint type' do
|
|
31
|
-
subject { DefinesBooleanInstanceSpec::API.new.router.map['POST'].first.options[:params]['message'][:type] }
|
|
32
|
-
|
|
33
|
-
it 'params type is a boolean' do
|
|
34
|
-
expect(subject).to eq 'Grape::API::Boolean'
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Grape::API do
|
|
6
|
-
subject { Class.new(described_class) }
|
|
7
|
-
|
|
8
|
-
let(:app) { subject }
|
|
9
|
-
|
|
10
|
-
context 'an endpoint with documentation' do
|
|
11
|
-
it 'documents parameters' do
|
|
12
|
-
subject.params do
|
|
13
|
-
requires 'price', type: Float, desc: 'Sales price'
|
|
14
|
-
end
|
|
15
|
-
subject.get '/'
|
|
16
|
-
|
|
17
|
-
expect(subject.routes.first.params['price']).to eq(required: true,
|
|
18
|
-
type: 'Float',
|
|
19
|
-
desc: 'Sales price')
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it 'allows documentation with a hash' do
|
|
23
|
-
documentation = { example: 'Joe' }
|
|
24
|
-
|
|
25
|
-
subject.params do
|
|
26
|
-
requires 'first_name', documentation: documentation
|
|
27
|
-
end
|
|
28
|
-
subject.get '/'
|
|
29
|
-
|
|
30
|
-
expect(subject.routes.first.params['first_name'][:documentation]).to eq(documentation)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
context 'an endpoint without documentation' do
|
|
35
|
-
before do
|
|
36
|
-
subject.do_not_document!
|
|
37
|
-
|
|
38
|
-
subject.params do
|
|
39
|
-
requires :city, type: String, desc: 'Should be ignored'
|
|
40
|
-
optional :postal_code, type: Integer
|
|
41
|
-
end
|
|
42
|
-
subject.post '/' do
|
|
43
|
-
declared(params).to_json
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it 'does not document parameters for the endpoint' do
|
|
48
|
-
expect(subject.routes.first.params).to eq({})
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
it 'still declares params internally' do
|
|
52
|
-
data = { city: 'Berlin', postal_code: 10_115 }
|
|
53
|
-
|
|
54
|
-
post '/', data
|
|
55
|
-
|
|
56
|
-
expect(last_response.body).to eq(data.to_json)
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe Grape::API::Helpers do
|
|
4
|
-
let(:user) { 'Miguel Caneo' }
|
|
5
|
-
let(:id) { '42' }
|
|
6
|
-
|
|
7
|
-
module InheritedHelpersSpec
|
|
8
|
-
class SuperClass < Grape::API
|
|
9
|
-
helpers do
|
|
10
|
-
params(:superclass_params) { requires :id, type: String }
|
|
11
|
-
|
|
12
|
-
def current_user
|
|
13
|
-
params[:user]
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
class OverriddenSubClass < SuperClass
|
|
19
|
-
params { use :superclass_params }
|
|
20
|
-
|
|
21
|
-
helpers do
|
|
22
|
-
def current_user
|
|
23
|
-
"#{params[:user]} with id"
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
get 'resource' do
|
|
28
|
-
"#{current_user}: #{params['id']}"
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
class SubClass < SuperClass
|
|
33
|
-
params { use :superclass_params }
|
|
34
|
-
|
|
35
|
-
get 'resource' do
|
|
36
|
-
"#{current_user}: #{params['id']}"
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
class Example < SubClass
|
|
41
|
-
params { use :superclass_params }
|
|
42
|
-
|
|
43
|
-
get 'resource' do
|
|
44
|
-
"#{current_user}: #{params['id']}"
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
context 'non overriding subclass' do
|
|
50
|
-
subject { InheritedHelpersSpec::SubClass }
|
|
51
|
-
|
|
52
|
-
def app
|
|
53
|
-
subject
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
context 'given expected params' do
|
|
57
|
-
it 'inherits helpers from a superclass' do
|
|
58
|
-
get '/resource', id: id, user: user
|
|
59
|
-
expect(last_response.body).to eq("#{user}: #{id}")
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
context 'with lack of expected params' do
|
|
64
|
-
it 'returns missing error' do
|
|
65
|
-
get '/resource'
|
|
66
|
-
expect(last_response.body).to eq('id is missing')
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
context 'overriding subclass' do
|
|
72
|
-
subject { InheritedHelpersSpec::OverriddenSubClass }
|
|
73
|
-
|
|
74
|
-
def app
|
|
75
|
-
subject
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
context 'given expected params' do
|
|
79
|
-
it 'overrides helpers from a superclass' do
|
|
80
|
-
get '/resource', id: id, user: user
|
|
81
|
-
expect(last_response.body).to eq("#{user} with id: #{id}")
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
context 'with lack of expected params' do
|
|
86
|
-
it 'returns missing error' do
|
|
87
|
-
get '/resource'
|
|
88
|
-
expect(last_response.body).to eq('id is missing')
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
context 'example subclass' do
|
|
94
|
-
subject { InheritedHelpersSpec::Example }
|
|
95
|
-
|
|
96
|
-
def app
|
|
97
|
-
subject
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
context 'given expected params' do
|
|
101
|
-
it 'inherits helpers from a superclass' do
|
|
102
|
-
get '/resource', id: id, user: user
|
|
103
|
-
expect(last_response.body).to eq("#{user}: #{id}")
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
context 'with lack of expected params' do
|
|
108
|
-
it 'returns missing error' do
|
|
109
|
-
get '/resource'
|
|
110
|
-
expect(last_response.body).to eq('id is missing')
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|