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.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +92 -0
  3. data/CONTRIBUTING.md +32 -1
  4. data/README.md +176 -25
  5. data/UPGRADING.md +61 -4
  6. data/grape.gemspec +6 -6
  7. data/lib/grape/api/instance.rb +14 -18
  8. data/lib/grape/api.rb +17 -12
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dry_types.rb +12 -0
  11. data/lib/grape/dsl/api.rb +0 -2
  12. data/lib/grape/dsl/callbacks.rb +0 -2
  13. data/lib/grape/dsl/configuration.rb +0 -2
  14. data/lib/grape/dsl/desc.rb +4 -20
  15. data/lib/grape/dsl/headers.rb +5 -2
  16. data/lib/grape/dsl/helpers.rb +7 -7
  17. data/lib/grape/dsl/inside_route.rb +43 -30
  18. data/lib/grape/dsl/middleware.rb +4 -6
  19. data/lib/grape/dsl/parameters.rb +13 -10
  20. data/lib/grape/dsl/request_response.rb +9 -8
  21. data/lib/grape/dsl/routing.rb +6 -4
  22. data/lib/grape/dsl/settings.rb +5 -7
  23. data/lib/grape/dsl/validations.rb +0 -15
  24. data/lib/grape/endpoint.rb +22 -37
  25. data/lib/grape/error_formatter/json.rb +9 -7
  26. data/lib/grape/error_formatter/xml.rb +2 -6
  27. data/lib/grape/exceptions/base.rb +3 -2
  28. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  29. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  30. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  31. data/lib/grape/exceptions/validation.rb +1 -6
  32. data/lib/grape/formatter/json.rb +1 -0
  33. data/lib/grape/formatter/serializable_hash.rb +2 -1
  34. data/lib/grape/formatter/xml.rb +1 -0
  35. data/lib/grape/locale/en.yml +9 -8
  36. data/lib/grape/middleware/auth/dsl.rb +7 -2
  37. data/lib/grape/middleware/base.rb +3 -1
  38. data/lib/grape/middleware/error.rb +2 -2
  39. data/lib/grape/middleware/formatter.rb +4 -4
  40. data/lib/grape/middleware/stack.rb +3 -3
  41. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  42. data/lib/grape/middleware/versioner/header.rb +6 -4
  43. data/lib/grape/middleware/versioner/param.rb +1 -0
  44. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  45. data/lib/grape/middleware/versioner/path.rb +2 -0
  46. data/lib/grape/path.rb +1 -0
  47. data/lib/grape/request.rb +4 -1
  48. data/lib/grape/router/attribute_translator.rb +1 -1
  49. data/lib/grape/router/pattern.rb +1 -1
  50. data/lib/grape/router/route.rb +2 -2
  51. data/lib/grape/router.rb +6 -0
  52. data/lib/grape/types/invalid_value.rb +8 -0
  53. data/lib/grape/util/cache.rb +1 -1
  54. data/lib/grape/util/inheritable_setting.rb +1 -3
  55. data/lib/grape/util/json.rb +2 -0
  56. data/lib/grape/util/lazy_value.rb +3 -2
  57. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  58. data/lib/grape/validations/attributes_doc.rb +58 -0
  59. data/lib/grape/validations/params_scope.rb +138 -79
  60. data/lib/grape/validations/types/array_coercer.rb +0 -2
  61. data/lib/grape/validations/types/custom_type_coercer.rb +1 -0
  62. data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
  63. data/lib/grape/validations/types/invalid_value.rb +0 -7
  64. data/lib/grape/validations/types/json.rb +2 -1
  65. data/lib/grape/validations/types/primitive_coercer.rb +16 -8
  66. data/lib/grape/validations/types/set_coercer.rb +0 -2
  67. data/lib/grape/validations/types.rb +98 -30
  68. data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
  69. data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
  70. data/lib/grape/validations/validators/as_validator.rb +14 -0
  71. data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
  72. data/lib/grape/validations/validators/base.rb +82 -70
  73. data/lib/grape/validations/validators/coerce_validator.rb +75 -0
  74. data/lib/grape/validations/validators/default_validator.rb +51 -0
  75. data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
  76. data/lib/grape/validations/validators/except_values_validator.rb +24 -0
  77. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  78. data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
  79. data/lib/grape/validations/validators/presence_validator.rb +15 -0
  80. data/lib/grape/validations/validators/regexp_validator.rb +16 -0
  81. data/lib/grape/validations/validators/same_as_validator.rb +29 -0
  82. data/lib/grape/validations/validators/values_validator.rb +88 -0
  83. data/lib/grape/validations.rb +16 -6
  84. data/lib/grape/version.rb +1 -1
  85. data/lib/grape.rb +77 -29
  86. data/spec/grape/api/custom_validations_spec.rb +116 -45
  87. data/spec/grape/api/deeply_included_options_spec.rb +3 -5
  88. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
  89. data/spec/grape/api/documentation_spec.rb +59 -0
  90. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  91. data/spec/grape/api/instance_spec.rb +0 -1
  92. data/spec/grape/api/invalid_format_spec.rb +2 -2
  93. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  94. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  95. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  96. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  97. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  98. data/spec/grape/api/recognize_path_spec.rb +1 -3
  99. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  100. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  101. data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
  102. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
  103. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  104. data/spec/grape/api_remount_spec.rb +16 -16
  105. data/spec/grape/api_spec.rb +462 -251
  106. data/spec/grape/config_spec.rb +0 -2
  107. data/spec/grape/dsl/callbacks_spec.rb +2 -3
  108. data/spec/grape/dsl/desc_spec.rb +2 -2
  109. data/spec/grape/dsl/headers_spec.rb +39 -11
  110. data/spec/grape/dsl/helpers_spec.rb +3 -4
  111. data/spec/grape/dsl/inside_route_spec.rb +16 -16
  112. data/spec/grape/dsl/logger_spec.rb +15 -19
  113. data/spec/grape/dsl/middleware_spec.rb +2 -3
  114. data/spec/grape/dsl/parameters_spec.rb +2 -2
  115. data/spec/grape/dsl/request_response_spec.rb +7 -8
  116. data/spec/grape/dsl/routing_spec.rb +11 -10
  117. data/spec/grape/dsl/settings_spec.rb +0 -2
  118. data/spec/grape/dsl/validations_spec.rb +0 -17
  119. data/spec/grape/endpoint/declared_spec.rb +261 -16
  120. data/spec/grape/endpoint_spec.rb +88 -59
  121. data/spec/grape/entity_spec.rb +22 -23
  122. data/spec/grape/exceptions/base_spec.rb +16 -2
  123. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
  124. data/spec/grape/exceptions/invalid_accept_header_spec.rb +64 -24
  125. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
  126. data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
  127. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
  128. data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
  129. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
  130. data/spec/grape/exceptions/missing_option_spec.rb +1 -3
  131. data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
  132. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
  133. data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
  134. data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
  135. data/spec/grape/exceptions/validation_spec.rb +5 -5
  136. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
  137. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
  138. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
  139. data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
  140. data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
  141. data/spec/grape/integration/rack_spec.rb +6 -7
  142. data/spec/grape/loading_spec.rb +8 -10
  143. data/spec/grape/middleware/auth/base_spec.rb +0 -1
  144. data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
  145. data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
  146. data/spec/grape/middleware/base_spec.rb +28 -19
  147. data/spec/grape/middleware/error_spec.rb +8 -3
  148. data/spec/grape/middleware/exception_spec.rb +111 -163
  149. data/spec/grape/middleware/formatter_spec.rb +33 -14
  150. data/spec/grape/middleware/globals_spec.rb +7 -6
  151. data/spec/grape/middleware/stack_spec.rb +14 -14
  152. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
  153. data/spec/grape/middleware/versioner/header_spec.rb +30 -15
  154. data/spec/grape/middleware/versioner/param_spec.rb +7 -3
  155. data/spec/grape/middleware/versioner/path_spec.rb +5 -3
  156. data/spec/grape/middleware/versioner_spec.rb +1 -3
  157. data/spec/grape/named_api_spec.rb +0 -2
  158. data/spec/grape/parser_spec.rb +4 -2
  159. data/spec/grape/path_spec.rb +52 -54
  160. data/spec/grape/presenters/presenter_spec.rb +7 -8
  161. data/spec/grape/request_spec.rb +6 -6
  162. data/spec/grape/util/inheritable_setting_spec.rb +7 -8
  163. data/spec/grape/util/inheritable_values_spec.rb +3 -3
  164. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
  165. data/spec/grape/util/stackable_values_spec.rb +7 -6
  166. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
  167. data/spec/grape/validations/attributes_doc_spec.rb +153 -0
  168. data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
  169. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
  170. data/spec/grape/validations/params_scope_spec.rb +361 -96
  171. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
  172. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  173. data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
  174. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  175. data/spec/grape/validations/types_spec.rb +36 -10
  176. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
  177. data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
  178. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
  179. data/spec/grape/validations/validators/coerce_spec.rb +23 -24
  180. data/spec/grape/validations/validators/default_spec.rb +72 -80
  181. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
  182. data/spec/grape/validations/validators/except_values_spec.rb +3 -5
  183. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
  184. data/spec/grape/validations/validators/presence_spec.rb +16 -3
  185. data/spec/grape/validations/validators/regexp_spec.rb +25 -33
  186. data/spec/grape/validations/validators/same_as_spec.rb +14 -22
  187. data/spec/grape/validations/validators/values_spec.rb +201 -179
  188. data/spec/grape/validations_spec.rb +171 -79
  189. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  190. data/spec/integration/multi_json/json_spec.rb +1 -3
  191. data/spec/integration/multi_xml/xml_spec.rb +1 -3
  192. data/spec/shared/versioning_examples.rb +12 -9
  193. data/spec/spec_helper.rb +21 -6
  194. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  195. metadata +41 -29
  196. data/lib/grape/validations/validators/all_or_none.rb +0 -15
  197. data/lib/grape/validations/validators/allow_blank.rb +0 -18
  198. data/lib/grape/validations/validators/as.rb +0 -16
  199. data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
  200. data/lib/grape/validations/validators/coerce.rb +0 -91
  201. data/lib/grape/validations/validators/default.rb +0 -48
  202. data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
  203. data/lib/grape/validations/validators/except_values.rb +0 -22
  204. data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
  205. data/lib/grape/validations/validators/presence.rb +0 -12
  206. data/lib/grape/validations/validators/regexp.rb +0 -13
  207. data/lib/grape/validations/validators/same_as.rb +0 -26
  208. data/lib/grape/validations/validators/values.rb +0 -83
  209. data/spec/grape/dsl/configuration_spec.rb +0 -16
  210. data/spec/grape/validations/attributes_iterator_spec.rb +0 -6
  211. data/spec/support/eager_load.rb +0 -19
