grape 1.5.3 → 1.7.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 +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) || {})
|