grape 1.5.2 → 1.7.0

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 (210) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +152 -21
  5. data/UPGRADING.md +86 -2
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +14 -18
  8. data/lib/grape/api.rb +18 -13
  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 +2 -19
  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 +8 -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 +21 -36
  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 +2 -2
  28. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  29. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  30. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  31. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  32. data/lib/grape/exceptions/validation.rb +1 -6
  33. data/lib/grape/formatter/json.rb +1 -0
  34. data/lib/grape/formatter/serializable_hash.rb +2 -1
  35. data/lib/grape/formatter/xml.rb +1 -0
  36. data/lib/grape/locale/en.yml +9 -8
  37. data/lib/grape/middleware/auth/dsl.rb +7 -2
  38. data/lib/grape/middleware/base.rb +3 -1
  39. data/lib/grape/middleware/error.rb +2 -2
  40. data/lib/grape/middleware/formatter.rb +4 -4
  41. data/lib/grape/middleware/stack.rb +2 -2
  42. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  43. data/lib/grape/middleware/versioner/header.rb +6 -4
  44. data/lib/grape/middleware/versioner/param.rb +1 -0
  45. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  46. data/lib/grape/middleware/versioner/path.rb +2 -0
  47. data/lib/grape/parser/json.rb +1 -1
  48. data/lib/grape/parser/xml.rb +1 -1
  49. data/lib/grape/path.rb +1 -0
  50. data/lib/grape/request.rb +5 -0
  51. data/lib/grape/router/pattern.rb +1 -1
  52. data/lib/grape/router/route.rb +2 -2
  53. data/lib/grape/router.rb +6 -0
  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 +137 -78
  60. data/lib/grape/validations/types/array_coercer.rb +0 -2
  61. data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
  62. data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
  63. data/lib/grape/validations/types/json.rb +2 -1
  64. data/lib/grape/validations/types/primitive_coercer.rb +16 -8
  65. data/lib/grape/validations/types/set_coercer.rb +0 -2
  66. data/lib/grape/validations/types.rb +98 -30
  67. data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
  68. data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
  69. data/lib/grape/validations/validators/as_validator.rb +14 -0
  70. data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
  71. data/lib/grape/validations/validators/base.rb +82 -70
  72. data/lib/grape/validations/validators/coerce_validator.rb +75 -0
  73. data/lib/grape/validations/validators/default_validator.rb +51 -0
  74. data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
  75. data/lib/grape/validations/validators/except_values_validator.rb +24 -0
  76. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  77. data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
  78. data/lib/grape/validations/validators/presence_validator.rb +15 -0
  79. data/lib/grape/validations/validators/regexp_validator.rb +16 -0
  80. data/lib/grape/validations/validators/same_as_validator.rb +29 -0
  81. data/lib/grape/validations/validators/values_validator.rb +88 -0
  82. data/lib/grape/validations.rb +16 -6
  83. data/lib/grape/version.rb +1 -1
  84. data/lib/grape.rb +70 -29
  85. data/spec/grape/api/custom_validations_spec.rb +116 -45
  86. data/spec/grape/api/deeply_included_options_spec.rb +3 -5
  87. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
  88. data/spec/grape/api/documentation_spec.rb +59 -0
  89. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  90. data/spec/grape/api/instance_spec.rb +0 -1
  91. data/spec/grape/api/invalid_format_spec.rb +2 -2
  92. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  93. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  94. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  95. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  96. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  97. data/spec/grape/api/recognize_path_spec.rb +1 -3
  98. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  99. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  100. data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
  101. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
  102. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  103. data/spec/grape/api_remount_spec.rb +16 -16
  104. data/spec/grape/api_spec.rb +527 -224
  105. data/spec/grape/config_spec.rb +0 -2
  106. data/spec/grape/dsl/callbacks_spec.rb +2 -3
  107. data/spec/grape/dsl/configuration_spec.rb +0 -2
  108. data/spec/grape/dsl/desc_spec.rb +0 -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 +98 -57
  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 +61 -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 +0 -2
  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 +24 -17
  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 +27 -8
  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/attributes_iterator_spec.rb +0 -2
  169. data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
  170. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
  171. data/spec/grape/validations/params_scope_spec.rb +361 -96
  172. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
  173. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  174. data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
  175. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  176. data/spec/grape/validations/types_spec.rb +36 -10
  177. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
  178. data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
  179. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
  180. data/spec/grape/validations/validators/coerce_spec.rb +99 -24
  181. data/spec/grape/validations/validators/default_spec.rb +72 -80
  182. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
  183. data/spec/grape/validations/validators/except_values_spec.rb +3 -5
  184. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
  185. data/spec/grape/validations/validators/presence_spec.rb +16 -3
  186. data/spec/grape/validations/validators/regexp_spec.rb +25 -33
  187. data/spec/grape/validations/validators/same_as_spec.rb +14 -22
  188. data/spec/grape/validations/validators/values_spec.rb +182 -179
  189. data/spec/grape/validations_spec.rb +149 -80
  190. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  191. data/spec/integration/multi_json/json_spec.rb +1 -3
  192. data/spec/integration/multi_xml/xml_spec.rb +1 -3
  193. data/spec/shared/versioning_examples.rb +12 -9
  194. data/spec/spec_helper.rb +21 -6
  195. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  196. metadata +125 -115
  197. data/lib/grape/validations/validators/all_or_none.rb +0 -15
  198. data/lib/grape/validations/validators/allow_blank.rb +0 -18
  199. data/lib/grape/validations/validators/as.rb +0 -16
  200. data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
  201. data/lib/grape/validations/validators/coerce.rb +0 -91
  202. data/lib/grape/validations/validators/default.rb +0 -48
  203. data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
  204. data/lib/grape/validations/validators/except_values.rb +0 -22
  205. data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
  206. data/lib/grape/validations/validators/presence.rb +0 -12
  207. data/lib/grape/validations/validators/regexp.rb +0 -13
  208. data/lib/grape/validations/validators/same_as.rb +0 -26
  209. data/lib/grape/validations/validators/values.rb +0 -83
  210. data/spec/support/eager_load.rb +0 -19
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)
@@ -141,7 +145,7 @@ module Grape
141
145
  # Adds a new stage to the set up require to get a Grape::API up and running
