grape 1.1.0 → 1.5.3
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 +278 -44
- data/LICENSE +1 -1
- data/README.md +514 -69
- data/UPGRADING.md +424 -17
- data/grape.gemspec +13 -2
- data/lib/grape.rb +104 -71
- data/lib/grape/api.rb +138 -175
- data/lib/grape/api/helpers.rb +2 -0
- data/lib/grape/api/instance.rb +283 -0
- data/lib/grape/config.rb +34 -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 +22 -0
- data/lib/grape/dsl/configuration.rb +2 -0
- data/lib/grape/dsl/desc.rb +41 -7
- data/lib/grape/dsl/headers.rb +2 -0
- data/lib/grape/dsl/helpers.rb +5 -2
- data/lib/grape/dsl/inside_route.rb +92 -49
- data/lib/grape/dsl/logger.rb +2 -0
- data/lib/grape/dsl/middleware.rb +9 -0
- data/lib/grape/dsl/parameters.rb +25 -14
- data/lib/grape/dsl/request_response.rb +4 -2
- data/lib/grape/dsl/routing.rb +17 -10
- data/lib/grape/dsl/settings.rb +7 -1
- data/lib/grape/dsl/validations.rb +24 -4
- data/lib/grape/eager_load.rb +20 -0
- data/lib/grape/endpoint.rb +59 -35
- data/lib/grape/error_formatter.rb +4 -2
- 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 +20 -14
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- 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 +11 -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 +4 -2
- data/lib/grape/exceptions/validation_array_errors.rb +2 -0
- data/lib/grape/exceptions/validation_errors.rb +16 -13
- 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/locale/en.yml +3 -1
- data/lib/grape/middleware/auth/base.rb +7 -7
- 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 +10 -7
- data/lib/grape/middleware/error.rb +21 -16
- 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 +12 -0
- data/lib/grape/middleware/stack.rb +13 -3
- 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 +10 -8
- 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 +4 -2
- data/lib/grape/parser/json.rb +3 -1
- data/lib/grape/parser/xml.rb +3 -1
- data/lib/grape/path.rb +15 -3
- data/lib/grape/presenters/presenter.rb +2 -0
- data/lib/grape/request.rb +19 -10
- data/lib/grape/router.rb +30 -29
- data/lib/grape/router/attribute_translator.rb +41 -8
- data/lib/grape/router/pattern.rb +20 -16
- data/lib/grape/router/route.rb +14 -28
- 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 +43 -0
- data/lib/grape/util/cache.rb +20 -0
- data/lib/grape/util/endpoint_configuration.rb +8 -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 +7 -25
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_block.rb +27 -0
- data/lib/grape/util/lazy_object.rb +43 -0
- data/lib/grape/util/lazy_value.rb +98 -0
- data/lib/grape/util/registrable.rb +2 -0
- data/lib/grape/util/reverse_stackable_values.rb +10 -35
- data/lib/grape/util/stackable_values.rb +21 -34
- 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 +16 -6
- data/lib/grape/validations/multiple_attributes_iterator.rb +13 -0
- data/lib/grape/validations/params_scope.rb +51 -30
- data/lib/grape/validations/single_attribute_iterator.rb +24 -0
- data/lib/grape/validations/types.rb +13 -38
- 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 +29 -51
- 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/invalid_value.rb +24 -0
- 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 +8 -11
- data/lib/grape/validations/validators/all_or_none.rb +8 -13
- data/lib/grape/validations/validators/allow_blank.rb +3 -1
- data/lib/grape/validations/validators/as.rb +5 -4
- data/lib/grape/validations/validators/at_least_one_of.rb +7 -13
- data/lib/grape/validations/validators/base.rb +20 -16
- data/lib/grape/validations/validators/coerce.rb +46 -29
- data/lib/grape/validations/validators/default.rb +6 -6
- data/lib/grape/validations/validators/exactly_one_of.rb +10 -23
- data/lib/grape/validations/validators/except_values.rb +4 -2
- data/lib/grape/validations/validators/multiple_params_base.rb +17 -10
- data/lib/grape/validations/validators/mutual_exclusion.rb +8 -18
- 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 +26 -0
- data/lib/grape/validations/validators/values.rb +18 -6
- 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 +39 -0
- 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 +61 -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 +473 -0
- data/spec/grape/api_spec.rb +565 -12
- data/spec/grape/config_spec.rb +19 -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 +42 -16
- 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 +184 -33
- data/spec/grape/dsl/logger_spec.rb +2 -0
- data/spec/grape/dsl/middleware_spec.rb +10 -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 +12 -0
- data/spec/grape/dsl/settings_spec.rb +2 -0
- data/spec/grape/dsl/validations_spec.rb +2 -0
- data/spec/grape/endpoint/declared_spec.rb +601 -0
- data/spec/grape/endpoint_spec.rb +53 -523
- data/spec/grape/entity_spec.rb +9 -1
- data/spec/grape/exceptions/base_spec.rb +67 -0
- 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 +13 -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 +8 -4
- 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 +25 -7
- 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 +5 -3
- data/spec/grape/middleware/auth/strategies_spec.rb +3 -1
- data/spec/grape/middleware/base_spec.rb +10 -0
- data/spec/grape/middleware/error_spec.rb +3 -1
- data/spec/grape/middleware/exception_spec.rb +4 -2
- data/spec/grape/middleware/formatter_spec.rb +33 -16
- data/spec/grape/middleware/globals_spec.rb +2 -0
- data/spec/grape/middleware/stack_spec.rb +12 -0
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
- data/spec/grape/middleware/versioner/header_spec.rb +9 -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 +21 -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 +26 -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 +41 -0
- data/spec/grape/validations/params_scope_spec.rb +213 -9
- data/spec/grape/validations/single_attribute_iterator_spec.rb +58 -0
- 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 +140 -30
- data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +175 -29
- data/spec/grape/validations/validators/coerce_spec.rb +476 -135
- data/spec/grape/validations/validators/default_spec.rb +172 -0
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +204 -38
- data/spec/grape/validations/validators/except_values_spec.rb +4 -1
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +186 -27
- 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 +65 -0
- data/spec/grape/validations/validators/values_spec.rb +30 -5
- data/spec/grape/validations_spec.rb +388 -50
- 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 +22 -20
- data/spec/spec_helper.rb +12 -1
- data/spec/support/basic_auth_encode_helpers.rb +2 -0
- data/spec/support/chunks.rb +14 -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 +8 -8
- metadata +86 -48
- data/Appraisals +0 -32
- data/Dangerfile +0 -2
- data/Gemfile +0 -33
- data/Gemfile.lock +0 -231
- data/Guardfile +0 -10
- data/RELEASING.md +0 -111
- data/Rakefile +0 -25
- data/benchmark/simple.rb +0 -27
- data/benchmark/simple_with_type_coercer.rb +0 -22
- data/gemfiles/multi_json.gemfile +0 -35
- data/gemfiles/multi_xml.gemfile +0 -35
- data/gemfiles/rack_1.5.2.gemfile +0 -35
- data/gemfiles/rack_edge.gemfile +0 -35
- data/gemfiles/rails_3.gemfile +0 -36
- data/gemfiles/rails_4.gemfile +0 -35
- data/gemfiles/rails_5.gemfile +0 -35
- data/gemfiles/rails_edge.gemfile +0 -35
- 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
- data/pkg/grape-0.17.0.gem +0 -0
- data/pkg/grape-0.19.0.gem +0 -0
data/lib/grape/dsl/headers.rb
CHANGED
data/lib/grape/dsl/helpers.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/concern'
|
2
4
|
|
3
5
|
module Grape
|
@@ -65,7 +67,7 @@ module Grape
|
|
65
67
|
|
66
68
|
def define_boolean_in_mod(mod)
|
67
69
|
return if defined? mod::Boolean
|
68
|
-
mod.const_set('Boolean',
|
70
|
+
mod.const_set('Boolean', Grape::API::Boolean)
|
69
71
|
end
|
70
72
|
|
71
73
|
def inject_api_helpers_to_mod(mod, &_block)
|
@@ -79,6 +81,7 @@ module Grape
|
|
79
81
|
# to provide some API-specific functionality.
|
80
82
|
module BaseHelper
|
81
83
|
attr_accessor :api
|
84
|
+
|
82
85
|
def params(name, &block)
|
83
86
|
@named_params ||= {}
|
84
87
|
@named_params[name] = block
|
@@ -92,7 +95,7 @@ module Grape
|
|
92
95
|
protected
|
93
96
|
|
94
97
|
def process_named_params
|
95
|
-
return unless @named_params && @named_params.any?
|
98
|
+
return unless instance_variable_defined?(:@named_params) && @named_params && @named_params.any?
|
96
99
|
api.namespace_stackable(:named_params, @named_params)
|
97
100
|
end
|
98
101
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/concern'
|
2
4
|
require 'grape/dsl/headers'
|
3
5
|
|
@@ -26,82 +28,92 @@ module Grape
|
|
26
28
|
# Methods which should not be available in filters until the before filter
|
27
29
|
# has completed
|
28
30
|
module PostBeforeFilter
|
29
|
-
def declared(passed_params, options = {}, declared_params = nil)
|
31
|
+
def declared(passed_params, options = {}, declared_params = nil, params_nested_path = [])
|
30
32
|
options = options.reverse_merge(include_missing: true, include_parent_namespaces: true)
|
31
|
-
declared_params ||= optioned_declared_params(options)
|
33
|
+
declared_params ||= optioned_declared_params(**options)
|
32
34
|
|
33
35
|
if passed_params.is_a?(Array)
|
34
|
-
declared_array(passed_params, options, declared_params)
|
36
|
+
declared_array(passed_params, options, declared_params, params_nested_path)
|
35
37
|
else
|
36
|
-
declared_hash(passed_params, options, declared_params)
|
38
|
+
declared_hash(passed_params, options, declared_params, params_nested_path)
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
42
|
private
|
41
43
|
|
42
|
-
def declared_array(passed_params, options, declared_params)
|
44
|
+
def declared_array(passed_params, options, declared_params, params_nested_path)
|
43
45
|
passed_params.map do |passed_param|
|
44
|
-
declared(passed_param || {}, options, declared_params)
|
46
|
+
declared(passed_param || {}, options, declared_params, params_nested_path)
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
def declared_hash(passed_params, options, declared_params)
|
50
|
+
def declared_hash(passed_params, options, declared_params, params_nested_path)
|
49
51
|
declared_params.each_with_object(passed_params.class.new) do |declared_param, memo|
|
50
52
|
if declared_param.is_a?(Hash)
|
51
53
|
declared_param.each_pair do |declared_parent_param, declared_children_params|
|
54
|
+
params_nested_path_dup = params_nested_path.dup
|
55
|
+
params_nested_path_dup << declared_parent_param.to_s
|
52
56
|
next unless options[:include_missing] || passed_params.key?(declared_parent_param)
|
53
57
|
|
54
58
|
passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
|
55
59
|
memo_key = optioned_param_key(declared_parent_param, options)
|
56
60
|
|
57
|
-
memo[memo_key] = handle_passed_param(
|
58
|
-
declared(passed_children_params, options, declared_children_params)
|
61
|
+
memo[memo_key] = handle_passed_param(params_nested_path_dup, passed_children_params.any?) do
|
62
|
+
declared(passed_children_params, options, declared_children_params, params_nested_path_dup)
|
59
63
|
end
|
60
64
|
end
|
61
65
|
else
|
62
66
|
# If it is not a Hash then it does not have children.
|
63
67
|
# Find its value or set it to nil.
|
64
|
-
|
65
|
-
|
68
|
+
has_renaming = route_setting(:renamed_params) && route_setting(:renamed_params).find { |current| current[declared_param] }
|
69
|
+
param_renaming = has_renaming[declared_param] if has_renaming
|
70
|
+
|
71
|
+
next unless options[:include_missing] || passed_params.key?(declared_param) || (param_renaming && passed_params.key?(param_renaming))
|
66
72
|
|
67
|
-
|
73
|
+
memo_key = optioned_param_key(param_renaming || declared_param, options)
|
74
|
+
passed_param = passed_params[param_renaming || declared_param]
|
68
75
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
76
|
+
params_nested_path_dup = params_nested_path.dup
|
77
|
+
params_nested_path_dup << declared_param.to_s
|
78
|
+
memo[memo_key] = passed_param || handle_passed_param(params_nested_path_dup) do
|
79
|
+
passed_param
|
73
80
|
end
|
74
81
|
end
|
75
82
|
end
|
76
83
|
end
|
77
84
|
|
78
|
-
def handle_passed_param(
|
79
|
-
|
80
|
-
end
|
85
|
+
def handle_passed_param(params_nested_path, has_passed_children = false, &_block)
|
86
|
+
return yield if has_passed_children
|
81
87
|
|
82
|
-
|
83
|
-
|
84
|
-
end
|
88
|
+
key = params_nested_path[0]
|
89
|
+
key += '[' + params_nested_path[1..-1].join('][') + ']' if params_nested_path.size > 1
|
85
90
|
|
86
|
-
|
87
|
-
|
88
|
-
|
91
|
+
route_options_params = options[:route_options][:params] || {}
|
92
|
+
type = route_options_params.dig(key, :type)
|
93
|
+
has_children = route_options_params.keys.any? { |k| k != key && k.start_with?(key) }
|
89
94
|
|
90
|
-
|
91
|
-
|
95
|
+
if type == 'Hash' && !has_children
|
96
|
+
{}
|
97
|
+
elsif type == 'Array' || type&.start_with?('[') && !type&.include?(',')
|
98
|
+
[]
|
99
|
+
elsif type == 'Set' || type&.start_with?('#<Set')
|
100
|
+
Set.new
|
101
|
+
else
|
102
|
+
yield
|
103
|
+
end
|
92
104
|
end
|
93
105
|
|
94
106
|
def optioned_param_key(declared_param, options)
|
95
107
|
options[:stringify] ? declared_param.to_s : declared_param.to_sym
|
96
108
|
end
|
97
109
|
|
98
|
-
def optioned_declared_params(options)
|
110
|
+
def optioned_declared_params(**options)
|
99
111
|
declared_params = if options[:include_parent_namespaces]
|
100
112
|
# Declared params including parent namespaces
|
101
|
-
route_setting(:
|
113
|
+
route_setting(:declared_params)
|
102
114
|
else
|
103
115
|
# Declared params at current namespace
|
104
|
-
|
116
|
+
namespace_stackable(:declared_params).last || []
|
105
117
|
end
|
106
118
|
|
107
119
|
raise ArgumentError, 'Tried to filter for declared parameters but none exist.' unless declared_params
|
@@ -129,13 +141,19 @@ module Grape
|
|
129
141
|
env[Grape::Env::API_VERSION]
|
130
142
|
end
|
131
143
|
|
144
|
+
def configuration
|
145
|
+
options[:for].configuration.evaluate
|
146
|
+
end
|
147
|
+
|
132
148
|
# End the request and display an error to the
|
133
149
|
# end user with the specified message.
|
134
150
|
#
|
135
151
|
# @param message [String] The message to display.
|
136
152
|
# @param status [Integer] the HTTP Status Code. Defaults to default_error_status, 500 if not set.
|
137
|
-
|
153
|
+
# @param additional_headers [Hash] Addtional headers for the response.
|
154
|
+
def error!(message, status = nil, additional_headers = nil)
|
138
155
|
self.status(status || namespace_inheritable(:default_error_status))
|
156
|
+
headers = additional_headers.present? ? header.merge(additional_headers) : header
|
139
157
|
throw :error, message: message, status: self.status, headers: headers
|
140
158
|
end
|
141
159
|
|
@@ -168,17 +186,17 @@ module Grape
|
|
168
186
|
def status(status = nil)
|
169
187
|
case status
|
170
188
|
when Symbol
|
171
|
-
raise ArgumentError, "Status code :#{status} is invalid." unless Rack::Utils::SYMBOL_TO_STATUS_CODE.
|
189
|
+
raise ArgumentError, "Status code :#{status} is invalid." unless Rack::Utils::SYMBOL_TO_STATUS_CODE.key?(status)
|
172
190
|
@status = Rack::Utils.status_code(status)
|
173
191
|
when Integer
|
174
192
|
@status = status
|
175
193
|
when nil
|
176
|
-
return @status if @status
|
194
|
+
return @status if instance_variable_defined?(:@status) && @status
|
177
195
|
case request.request_method.to_s.upcase
|
178
196
|
when Grape::Http::Headers::POST
|
179
197
|
201
|
180
198
|
when Grape::Http::Headers::DELETE
|
181
|
-
if @body.present?
|
199
|
+
if instance_variable_defined?(:@body) && @body.present?
|
182
200
|
200
|
183
201
|
else
|
184
202
|
204
|
@@ -229,7 +247,7 @@ module Grape
|
|
229
247
|
@body = ''
|
230
248
|
status 204
|
231
249
|
else
|
232
|
-
@body
|
250
|
+
instance_variable_defined?(:@body) ? @body : nil
|
233
251
|
end
|
234
252
|
end
|
235
253
|
|
@@ -247,23 +265,36 @@ module Grape
|
|
247
265
|
body false
|
248
266
|
end
|
249
267
|
|
250
|
-
#
|
268
|
+
# Deprecated method to send files to the client. Use `sendfile` or `stream`
|
269
|
+
def file(value = nil)
|
270
|
+
if value.is_a?(String)
|
271
|
+
warn '[DEPRECATION] Use sendfile or stream to send files.'
|
272
|
+
sendfile(value)
|
273
|
+
elsif !value.is_a?(NilClass)
|
274
|
+
warn '[DEPRECATION] Use stream to use a Stream object.'
|
275
|
+
stream(value)
|
276
|
+
else
|
277
|
+
warn '[DEPRECATION] Use sendfile or stream to send files.'
|
278
|
+
sendfile
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
# Allows you to send a file to the client via sendfile.
|
251
283
|
#
|
252
284
|
# @example
|
253
285
|
# get '/file' do
|
254
|
-
#
|
286
|
+
# sendfile FileStreamer.new(...)
|
255
287
|
# end
|
256
288
|
#
|
257
289
|
# GET /file # => "contents of file"
|
258
|
-
def
|
290
|
+
def sendfile(value = nil)
|
259
291
|
if value.is_a?(String)
|
260
|
-
file_body = Grape::
|
261
|
-
@
|
292
|
+
file_body = Grape::ServeStream::FileBody.new(value)
|
293
|
+
@stream = Grape::ServeStream::StreamResponse.new(file_body)
|
262
294
|
elsif !value.is_a?(NilClass)
|
263
|
-
|
264
|
-
@file = Grape::ServeFile::FileResponse.new(value)
|
295
|
+
raise ArgumentError, 'Argument must be a file path'
|
265
296
|
else
|
266
|
-
|
297
|
+
stream
|
267
298
|
end
|
268
299
|
end
|
269
300
|
|
@@ -283,10 +314,21 @@ module Grape
|
|
283
314
|
# * https://github.com/rack/rack/blob/99293fa13d86cd48021630fcc4bd5acc9de5bdc3/lib/rack/chunked.rb
|
284
315
|
# * https://github.com/rack/rack/blob/99293fa13d86cd48021630fcc4bd5acc9de5bdc3/lib/rack/etag.rb
|
285
316
|
def stream(value = nil)
|
317
|
+
return if value.nil? && @stream.nil?
|
318
|
+
|
286
319
|
header 'Content-Length', nil
|
287
320
|
header 'Transfer-Encoding', nil
|
288
321
|
header 'Cache-Control', 'no-cache' # Skips ETag generation (reading the response up front)
|
289
|
-
|
322
|
+
if value.is_a?(String)
|
323
|
+
file_body = Grape::ServeStream::FileBody.new(value)
|
324
|
+
@stream = Grape::ServeStream::StreamResponse.new(file_body)
|
325
|
+
elsif value.respond_to?(:each)
|
326
|
+
@stream = Grape::ServeStream::StreamResponse.new(value)
|
327
|
+
elsif !value.is_a?(NilClass)
|
328
|
+
raise ArgumentError, 'Stream object must respond to :each.'
|
329
|
+
else
|
330
|
+
@stream
|
331
|
+
end
|
290
332
|
end
|
291
333
|
|
292
334
|
# Allows you to make use of Grape Entities by setting
|
@@ -322,11 +364,12 @@ module Grape
|
|
322
364
|
end
|
323
365
|
|
324
366
|
representation = { root => representation } if root
|
367
|
+
|
325
368
|
if key
|
326
|
-
representation = (
|
327
|
-
elsif entity_class.present? &&
|
369
|
+
representation = (body || {}).merge(key => representation)
|
370
|
+
elsif entity_class.present? && body
|
328
371
|
raise ArgumentError, "Representation of type #{representation.class} cannot be merged." unless representation.respond_to?(:merge)
|
329
|
-
representation =
|
372
|
+
representation = body.merge(representation)
|
330
373
|
end
|
331
374
|
|
332
375
|
body representation
|
@@ -356,7 +399,7 @@ module Grape
|
|
356
399
|
entity_class = options.delete(:with)
|
357
400
|
|
358
401
|
if entity_class.nil?
|
359
|
-
# entity class not
|
402
|
+
# entity class not explicitly defined, auto-detect from relation#klass or first object in the collection
|
360
403
|
object_class = if object.respond_to?(:klass)
|
361
404
|
object.klass
|
362
405
|
else
|
@@ -378,7 +421,7 @@ module Grape
|
|
378
421
|
def entity_representation_for(entity_class, object, options)
|
379
422
|
embeds = { env: env }
|
380
423
|
embeds[:version] = env[Grape::Env::API_VERSION] if env[Grape::Env::API_VERSION]
|
381
|
-
entity_class.represent(object, embeds.merge(options))
|
424
|
+
entity_class.represent(object, **embeds.merge(options))
|
382
425
|
end
|
383
426
|
end
|
384
427
|
end
|
data/lib/grape/dsl/logger.rb
CHANGED
data/lib/grape/dsl/middleware.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/concern'
|
2
4
|
|
3
5
|
module Grape
|
@@ -21,6 +23,13 @@ module Grape
|
|
21
23
|
namespace_stackable(:middleware, arr)
|
22
24
|
end
|
23
25
|
|
26
|
+
def insert(*args, &block)
|
27
|
+
arr = [:insert, *args]
|
28
|
+
arr << block if block_given?
|
29
|
+
|
30
|
+
namespace_stackable(:middleware, arr)
|
31
|
+
end
|
32
|
+
|
24
33
|
def insert_before(*args, &block)
|
25
34
|
arr = [:insert_before, *args]
|
26
35
|
arr << block if block_given?
|
data/lib/grape/dsl/parameters.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/concern'
|
2
4
|
|
3
5
|
module Grape
|
@@ -70,7 +72,7 @@ module Grape
|
|
70
72
|
|
71
73
|
# Require one or more parameters for the current endpoint.
|
72
74
|
#
|
73
|
-
# @param attrs list of
|
75
|
+
# @param attrs list of parameters names, or, if :using is
|
74
76
|
# passed as an option, which keys to include (:all or :none) from
|
75
77
|
# the :using hash. The last key can be a hash, which specifies
|
76
78
|
# options for the parameters
|
@@ -125,13 +127,13 @@ module Grape
|
|
125
127
|
|
126
128
|
opts = attrs.extract_options!.clone
|
127
129
|
opts[:presence] = { value: true, message: opts[:message] }
|
128
|
-
opts = @group.merge(opts) if @group
|
130
|
+
opts = @group.merge(opts) if instance_variable_defined?(:@group) && @group
|
129
131
|
|
130
132
|
if opts[:using]
|
131
133
|
require_required_and_optional_fields(attrs.first, opts)
|
132
134
|
else
|
133
135
|
validate_attributes(attrs, opts, &block)
|
134
|
-
block_given? ? new_scope(orig_attrs, &block) : push_declared_params(attrs, opts.slice(:as))
|
136
|
+
block_given? ? new_scope(orig_attrs, &block) : push_declared_params(attrs, **opts.slice(:as))
|
135
137
|
end
|
136
138
|
end
|
137
139
|
|
@@ -144,7 +146,7 @@ module Grape
|
|
144
146
|
|
145
147
|
opts = attrs.extract_options!.clone
|
146
148
|
type = opts[:type]
|
147
|
-
opts = @group.merge(opts) if @group
|
149
|
+
opts = @group.merge(opts) if instance_variable_defined?(:@group) && @group
|
148
150
|
|
149
151
|
# check type for optional parameter group
|
150
152
|
if attrs && block_given?
|
@@ -157,7 +159,7 @@ module Grape
|
|
157
159
|
else
|
158
160
|
validate_attributes(attrs, opts, &block)
|
159
161
|
|
160
|
-
block_given? ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, opts.slice(:as))
|
162
|
+
block_given? ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, **opts.slice(:as))
|
161
163
|
end
|
162
164
|
end
|
163
165
|
|
@@ -211,22 +213,31 @@ module Grape
|
|
211
213
|
# block yet.
|
212
214
|
# @return [Boolean] whether the parameter has been defined
|
213
215
|
def declared_param?(param)
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
216
|
+
if lateral?
|
217
|
+
# Elements of @declared_params of lateral scope are pushed in @parent. So check them in @parent.
|
218
|
+
@parent.declared_param?(param)
|
219
|
+
else
|
220
|
+
# @declared_params also includes hashes of options and such, but those
|
221
|
+
# won't be flattened out.
|
222
|
+
@declared_params.flatten.any? do |declared_param|
|
223
|
+
first_hash_key_or_param(declared_param) == param
|
224
|
+
end
|
218
225
|
end
|
219
226
|
end
|
220
227
|
|
221
228
|
alias group requires
|
222
229
|
|
223
|
-
|
230
|
+
class EmptyOptionalValue; end
|
231
|
+
|
232
|
+
def map_params(params, element, is_array = false)
|
224
233
|
if params.is_a?(Array)
|
225
234
|
params.map do |el|
|
226
|
-
map_params(el, element)
|
235
|
+
map_params(el, element, true)
|
227
236
|
end
|
228
237
|
elsif params.is_a?(Hash)
|
229
|
-
params[element] || {}
|
238
|
+
params[element] || (@optional && is_array ? EmptyOptionalValue : {})
|
239
|
+
elsif params == EmptyOptionalValue
|
240
|
+
EmptyOptionalValue
|
230
241
|
else
|
231
242
|
{}
|
232
243
|
end
|
@@ -236,8 +247,8 @@ module Grape
|
|
236
247
|
# @return hash of parameters relevant for the current scope
|
237
248
|
# @api private
|
238
249
|
def params(params)
|
239
|
-
params = @parent.params(params) if @parent
|
240
|
-
params = map_params(params, @element) if @element
|
250
|
+
params = @parent.params(params) if instance_variable_defined?(:@parent) && @parent
|
251
|
+
params = map_params(params, @element) if instance_variable_defined?(:@element) && @element
|
241
252
|
params
|
242
253
|
end
|
243
254
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/concern'
|
2
4
|
|
3
5
|
module Grape
|
@@ -20,7 +22,7 @@ module Grape
|
|
20
22
|
if new_format
|
21
23
|
namespace_inheritable(:format, new_format.to_sym)
|
22
24
|
# define the default error formatters
|
23
|
-
namespace_inheritable(:default_error_formatter, Grape::ErrorFormatter.formatter_for(new_format, {}))
|
25
|
+
namespace_inheritable(:default_error_formatter, Grape::ErrorFormatter.formatter_for(new_format, **{}))
|
24
26
|
# define a single mime type
|
25
27
|
mime_type = content_types[new_format.to_sym]
|
26
28
|
raise Grape::Exceptions::MissingMimeType.new(new_format) unless mime_type
|
@@ -43,7 +45,7 @@ module Grape
|
|
43
45
|
# Specify a default error formatter.
|
44
46
|
def default_error_formatter(new_formatter_name = nil)
|
45
47
|
if new_formatter_name
|
46
|
-
new_formatter = Grape::ErrorFormatter.formatter_for(new_formatter_name, {})
|
48
|
+
new_formatter = Grape::ErrorFormatter.formatter_for(new_formatter_name, **{})
|
47
49
|
namespace_inheritable(:default_error_formatter, new_formatter)
|
48
50
|
else
|
49
51
|
namespace_inheritable(:default_error_formatter)
|