@@ -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 && block_given?
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
- (base && base.to_s) || super
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.reject!(&:nil?)
104
+ blocks.compact!
105
105
  if blocks.any?
106
- evaluate_as_instance_with_configuration(block) if block_given?
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) && self.class.namespace_inheritable(:version_options).key?(:cascade)
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
- unless self.class.namespace_inheritable(:do_not_route_head)
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, base_instance_parent = Grape::API::Instance)
24
- api.initial_setup(base_instance_parent)
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
@@ -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 API
@@ -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
  # Blocks can be executed before or after every API call, using `before`, `after`,
@@ -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 Configuration
@@ -50,7 +50,7 @@ module Grape
50
50
  # end
51
51
  #
52
52
  def desc(description, options = {}, &config_block)
53
- if block_given?
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
@@ -3,8 +3,11 @@
3
3
  module Grape
4
4
  module DSL
5
5
  module Headers
6
- # Set an individual header or retrieve
7
- # all headers that have been set.
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)
@@ -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 block_given?
40
- include_all_in_scope if !block_given? && new_modules.empty?
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
- mod.const_set('Boolean', Grape::API::Boolean)
68
+
69
+ mod.const_set(:Boolean, Grape::API::Boolean)
71
70
  end
72
71
 
73
- def inject_api_helpers_to_mod(mod, &_block)
72
+ def inject_api_helpers_to_mod(mod, &block)
74
73
  mod.extend(BaseHelper) unless mod.is_a?(BaseHelper)