142
146
  def add_setup(method, *args, &block)
143
147
  setup_step = { method: method, args: args, block: block }
144
- @setup << setup_step
148
+ @setup += [setup_step]
145
149
  last_response = nil
146
150
  @instances.each do |instance|
147
151
  last_response = replay_step_on(instance, setup_step)
@@ -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
@@ -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..-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,7 @@ 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
+ instance_exec(**options, &params_block)
68
66
  end
69
67
  end
70
68
  alias use_scope use
@@ -133,7 +131,7 @@ module Grape
133
131
  require_required_and_optional_fields(attrs.first, opts)
134
132
  else
135
133
  validate_attributes(attrs, opts, &block)
136
- block_given? ? new_scope(orig_attrs, &block) : push_declared_params(attrs, **opts.slice(:as))
134
+ block ? new_scope(orig_attrs, &block) : push_declared_params(attrs, **opts.slice(:as))
137
135
  end
138
136
  end
139
137
 
@@ -149,9 +147,9 @@ module Grape
149
147
  opts = @group.merge(opts) if instance_variable_defined?(:@group) && @group
150
148
 
151
149
  # 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)
150
+ if attrs && block
151
+ raise Grape::Exceptions::MissingGroupType if type.nil?
152
+ raise Grape::Exceptions::UnsupportedGroupType unless Grape::Validations::Types.group?(type)
155
153
  end
156
154
 
157
155
  if opts[:using]
@@ -159,7 +157,7 @@ module Grape
159
157
  else
160
158
  validate_attributes(attrs, opts, &block)
161
159
 
162
- block_given? ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, **opts.slice(:as))
160
+ block ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, **opts.slice(:as))
163
161
  end
164
162
  end
165
163
 
@@ -219,8 +217,8 @@ module Grape
219
217
  else
220
218
  # @declared_params also includes hashes of options and such, but those
221
219
  # won't be flattened out.
222
- @declared_params.flatten.any? do |declared_param|
223
- first_hash_key_or_param(declared_param) == param
220
+ @declared_params.flatten.any? do |declared_param_attr|
221
+ first_hash_key_or_param(declared_param_attr.key) == param
224
222
  end
225
223
  end
226
224
  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.map { |arg| [arg, handler] }.to_h
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) || {})
@@ -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
  # Keeps track of settings (implemented as key-value pairs, grouped by
@@ -103,12 +101,14 @@ module Grape
103
101
  def namespace_stackable_with_hash(key)
104
102
  settings = get_or_set :namespace_stackable, key, nil
105
103
  return if settings.blank?
104
+
106
105
  settings.each_with_object({}) { |value, result| result.deep_merge!(value) }
107
106
  end
108
107
 
109
108
  def namespace_reverse_stackable_with_hash(key)
110
109
  settings = get_or_set :namespace_reverse_stackable, key, nil
111
110
  return if settings.blank?
111
+
112
112
  result = {}
113
113
  settings.each do |setting|
114
114
  setting.each do |field, value|
@@ -154,10 +154,10 @@ module Grape
154
154
 
155
155
  # Execute the block within a context where our inheritable settings are forked
156
156
  # to a new copy (see #namespace_start).
157
- def within_namespace(&_block)
157
+ def within_namespace(&block)
158
158
  namespace_start
159
159
 
160
- result = yield if block_given?
160
+ result = yield if block
161
161
 
162
162
  namespace_end
163
163
  reset_validations!
@@ -175,9 +175,7 @@ module Grape
175
175
  # +inheritable_setting+, however, it doesn't contain any user-defined settings.
176
176
  # Otherwise, it would lead to an extra instance of +Grape::Util::InheritableSetting+
177
177
  # in the chain for every endpoint.
178
- if defined?(superclass) && superclass.respond_to?(:inheritable_setting) && superclass != Grape::API::Instance
179
- setting.inherit_from superclass.inheritable_setting
180
- end
178
+ setting.inherit_from superclass.inheritable_setting if defined?(superclass) && superclass.respond_to?(:inheritable_setting) && superclass != Grape::API::Instance
181
179
  end
182
180
  end
183
181
  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 Validations
@@ -32,7 +30,6 @@ module Grape
32
30
  unset_namespace_stackable :declared_params
33
31
  unset_namespace_stackable :validations
34
32
  unset_namespace_stackable :params
35
- unset_description_field :params
36
33
  end
37
34
 
38
35
  # Opens a root-level ParamsScope, defining parameter coercions and
@@ -41,18 +38,6 @@ module Grape
41
38
  def params(&block)
42
39
  Grape::Validations::ParamsScope.new(api: self, type: Hash, &block)
43
40
  end
44
-
45
- def document_attribute(names, opts)
46
- setting = description_field(:params)
47
- setting ||= description_field(:params, {})
48
- Array(names).each do |name|
49
- full_name = name[:full_name].to_s
50
- setting[full_name] ||= {}
51
- setting[full_name].merge!(opts)
52
-
53
- namespace_stackable(:params, full_name => opts)
54
- end
55
- end
56
41
  end
57
42
  end
58
43
  end