grape 1.5.3 → 1.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +92 -0
- data/CONTRIBUTING.md +32 -1
- data/README.md +176 -25
- data/UPGRADING.md +61 -4
- data/grape.gemspec +6 -6
- data/lib/grape/api/instance.rb +14 -18
- data/lib/grape/api.rb +17 -12
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dry_types.rb +12 -0
- data/lib/grape/dsl/api.rb +0 -2
- data/lib/grape/dsl/callbacks.rb +0 -2
- data/lib/grape/dsl/configuration.rb +0 -2
- data/lib/grape/dsl/desc.rb +4 -20
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +7 -7
- data/lib/grape/dsl/inside_route.rb +43 -30
- data/lib/grape/dsl/middleware.rb +4 -6
- data/lib/grape/dsl/parameters.rb +13 -10
- data/lib/grape/dsl/request_response.rb +9 -8
- data/lib/grape/dsl/routing.rb +6 -4
- data/lib/grape/dsl/settings.rb +5 -7
- data/lib/grape/dsl/validations.rb +0 -15
- data/lib/grape/endpoint.rb +22 -37
- data/lib/grape/error_formatter/json.rb +9 -7
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/base.rb +3 -2
- data/lib/grape/exceptions/missing_group_type.rb +8 -1
- data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
- data/lib/grape/exceptions/validation.rb +1 -6
- data/lib/grape/formatter/json.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -1
- data/lib/grape/formatter/xml.rb +1 -0
- data/lib/grape/locale/en.yml +9 -8
- data/lib/grape/middleware/auth/dsl.rb +7 -2
- data/lib/grape/middleware/base.rb +3 -1
- data/lib/grape/middleware/error.rb +2 -2
- data/lib/grape/middleware/formatter.rb +4 -4
- data/lib/grape/middleware/stack.rb +3 -3
- data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
- data/lib/grape/middleware/versioner/header.rb +6 -4
- data/lib/grape/middleware/versioner/param.rb +1 -0
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
- data/lib/grape/middleware/versioner/path.rb +2 -0
- data/lib/grape/path.rb +1 -0
- data/lib/grape/request.rb +4 -1
- data/lib/grape/router/attribute_translator.rb +1 -1
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/router.rb +6 -0
- data/lib/grape/types/invalid_value.rb +8 -0
- data/lib/grape/util/cache.rb +1 -1
- data/lib/grape/util/inheritable_setting.rb +1 -3
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_value.rb +3 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/attributes_doc.rb +58 -0
- data/lib/grape/validations/params_scope.rb +138 -79
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/custom_type_coercer.rb +1 -0
- data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
- data/lib/grape/validations/types/invalid_value.rb +0 -7
- data/lib/grape/validations/types/json.rb +2 -1
- data/lib/grape/validations/types/primitive_coercer.rb +16 -8
- data/lib/grape/validations/types/set_coercer.rb +0 -2
- data/lib/grape/validations/types.rb +98 -30
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
- data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
- data/lib/grape/validations/validators/as_validator.rb +14 -0
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
- data/lib/grape/validations/validators/base.rb +82 -70
- data/lib/grape/validations/validators/coerce_validator.rb +75 -0
- data/lib/grape/validations/validators/default_validator.rb +51 -0
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
- data/lib/grape/validations/validators/except_values_validator.rb +24 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
- data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
- data/lib/grape/validations/validators/presence_validator.rb +15 -0
- data/lib/grape/validations/validators/regexp_validator.rb +16 -0
- data/lib/grape/validations/validators/same_as_validator.rb +29 -0
- data/lib/grape/validations/validators/values_validator.rb +88 -0
- data/lib/grape/validations.rb +16 -6
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +77 -29
- data/spec/grape/api/custom_validations_spec.rb +116 -45
- data/spec/grape/api/deeply_included_options_spec.rb +3 -5
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
- data/spec/grape/api/documentation_spec.rb +59 -0
- data/spec/grape/api/inherited_helpers_spec.rb +0 -2
- data/spec/grape/api/instance_spec.rb +0 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -2
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/nested_helpers_spec.rb +0 -2
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/parameters_modification_spec.rb +0 -2
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
- data/spec/grape/api/recognize_path_spec.rb +1 -3
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
- data/spec/grape/api/shared_helpers_spec.rb +0 -2
- data/spec/grape/api_remount_spec.rb +16 -16
- data/spec/grape/api_spec.rb +462 -251
- data/spec/grape/config_spec.rb +0 -2
- data/spec/grape/dsl/callbacks_spec.rb +2 -3
- data/spec/grape/dsl/desc_spec.rb +2 -2
- data/spec/grape/dsl/headers_spec.rb +39 -11
- data/spec/grape/dsl/helpers_spec.rb +3 -4
- data/spec/grape/dsl/inside_route_spec.rb +16 -16
- data/spec/grape/dsl/logger_spec.rb +15 -19
- data/spec/grape/dsl/middleware_spec.rb +2 -3
- data/spec/grape/dsl/parameters_spec.rb +2 -2
- data/spec/grape/dsl/request_response_spec.rb +7 -8
- data/spec/grape/dsl/routing_spec.rb +11 -10
- data/spec/grape/dsl/settings_spec.rb +0 -2
- data/spec/grape/dsl/validations_spec.rb +0 -17
- data/spec/grape/endpoint/declared_spec.rb +261 -16
- data/spec/grape/endpoint_spec.rb +88 -59
- data/spec/grape/entity_spec.rb +22 -23
- data/spec/grape/exceptions/base_spec.rb +16 -2
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +64 -24
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
- data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
- data/spec/grape/exceptions/missing_option_spec.rb +1 -3
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
- data/spec/grape/exceptions/validation_spec.rb +5 -5
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
- data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
- data/spec/grape/integration/rack_spec.rb +6 -7
- data/spec/grape/loading_spec.rb +8 -10
- data/spec/grape/middleware/auth/base_spec.rb +0 -1
- data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
- data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
- data/spec/grape/middleware/base_spec.rb +28 -19
- data/spec/grape/middleware/error_spec.rb +8 -3
- data/spec/grape/middleware/exception_spec.rb +111 -163
- data/spec/grape/middleware/formatter_spec.rb +33 -14
- data/spec/grape/middleware/globals_spec.rb +7 -6
- data/spec/grape/middleware/stack_spec.rb +14 -14
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
- data/spec/grape/middleware/versioner/header_spec.rb +30 -15
- data/spec/grape/middleware/versioner/param_spec.rb +7 -3
- data/spec/grape/middleware/versioner/path_spec.rb +5 -3
- data/spec/grape/middleware/versioner_spec.rb +1 -3
- data/spec/grape/named_api_spec.rb +0 -2
- data/spec/grape/parser_spec.rb +4 -2
- data/spec/grape/path_spec.rb +52 -54
- data/spec/grape/presenters/presenter_spec.rb +7 -8
- data/spec/grape/request_spec.rb +6 -6
- data/spec/grape/util/inheritable_setting_spec.rb +7 -8
- data/spec/grape/util/inheritable_values_spec.rb +3 -3
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
- data/spec/grape/util/stackable_values_spec.rb +7 -6
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
- data/spec/grape/validations/attributes_doc_spec.rb +153 -0
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
- data/spec/grape/validations/params_scope_spec.rb +361 -96
- data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
- data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
- data/spec/grape/validations/types_spec.rb +36 -10
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
- data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
- data/spec/grape/validations/validators/coerce_spec.rb +23 -24
- data/spec/grape/validations/validators/default_spec.rb +72 -80
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
- data/spec/grape/validations/validators/except_values_spec.rb +3 -5
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
- data/spec/grape/validations/validators/presence_spec.rb +16 -3
- data/spec/grape/validations/validators/regexp_spec.rb +25 -33
- data/spec/grape/validations/validators/same_as_spec.rb +14 -22
- data/spec/grape/validations/validators/values_spec.rb +201 -179
- data/spec/grape/validations_spec.rb +171 -79
- data/spec/integration/eager_load/eager_load_spec.rb +2 -2
- data/spec/integration/multi_json/json_spec.rb +1 -3
- data/spec/integration/multi_xml/xml_spec.rb +1 -3
- data/spec/shared/versioning_examples.rb +12 -9
- data/spec/spec_helper.rb +21 -6
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- metadata +41 -29
- data/lib/grape/validations/validators/all_or_none.rb +0 -15
- data/lib/grape/validations/validators/allow_blank.rb +0 -18
- data/lib/grape/validations/validators/as.rb +0 -16
- data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
- data/lib/grape/validations/validators/coerce.rb +0 -91
- data/lib/grape/validations/validators/default.rb +0 -48
- data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
- data/lib/grape/validations/validators/except_values.rb +0 -22
- data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
- data/lib/grape/validations/validators/presence.rb +0 -12
- data/lib/grape/validations/validators/regexp.rb +0 -13
- data/lib/grape/validations/validators/same_as.rb +0 -26
- data/lib/grape/validations/validators/values.rb +0 -83
- data/spec/grape/dsl/configuration_spec.rb +0 -16
- data/spec/grape/validations/attributes_iterator_spec.rb +0 -6
- data/spec/support/eager_load.rb +0 -19
data/lib/grape/api/instance.rb
CHANGED
@@ -10,12 +10,11 @@ module Grape
|
|
10
10
|
include Grape::DSL::API
|
11
11
|
|
12
12
|
class << self
|
13
|
-
attr_reader :instance
|
14
|
-
attr_reader :base
|
13
|
+
attr_reader :instance, :base
|
15
14
|
attr_accessor :configuration
|
16
15
|
|
17
16
|
def given(conditional_option, &block)
|
18
|
-
evaluate_as_instance_with_configuration(block, lazy: true) if conditional_option &&
|
17
|
+
evaluate_as_instance_with_configuration(block, lazy: true) if conditional_option && block
|
19
18
|
end
|
20
19
|
|
21
20
|
def mounted(&block)
|
@@ -28,7 +27,7 @@ module Grape
|
|
28
27
|
end
|
29
28
|
|
30
29
|
def to_s
|
31
|
-
|
30
|
+
base&.to_s || super
|
32
31
|
end
|
33
32
|
|
34
33
|
def base_instance?
|
@@ -82,6 +81,7 @@ module Grape
|
|
82
81
|
|
83
82
|
def compile!
|
84
83
|
return if instance
|
84
|
+
|
85
85
|
LOCK.synchronize { compile unless instance }
|
86
86
|
end
|
87
87
|
|
@@ -101,9 +101,9 @@ module Grape
|
|
101
101
|
# block passed in. Allows for simple 'before' setups
|
102
102
|
# of settings stack pushes.
|
103
103
|
def nest(*blocks, &block)
|
104
|
-
blocks.
|
104
|
+
blocks.compact!
|
105
105
|
if blocks.any?
|
106
|
-
evaluate_as_instance_with_configuration(block) if
|
106
|
+
evaluate_as_instance_with_configuration(block) if block
|
107
107
|
blocks.each { |b| evaluate_as_instance_with_configuration(b) }
|
108
108
|
reset_validations!
|
109
109
|
else
|
@@ -114,9 +114,7 @@ module Grape
|
|
114
114
|
def evaluate_as_instance_with_configuration(block, lazy: false)
|
115
115
|
lazy_block = Grape::Util::LazyBlock.new do |configuration|
|
116
116
|
value_for_configuration = configuration
|
117
|
-
if value_for_configuration.respond_to?(:lazy?) && value_for_configuration.lazy?
|
118
|
-
self.configuration = value_for_configuration.evaluate
|
119
|
-
end
|
117
|
+
self.configuration = value_for_configuration.evaluate if value_for_configuration.respond_to?(:lazy?) && value_for_configuration.lazy?
|
120
118
|
response = instance_eval(&block)
|
121
119
|
self.configuration = value_for_configuration
|
122
120
|
response
|
@@ -179,7 +177,8 @@ module Grape
|
|
179
177
|
# X-Cascade. Default :cascade is true.
|
180
178
|
def cascade?
|
181
179
|
return self.class.namespace_inheritable(:cascade) if self.class.inheritable_setting.namespace_inheritable.key?(:cascade)
|
182
|
-
return self.class.namespace_inheritable(:version_options)[:cascade] if self.class.namespace_inheritable(:version_options)
|
180
|
+
return self.class.namespace_inheritable(:version_options)[:cascade] if self.class.namespace_inheritable(:version_options)&.key?(:cascade)
|
181
|
+
|
183
182
|
true
|
184
183
|
end
|
185
184
|
|
@@ -200,17 +199,15 @@ module Grape
|
|
200
199
|
without_root_prefix do
|
201
200
|
without_versioning do
|
202
201
|
versioned_route_configs.each do |config|
|
202
|
+
next if config[:options][:matching_wildchar]
|
203
|
+
|
203
204
|
allowed_methods = config[:methods].dup
|
204
205
|
|
205
|
-
|
206
|
-
allowed_methods |= [Grape::Http::Headers::HEAD] if allowed_methods.include?(Grape::Http::Headers::GET)
|
207
|
-
end
|
206
|
+
allowed_methods |= [Grape::Http::Headers::HEAD] if !self.class.namespace_inheritable(:do_not_route_head) && allowed_methods.include?(Grape::Http::Headers::GET)
|
208
207
|
|
209
208
|
allow_header = (self.class.namespace_inheritable(:do_not_route_options) ? allowed_methods : [Grape::Http::Headers::OPTIONS] | allowed_methods)
|
210
209
|
|
211
|
-
unless self.class.namespace_inheritable(:do_not_route_options) || allowed_methods.include?(Grape::Http::Headers::OPTIONS)
|
212
|
-
config[:endpoint].options[:options_route_enabled] = true
|
213
|
-
end
|
210
|
+
config[:endpoint].options[:options_route_enabled] = true unless self.class.namespace_inheritable(:do_not_route_options) || allowed_methods.include?(Grape::Http::Headers::OPTIONS)
|
214
211
|
|
215
212
|
attributes = config.merge(allowed_methods: allowed_methods, allow_header: allow_header)
|
216
213
|
generate_not_allowed_method(config[:pattern], **attributes)
|
@@ -228,7 +225,7 @@ module Grape
|
|
228
225
|
last_route = routes.last # Most of the configuration is taken from the last endpoint
|
229
226
|
matching_wildchar = routes.any? { |route| route.request_method == '*' }
|
230
227
|
{
|
231
|
-
options: {},
|
228
|
+
options: { matching_wildchar: matching_wildchar },
|
232
229
|
pattern: last_route.pattern,
|
233
230
|
requirements: last_route.requirements,
|
234
231
|
path: last_route.origin,
|
@@ -248,7 +245,6 @@ module Grape
|
|
248
245
|
Grape::Http::Headers::SUPPORTED_METHODS_WITHOUT_OPTIONS
|
249
246
|
end
|
250
247
|
not_allowed_methods = supported_methods - allowed_methods
|
251
|
-
return if not_allowed_methods.empty?
|
252
248
|
@router.associate_routes(pattern, not_allowed_methods: not_allowed_methods, **attributes)
|
253
249
|
end
|
254
250
|
|
data/lib/grape/api.rb
CHANGED
@@ -10,6 +10,18 @@ module Grape
|
|
10
10
|
# Class methods that we want to call on the API rather than on the API object
|
11
11
|
NON_OVERRIDABLE = (Class.new.methods + %i[call call! configuration compile! inherited]).freeze
|
12
12
|
|
13
|
+
class Boolean
|
14
|
+
def self.build(val)
|
15
|
+
return nil if val != true && val != false
|
16
|
+
|
17
|
+
new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Instance
|
22
|
+
Boolean = Grape::API::Boolean
|
23
|
+
end
|
24
|
+
|
13
25
|
class << self
|
14
26
|
attr_accessor :base_instance, :instances
|
15
27
|
|
@@ -20,10 +32,11 @@ module Grape
|
|
20
32
|
|
21
33
|
# When inherited, will create a list of all instances (times the API was mounted)
|
22
34
|
# It will listen to the setup required to mount that endpoint, and replicate it on any new instance
|
23
|
-
def inherited(api
|
24
|
-
|
35
|
+
def inherited(api)
|
36
|
+
super
|
37
|
+
|
38
|
+
api.initial_setup(Grape::API == self ? Grape::API::Instance : @base_instance)
|
25
39
|
api.override_all_methods!
|
26
|
-
make_inheritable(api)
|
27
40
|
end
|
28
41
|
|
29
42
|
# Initialize the instance variables on the remountable class, and the base_instance
|
@@ -68,15 +81,6 @@ module Grape
|
|
68
81
|
instance_for_rack.call(*args, &block)
|
69
82
|
end
|
70
83
|
|
71
|
-
# Allows an API to itself be inheritable:
|
72
|
-
def make_inheritable(api)
|
73
|
-
# When a child API inherits from a parent API.
|
74
|
-
def api.inherited(child_api)
|
75
|
-
# The instances of the child API inherit from the instances of the parent API
|
76
|
-
Grape::API.inherited(child_api, base_instance)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
84
|
# Alleviates problems with autoloading by tring to search for the constant
|
81
85
|
def const_missing(*args)
|
82
86
|
if base_instance.const_defined?(*args)
|
@@ -151,6 +155,7 @@ module Grape
|
|
151
155
|
|
152
156
|
def replay_step_on(instance, setup_step)
|
153
157
|
return if skip_immediate_run?(instance, setup_step[:args])
|
158
|
+
|
154
159
|
args = evaluate_arguments(instance.configuration, *setup_step[:args])
|
155
160
|
response = instance.send(setup_step[:method], *args, &setup_step[:block])
|
156
161
|
if skip_immediate_run?(instance, [response])
|
data/lib/grape/cookies.rb
CHANGED
@@ -33,9 +33,11 @@ module Grape
|
|
33
33
|
@cookies.each(&block)
|
34
34
|
end
|
35
35
|
|
36
|
+
# rubocop:disable Layout/SpaceBeforeBrackets
|
36
37
|
def delete(name, **opts)
|
37
38
|
options = opts.merge(value: 'deleted', expires: Time.at(0))
|
38
39
|
self.[]=(name, options)
|
39
40
|
end
|
41
|
+
# rubocop:enable Layout/SpaceBeforeBrackets
|
40
42
|
end
|
41
43
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry-types'
|
4
|
+
|
5
|
+
module Grape
|
6
|
+
module DryTypes
|
7
|
+
# Call +Dry.Types()+ to add all registered types to +DryTypes+ which is
|
8
|
+
# a container in this case. Check documentation for more information
|
9
|
+
# https://dry-rb.org/gems/dry-types/1.2/getting-started/
|
10
|
+
include Dry.Types()
|
11
|
+
end
|
12
|
+
end
|
data/lib/grape/dsl/api.rb
CHANGED
data/lib/grape/dsl/callbacks.rb
CHANGED
data/lib/grape/dsl/desc.rb
CHANGED
@@ -50,7 +50,7 @@ module Grape
|
|
50
50
|
# end
|
51
51
|
#
|
52
52
|
def desc(description, options = {}, &config_block)
|
53
|
-
if
|
53
|
+
if config_block
|
54
54
|
endpoint_configuration = if defined?(configuration)
|
55
55
|
# When the instance is mounted - the configuration is executed on mount time
|
56
56
|
if configuration.respond_to?(:evaluate)
|
@@ -68,9 +68,7 @@ module Grape
|
|
68
68
|
end
|
69
69
|
|
70
70
|
config_class.configure(&config_block)
|
71
|
-
unless options.empty?
|
72
|
-
warn '[DEPRECATION] Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.'
|
73
|
-
end
|
71
|
+
warn '[DEPRECATION] Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.' unless options.empty?
|
74
72
|
options = config_class.settings
|
75
73
|
else
|
76
74
|
options = options.merge(description: description)
|
@@ -80,21 +78,6 @@ module Grape
|
|
80
78
|
route_setting :description, options
|
81
79
|
end
|
82
80
|
|
83
|
-
def description_field(field, value = nil)
|
84
|
-
description = route_setting(:description)
|
85
|
-
if value
|
86
|
-
description ||= route_setting(:description, {})
|
87
|
-
description[field] = value
|
88
|
-
elsif description
|
89
|
-
description[field]
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def unset_description_field(field)
|
94
|
-
description = route_setting(:description)
|
95
|
-
description.delete(field) if description
|
96
|
-
end
|
97
|
-
|
98
81
|
# Returns an object which configures itself via an instance-context DSL.
|
99
82
|
def desc_container(endpoint_configuration)
|
100
83
|
Module.new do
|
@@ -115,7 +98,8 @@ module Grape
|
|
115
98
|
:produces,
|
116
99
|
:consumes,
|
117
100
|
:security,
|
118
|
-
:tags
|
101
|
+
:tags,
|
102
|
+
:default
|
119
103
|
)
|
120
104
|
config_context.define_singleton_method(:configuration) do
|
121
105
|
endpoint_configuration
|
data/lib/grape/dsl/headers.rb
CHANGED
@@ -3,8 +3,11 @@
|
|
3
3
|
module Grape
|
4
4
|
module DSL
|
5
5
|
module Headers
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# This method has four responsibilities:
|
7
|
+
# 1. Set a specifc header value by key
|
8
|
+
# 2. Retrieve a specifc header value by key
|
9
|
+
# 3. Retrieve all headers that have been set
|
10
|
+
# 4. Delete a specifc header key-value pair
|
8
11
|
def header(key = nil, val = nil)
|
9
12
|
if key
|
10
13
|
val ? header[key.to_s] = val : header.delete(key.to_s)
|
data/lib/grape/dsl/helpers.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
module Helpers
|
@@ -36,8 +34,8 @@ module Grape
|
|
36
34
|
#
|
37
35
|
def helpers(*new_modules, &block)
|
38
36
|
include_new_modules(new_modules) if new_modules.any?
|
39
|
-
include_block(block) if
|
40
|
-
include_all_in_scope if !
|
37
|
+
include_block(block) if block
|
38
|
+
include_all_in_scope if !block && new_modules.empty?
|
41
39
|
end
|
42
40
|
|
43
41
|
protected
|
@@ -67,12 +65,13 @@ module Grape
|
|
67
65
|
|
68
66
|
def define_boolean_in_mod(mod)
|
69
67
|
return if defined? mod::Boolean
|
70
|
-
|
68
|
+
|
69
|
+
mod.const_set(:Boolean, Grape::API::Boolean)
|
71
70
|
end
|
72
71
|
|
73
|
-
def inject_api_helpers_to_mod(mod, &
|
72
|
+
def inject_api_helpers_to_mod(mod, &block)
|
74
73
|
mod.extend(BaseHelper) unless mod.is_a?(BaseHelper)
|
75
|
-
yield if
|
74
|
+
yield if block
|
76
75
|
mod.api_changed(self)
|
77
76
|
end
|
78
77
|
end
|
@@ -96,6 +95,7 @@ module Grape
|
|
96
95
|
|
97
96
|
def process_named_params
|
98
97
|
return unless instance_variable_defined?(:@named_params) && @named_params && @named_params.any?
|
98
|
+
|
99
99
|
api.namespace_stackable(:named_params, @named_params)
|
100
100
|
end
|
101
101
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
3
|
require 'grape/dsl/headers'
|
5
4
|
|
6
5
|
module Grape
|
@@ -29,7 +28,7 @@ module Grape
|
|
29
28
|
# has completed
|
30
29
|
module PostBeforeFilter
|
31
30
|
def declared(passed_params, options = {}, declared_params = nil, params_nested_path = [])
|
32
|
-
options = options.reverse_merge(include_missing: true, include_parent_namespaces: true)
|
31
|
+
options = options.reverse_merge(include_missing: true, include_parent_namespaces: true, evaluate_given: false)
|
33
32
|
declared_params ||= optioned_declared_params(**options)
|
34
33
|
|
35
34
|
if passed_params.is_a?(Array)
|
@@ -48,37 +47,47 @@ module Grape
|
|
48
47
|
end
|
49
48
|
|
50
49
|
def declared_hash(passed_params, options, declared_params, params_nested_path)
|
51
|
-
declared_params.each_with_object(passed_params.class.new) do |
|
52
|
-
if
|
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
|
56
|
-
next unless options[:include_missing] || passed_params.key?(declared_parent_param)
|
57
|
-
|
58
|
-
passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
|
59
|
-
memo_key = optioned_param_key(declared_parent_param, options)
|
60
|
-
|
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)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
else
|
66
|
-
# If it is not a Hash then it does not have children.
|
67
|
-
# Find its value or set it to nil.
|
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))
|
50
|
+
declared_params.each_with_object(passed_params.class.new) do |declared_param_attr, memo|
|
51
|
+
next if options[:evaluate_given] && !declared_param_attr.scope.attr_meets_dependency?(passed_params)
|
72
52
|
|
73
|
-
|
74
|
-
|
53
|
+
declared_hash_attr(passed_params, options, declared_param_attr.key, params_nested_path, memo)
|
54
|
+
end
|
55
|
+
end
|
75
56
|
|
57
|
+
def declared_hash_attr(passed_params, options, declared_param, params_nested_path, memo)
|
58
|
+
renamed_params = route_setting(:renamed_params) || {}
|
59
|
+
if declared_param.is_a?(Hash)
|
60
|
+
declared_param.each_pair do |declared_parent_param, declared_children_params|
|
76
61
|
params_nested_path_dup = params_nested_path.dup
|
77
|
-
params_nested_path_dup <<
|
78
|
-
|
79
|
-
|
62
|
+
params_nested_path_dup << declared_parent_param.to_s
|
63
|
+
next unless options[:include_missing] || passed_params.key?(declared_parent_param)
|
64
|
+
|
65
|
+
rename_path = params_nested_path + [declared_parent_param.to_s]
|
66
|
+
renamed_param_name = renamed_params[rename_path]
|
67
|
+
|
68
|
+
memo_key = optioned_param_key(renamed_param_name || declared_parent_param, options)
|
69
|
+
passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
|
70
|
+
|
71
|
+
memo[memo_key] = handle_passed_param(params_nested_path_dup, passed_children_params.any?) do
|
72
|
+
declared(passed_children_params, options, declared_children_params, params_nested_path_dup)
|
80
73
|
end
|
81
74
|
end
|
75
|
+
else
|
76
|
+
# If it is not a Hash then it does not have children.
|
77
|
+
# Find its value or set it to nil.
|
78
|
+
return unless options[:include_missing] || passed_params.key?(declared_param)
|
79
|
+
|
80
|
+
rename_path = params_nested_path + [declared_param.to_s]
|
81
|
+
renamed_param_name = renamed_params[rename_path]
|
82
|
+
|
83
|
+
memo_key = optioned_param_key(renamed_param_name || declared_param, options)
|
84
|
+
passed_param = passed_params[declared_param]
|
85
|
+
|
86
|
+
params_nested_path_dup = params_nested_path.dup
|
87
|
+
params_nested_path_dup << declared_param.to_s
|
88
|
+
memo[memo_key] = passed_param || handle_passed_param(params_nested_path_dup) do
|
89
|
+
passed_param
|
90
|
+
end
|
82
91
|
end
|
83
92
|
end
|
84
93
|
|
@@ -86,7 +95,7 @@ module Grape
|
|
86
95
|
return yield if has_passed_children
|
87
96
|
|
88
97
|
key = params_nested_path[0]
|
89
|
-
key +=
|
98
|
+
key += "[#{params_nested_path[1..].join('][')}]" if params_nested_path.size > 1
|
90
99
|
|
91
100
|
route_options_params = options[:route_options][:params] || {}
|
92
101
|
type = route_options_params.dig(key, :type)
|
@@ -94,7 +103,7 @@ module Grape
|
|
94
103
|
|
95
104
|
if type == 'Hash' && !has_children
|
96
105
|
{}
|
97
|
-
elsif type == 'Array' || type&.start_with?('[') && !type&.include?(',')
|
106
|
+
elsif type == 'Array' || (type&.start_with?('[') && !type&.include?(','))
|
98
107
|
[]
|
99
108
|
elsif type == 'Set' || type&.start_with?('#<Set')
|
100
109
|
Set.new
|
@@ -117,6 +126,7 @@ module Grape
|
|
117
126
|
end
|
118
127
|
|
119
128
|
raise ArgumentError, 'Tried to filter for declared parameters but none exist.' unless declared_params
|
129
|
+
|
120
130
|
declared_params
|
121
131
|
end
|
122
132
|
end
|
@@ -187,11 +197,13 @@ module Grape
|
|
187
197
|
case status
|
188
198
|
when Symbol
|
189
199
|
raise ArgumentError, "Status code :#{status} is invalid." unless Rack::Utils::SYMBOL_TO_STATUS_CODE.key?(status)
|
200
|
+
|
190
201
|
@status = Rack::Utils.status_code(status)
|
191
202
|
when Integer
|
192
203
|
@status = status
|
193
204
|
when nil
|
194
205
|
return @status if instance_variable_defined?(:@status) && @status
|
206
|
+
|
195
207
|
case request.request_method.to_s.upcase
|
196
208
|
when Grape::Http::Headers::POST
|
197
209
|
201
|
@@ -369,6 +381,7 @@ module Grape
|
|
369
381
|
representation = (body || {}).merge(key => representation)
|
370
382
|
elsif entity_class.present? && body
|
371
383
|
raise ArgumentError, "Representation of type #{representation.class} cannot be merged." unless representation.respond_to?(:merge)
|
384
|
+
|
372
385
|
representation = body.merge(representation)
|
373
386
|
end
|
374
387
|
|
data/lib/grape/dsl/middleware.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
module Middleware
|
@@ -18,28 +16,28 @@ module Grape
|
|
18
16
|
# to inject.
|
19
17
|
def use(middleware_class, *args, &block)
|
20
18
|
arr = [:use, middleware_class, *args]
|
21
|
-
arr << block if
|
19
|
+
arr << block if block
|
22
20
|
|
23
21
|
namespace_stackable(:middleware, arr)
|
24
22
|
end
|
25
23
|
|
26
24
|
def insert(*args, &block)
|
27
25
|
arr = [:insert, *args]
|
28
|
-
arr << block if
|
26
|
+
arr << block if block
|
29
27
|
|
30
28
|
namespace_stackable(:middleware, arr)
|
31
29
|
end
|
32
30
|
|
33
31
|
def insert_before(*args, &block)
|
34
32
|
arr = [:insert_before, *args]
|
35
|
-
arr << block if
|
33
|
+
arr << block if block
|
36
34
|
|
37
35
|
namespace_stackable(:middleware, arr)
|
38
36
|
end
|
39
37
|
|
40
38
|
def insert_after(*args, &block)
|
41
39
|
arr = [:insert_after, *args]
|
42
|
-
arr << block if
|
40
|
+
arr << block if block
|
43
41
|
|
44
42
|
namespace_stackable(:middleware, arr)
|
45
43
|
end
|
data/lib/grape/dsl/parameters.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
# Defines DSL methods, meant to be applied to a ParamsScope, which define
|
@@ -64,7 +62,12 @@ module Grape
|
|
64
62
|
params_block = named_params.fetch(name) do
|
65
63
|
raise "Params :#{name} not found!"
|
66
64
|
end
|
67
|
-
|
65
|
+
|
66
|
+
if options.empty?
|
67
|
+
instance_exec(options, ¶ms_block)
|
68
|
+
else
|
69
|
+
instance_exec(**options, ¶ms_block)
|
70
|
+
end
|
68
71
|
end
|
69
72
|
end
|
70
73
|
alias use_scope use
|
@@ -133,7 +136,7 @@ module Grape
|
|
133
136
|
require_required_and_optional_fields(attrs.first, opts)
|
134
137
|
else
|
135
138
|
validate_attributes(attrs, opts, &block)
|
136
|
-
|
139
|
+
block ? new_scope(orig_attrs, &block) : push_declared_params(attrs, **opts.slice(:as))
|
137
140
|
end
|
138
141
|
end
|
139
142
|
|
@@ -149,9 +152,9 @@ module Grape
|
|
149
152
|
opts = @group.merge(opts) if instance_variable_defined?(:@group) && @group
|
150
153
|
|
151
154
|
# check type for optional parameter group
|
152
|
-
if attrs &&
|
153
|
-
raise Grape::Exceptions::
|
154
|
-
raise Grape::Exceptions::
|
155
|
+
if attrs && block
|
156
|
+
raise Grape::Exceptions::MissingGroupType if type.nil?
|
157
|
+
raise Grape::Exceptions::UnsupportedGroupType unless Grape::Validations::Types.group?(type)
|
155
158
|
end
|
156
159
|
|
157
160
|
if opts[:using]
|
@@ -159,7 +162,7 @@ module Grape
|
|
159
162
|
else
|
160
163
|
validate_attributes(attrs, opts, &block)
|
161
164
|
|
162
|
-
|
165
|
+
block ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, **opts.slice(:as))
|
163
166
|
end
|
164
167
|
end
|
165
168
|
|
@@ -219,8 +222,8 @@ module Grape
|
|
219
222
|
else
|
220
223
|
# @declared_params also includes hashes of options and such, but those
|
221
224
|
# won't be flattened out.
|
222
|
-
@declared_params.flatten.any? do |
|
223
|
-
first_hash_key_or_param(
|
225
|
+
@declared_params.flatten.any? do |declared_param_attr|
|
226
|
+
first_hash_key_or_param(declared_param_attr.key) == param
|
224
227
|
end
|
225
228
|
end
|
226
229
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
module RequestResponse
|
@@ -26,6 +24,7 @@ module Grape
|
|
26
24
|
# define a single mime type
|
27
25
|
mime_type = content_types[new_format.to_sym]
|
28
26
|
raise Grape::Exceptions::MissingMimeType.new(new_format) unless mime_type
|
27
|
+
|
29
28
|
namespace_stackable(:content_types, new_format.to_sym => mime_type)
|
30
29
|
else
|
31
30
|
namespace_inheritable(:format)
|
@@ -102,14 +101,13 @@ module Grape
|
|
102
101
|
def rescue_from(*args, &block)
|
103
102
|
if args.last.is_a?(Proc)
|
104
103
|
handler = args.pop
|
105
|
-
elsif
|
104
|
+
elsif block
|
106
105
|
handler = block
|
107
106
|
end
|
108
107
|
|
109
108
|
options = args.extract_options!
|
110
|
-
if
|
111
|
-
|
112
|
-
end
|
109
|
+
raise ArgumentError, 'both :with option and block cannot be passed' if block && options.key?(:with)
|
110
|
+
|
113
111
|
handler ||= extract_with(options)
|
114
112
|
|
115
113
|
if args.include?(:all)
|
@@ -127,7 +125,7 @@ module Grape
|
|
127
125
|
:base_only_rescue_handlers
|
128
126
|
end
|
129
127
|
|
130
|
-
namespace_reverse_stackable
|
128
|
+
namespace_reverse_stackable(handler_type, args.to_h { |arg| [arg, handler] })
|
131
129
|
end
|
132
130
|
|
133
131
|
namespace_stackable(:rescue_options, options)
|
@@ -154,7 +152,8 @@ module Grape
|
|
154
152
|
# @param model_class [Class] The model class that will be represented.
|
155
153
|
# @option options [Class] :with The entity class that will represent the model.
|
156
154
|
def represent(model_class, options)
|
157
|
-
raise Grape::Exceptions::InvalidWithOptionForRepresent.new unless options[:with]
|
155
|
+
raise Grape::Exceptions::InvalidWithOptionForRepresent.new unless options[:with].is_a?(Class)
|
156
|
+
|
158
157
|
namespace_stackable(:representations, model_class => options[:with])
|
159
158
|
end
|
160
159
|
|
@@ -162,9 +161,11 @@ module Grape
|
|
162
161
|
|
163
162
|
def extract_with(options)
|
164
163
|
return unless options.key?(:with)
|
164
|
+
|
165
165
|
with_option = options.delete(:with)
|
166
166
|
return with_option if with_option.instance_of?(Proc)
|
167
167
|
return with_option.to_sym if with_option.instance_of?(Symbol) || with_option.instance_of?(String)
|
168
|
+
|
168
169
|
raise ArgumentError, "with: #{with_option.class}, expected Symbol, String or Proc"
|
169
170
|
end
|
170
171
|
end
|
data/lib/grape/dsl/routing.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module Grape
|
6
4
|
module DSL
|
7
5
|
module Routing
|
@@ -38,7 +36,7 @@ module Grape
|
|
38
36
|
|
39
37
|
@versions = versions | requested_versions
|
40
38
|
|
41
|
-
if
|
39
|
+
if block
|
42
40
|
within_namespace do
|
43
41
|
namespace_inheritable(:version, requested_versions)
|
44
42
|
namespace_inheritable(:version_options, options)
|
@@ -79,6 +77,10 @@ module Grape
|
|
79
77
|
namespace_inheritable(:do_not_route_options, true)
|
80
78
|
end
|
81
79
|
|
80
|
+
def do_not_document!
|
81
|
+
namespace_inheritable(:do_not_document, true)
|
82
|
+
end
|
83
|
+
|
82
84
|
def mount(mounts, *opts)
|
83
85
|
mounts = { mounts => '/' } unless mounts.respond_to?(:each_pair)
|
84
86
|
mounts.each_pair do |app, path|
|
@@ -166,7 +168,7 @@ module Grape
|
|
166
168
|
def namespace(space = nil, options = {}, &block)
|
167
169
|
@namespace_description = nil unless instance_variable_defined?(:@namespace_description) && @namespace_description
|
168
170
|
|
169
|
-
if space ||
|
171
|
+
if space || block
|
170
172
|
within_namespace do
|
171
173
|
previous_namespace_description = @namespace_description
|
172
174
|
@namespace_description = (@namespace_description || {}).deep_merge(namespace_setting(:description) || {})
|