75
- yield if block_given?
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 |declared_param, memo|
52
- if declared_param.is_a?(Hash)
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
- memo_key = optioned_param_key(param_renaming || declared_param, options)
74
- passed_param = passed_params[param_renaming || declared_param]
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 << declared_param.to_s
78
- memo[memo_key] = passed_param || handle_passed_param(params_nested_path_dup) do
79
- passed_param
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 += '[' + params_nested_path[1..-1].join('][') + ']' if params_nested_path.size > 1
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
 
@@ -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 block_given?
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 block_given?
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 block_given?
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 block_given?
40
+ arr << block if block
43
41
 
44
42
  namespace_stackable(:middleware, arr)
45
43
  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
  # 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
- instance_exec(options, &params_block)
65
+
66
+ if options.empty?
67
+ instance_exec(options, &params_block)
68
+ else
69
+ instance_exec(**options, &params_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
- block_given? ? new_scope(orig_attrs, &block) : push_declared_params(attrs, **opts.slice(:as))
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 && block_given?
153
- raise Grape::Exceptions::MissingGroupTypeError.new if type.nil?
154
- raise Grape::Exceptions::UnsupportedGroupTypeError.new unless Grape::Validations::Types.group?(type)
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
- block_given? ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, **opts.slice(:as))
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 |declared_param|
223
- first_hash_key_or_param(declared_param) == 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 block_given?
104
+ elsif block
106
105
  handler = block
107
106
  end
108
107
 
109
108
  options = args.extract_options!
110
- if block_given? && options.key?(:with)
111
- raise ArgumentError, 'both :with option and block cannot be passed'
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 handler_type, Hash[args.map { |arg| [arg, handler] }]
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] && options[:with].is_a?(Class)
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
@@ -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 block_given?
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 || block_given?
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) || {})