grape 2.3.0 → 3.0.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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -0
  3. data/CONTRIBUTING.md +2 -10
  4. data/README.md +106 -43
  5. data/UPGRADING.md +90 -1
  6. data/grape.gemspec +4 -4
  7. data/lib/grape/api/instance.rb +51 -73
  8. data/lib/grape/api.rb +56 -89
  9. data/lib/grape/cookies.rb +31 -25
  10. data/lib/grape/dry_types.rb +48 -4
  11. data/lib/grape/dsl/callbacks.rb +8 -58
  12. data/lib/grape/dsl/desc.rb +8 -67
  13. data/lib/grape/dsl/headers.rb +1 -1
  14. data/lib/grape/dsl/helpers.rb +60 -65
  15. data/lib/grape/dsl/inside_route.rb +26 -61
  16. data/lib/grape/dsl/logger.rb +3 -6
  17. data/lib/grape/dsl/middleware.rb +22 -40
  18. data/lib/grape/dsl/parameters.rb +10 -19
  19. data/lib/grape/dsl/request_response.rb +136 -139
  20. data/lib/grape/dsl/routing.rb +230 -194
  21. data/lib/grape/dsl/settings.rb +22 -134
  22. data/lib/grape/dsl/validations.rb +37 -45
  23. data/lib/grape/endpoint.rb +91 -126
  24. data/lib/grape/error_formatter/base.rb +2 -0
  25. data/lib/grape/exceptions/base.rb +1 -1
  26. data/lib/grape/exceptions/conflicting_types.rb +11 -0
  27. data/lib/grape/exceptions/invalid_parameters.rb +11 -0
  28. data/lib/grape/exceptions/missing_group_type.rb +0 -2
  29. data/lib/grape/exceptions/too_deep_parameters.rb +11 -0
  30. data/lib/grape/exceptions/unknown_auth_strategy.rb +11 -0
  31. data/lib/grape/exceptions/unknown_params_builder.rb +11 -0
  32. data/lib/grape/exceptions/unsupported_group_type.rb +0 -2
  33. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +2 -5
  34. data/lib/grape/extensions/hash.rb +2 -1
  35. data/lib/grape/extensions/hashie/mash.rb +3 -5
  36. data/lib/grape/locale/en.yml +44 -44
  37. data/lib/grape/middleware/auth/base.rb +11 -32
  38. data/lib/grape/middleware/auth/dsl.rb +22 -29
  39. data/lib/grape/middleware/base.rb +30 -11
  40. data/lib/grape/middleware/error.rb +14 -32
  41. data/lib/grape/middleware/formatter.rb +40 -72
  42. data/lib/grape/middleware/stack.rb +28 -38
  43. data/lib/grape/middleware/versioner/accept_version_header.rb +2 -4
  44. data/lib/grape/middleware/versioner/base.rb +30 -56
  45. data/lib/grape/middleware/versioner/header.rb +2 -2
  46. data/lib/grape/middleware/versioner/param.rb +2 -3
  47. data/lib/grape/middleware/versioner/path.rb +1 -1
  48. data/lib/grape/namespace.rb +11 -0
  49. data/lib/grape/params_builder/base.rb +20 -0
  50. data/lib/grape/params_builder/hash.rb +11 -0
  51. data/lib/grape/params_builder/hash_with_indifferent_access.rb +11 -0
  52. data/lib/grape/params_builder/hashie_mash.rb +11 -0
  53. data/lib/grape/params_builder.rb +32 -0
  54. data/lib/grape/request.rb +161 -22
  55. data/lib/grape/router/route.rb +1 -1
  56. data/lib/grape/router.rb +27 -8
  57. data/lib/grape/util/api_description.rb +56 -0
  58. data/lib/grape/util/base_inheritable.rb +5 -2
  59. data/lib/grape/util/inheritable_setting.rb +7 -0
  60. data/lib/grape/util/media_type.rb +1 -1
  61. data/lib/grape/util/registry.rb +1 -1
  62. data/lib/grape/validations/contract_scope.rb +2 -2
  63. data/lib/grape/validations/params_documentation.rb +50 -0
  64. data/lib/grape/validations/params_scope.rb +46 -56
  65. data/lib/grape/validations/types/array_coercer.rb +2 -3
  66. data/lib/grape/validations/types/dry_type_coercer.rb +4 -11
  67. data/lib/grape/validations/types/primitive_coercer.rb +1 -28
  68. data/lib/grape/validations/types.rb +10 -25
  69. data/lib/grape/validations/validators/base.rb +2 -9
  70. data/lib/grape/validations/validators/except_values_validator.rb +1 -1
  71. data/lib/grape/validations/validators/presence_validator.rb +1 -1
  72. data/lib/grape/validations/validators/regexp_validator.rb +1 -1
  73. data/lib/grape/version.rb +1 -1
  74. data/lib/grape.rb +18 -9
  75. metadata +35 -20
  76. data/lib/grape/api/helpers.rb +0 -9
  77. data/lib/grape/dsl/api.rb +0 -19
  78. data/lib/grape/dsl/configuration.rb +0 -15
  79. data/lib/grape/error_formatter/jsonapi.rb +0 -7
  80. data/lib/grape/http/headers.rb +0 -56
  81. data/lib/grape/middleware/helpers.rb +0 -12
  82. data/lib/grape/parser/jsonapi.rb +0 -7
  83. data/lib/grape/types/invalid_value.rb +0 -8
  84. data/lib/grape/util/lazy/object.rb +0 -45
  85. data/lib/grape/util/strict_hash_configuration.rb +0 -108
  86. data/lib/grape/validations/attributes_doc.rb +0 -60
@@ -3,28 +3,7 @@
3
3
  module Grape
4
4
  module DSL
5
5
  module Desc
6
- include Grape::DSL::Settings
7
-
8
- ROUTE_ATTRIBUTES = %i[
9
- body_name
10
- consumes
11
- default
12
- deprecated
13
- description
14
- detail
15
- entity
16
- headers
17
- hidden
18
- http_codes
19
- is_array
20
- named
21
- nickname
22
- params
23
- produces
24
- security
25
- summary
26
- tags
27
- ].freeze
6
+ extend Grape::DSL::Settings
28
7
 
29
8
  # Add a description to the next namespace or function.
30
9
  # @param description [String] descriptive string for this endpoint
@@ -70,54 +49,16 @@ module Grape
70
49
  # # ...
71
50
  # end
72
51
  #
73
- def desc(description, options = nil, &config_block)
74
- opts =
52
+ def desc(description, options = {}, &config_block)
53
+ settings =
75
54
  if config_block
76
- desc_container(endpoint_configuration).then do |config_class|
77
- config_class.configure do
78
- description(description)
79
- end
80
-
81
- config_class.configure(&config_block)
82
- config_class.settings
83
- end
55
+ endpoint_config = defined?(configuration) ? configuration : nil
56
+ Grape::Util::ApiDescription.new(description, endpoint_config, &config_block).settings
84
57
  else
85
- options&.merge(description: description) || { description: description }
86
- end
87
-
88
- namespace_setting :description, opts
89
- route_setting :description, opts
90
- end
91
-
92
- # Returns an object which configures itself via an instance-context DSL.
93
- def desc_container(endpoint_configuration)
94
- Module.new do
95
- include Grape::Util::StrictHashConfiguration.module(*ROUTE_ATTRIBUTES)
96
- config_context.define_singleton_method(:configuration) do
97
- endpoint_configuration
98
- end
99
-
100
- def config_context.success(*args)
101
- entity(*args)
102
- end
103
-
104
- def config_context.failure(*args)
105
- http_codes(*args)
58
+ options.merge(description: description)
106
59
  end
107
- end
108
- end
109
-
110
- private
111
-
112
- def endpoint_configuration
113
- return {} unless defined?(configuration)
114
-
115
- if configuration.respond_to?(:evaluate)
116
- configuration.evaluate
117
- # Within `given` or `mounted blocks` the configuration is already evaluated
118
- elsif configuration.is_a?(Hash)
119
- configuration
120
- end
60
+ inheritable_setting.namespace[:description] = settings
61
+ inheritable_setting.route[:description] = settings
121
62
  end
122
63
  end
123
64
  end
@@ -10,7 +10,7 @@ module Grape
10
10
  # 4. Delete a specifc header key-value pair
11
11
  def header(key = nil, val = nil)
12
12
  if key
13
- val ? header[key.to_s] = val : header.delete(key.to_s)
13
+ val ? header[key] = val : header.delete(key)
14
14
  else
15
15
  @header ||= Grape::Util::Header.new
16
16
  end
@@ -3,81 +3,76 @@
3
3
  module Grape
4
4
  module DSL
5
5
  module Helpers
6
- extend ActiveSupport::Concern
7
- include Grape::DSL::Configuration
8
-
9
- module ClassMethods
10
- # Add helper methods that will be accessible from any
11
- # endpoint within this namespace (and child namespaces).
12
- #
13
- # When called without a block, all known helpers within this scope
14
- # are included.
15
- #
16
- # @param [Array] new_modules optional array of modules to include
17
- # @param [Block] block optional block of methods to include
18
- #
19
- # @example Define some helpers.
20
- #
21
- # class ExampleAPI < Grape::API
22
- # helpers do
23
- # def current_user
24
- # User.find_by_id(params[:token])
25
- # end
26
- # end
27
- # end
28
- #
29
- # @example Include many modules
30
- #
31
- # class ExampleAPI < Grape::API
32
- # helpers Authentication, Mailer, OtherModule
33
- # end
34
- #
35
- def helpers(*new_modules, &block)
36
- include_new_modules(new_modules)
37
- include_block(block)
38
- include_all_in_scope if !block && new_modules.empty?
39
- end
6
+ # Add helper methods that will be accessible from any
7
+ # endpoint within this namespace (and child namespaces).
8
+ #
9
+ # When called without a block, all known helpers within this scope
10
+ # are included.
11
+ #
12
+ # @param [Array] new_modules optional array of modules to include
13
+ # @param [Block] block optional block of methods to include
14
+ #
15
+ # @example Define some helpers.
16
+ #
17
+ # class ExampleAPI < Grape::API
18
+ # helpers do
19
+ # def current_user
20
+ # User.find_by_id(params[:token])
21
+ # end
22
+ # end
23
+ # end
24
+ #
25
+ # @example Include many modules
26
+ #
27
+ # class ExampleAPI < Grape::API
28
+ # helpers Authentication, Mailer, OtherModule
29
+ # end
30
+ #
31
+ def helpers(*new_modules, &block)
32
+ include_new_modules(new_modules)
33
+ include_block(block)
34
+ include_all_in_scope if !block && new_modules.empty?
35
+ end
40
36
 
41
- protected
37
+ private
42
38
 
43
- def include_new_modules(modules)
44
- return if modules.empty?
39
+ def include_new_modules(modules)
40
+ return if modules.empty?
45
41
 
46
- modules.each { |mod| make_inclusion(mod) }
47
- end
42
+ modules.each { |mod| make_inclusion(mod) }
43
+ end
48
44
 
49
- def include_block(block)
50
- return unless block
45
+ def include_block(block)
46
+ return unless block
51
47
 
52
- Module.new.tap do |mod|
53
- make_inclusion(mod) { mod.class_eval(&block) }
54
- end
48
+ Module.new.tap do |mod|
49
+ make_inclusion(mod) { mod.class_eval(&block) }
55
50
  end
51
+ end
56
52
 
57
- def make_inclusion(mod, &block)
58
- define_boolean_in_mod(mod)
59
- inject_api_helpers_to_mod(mod, &block)
60
- namespace_stackable(:helpers, mod)
61
- end
53
+ def make_inclusion(mod, &block)
54
+ define_boolean_in_mod(mod)
55
+ inject_api_helpers_to_mod(mod, &block)
56
+ inheritable_setting.namespace_stackable[:helpers] = mod
57
+ end
62
58
 
63
- def include_all_in_scope
64
- Module.new.tap do |mod|
65
- namespace_stackable(:helpers).each { |mod_to_include| mod.include mod_to_include }
66
- change!
67
- end
59
+ def include_all_in_scope
60
+ Module.new.tap do |mod|
61
+ namespace_stackable(:helpers).each { |mod_to_include| mod.include mod_to_include }
62
+ change!
68
63
  end
64
+ end
69
65
 
70
- def define_boolean_in_mod(mod)
71
- return if defined? mod::Boolean
66
+ def define_boolean_in_mod(mod)
67
+ return if defined? mod::Boolean
72
68
 
73
- mod.const_set(:Boolean, Grape::API::Boolean)
74
- end
69
+ mod.const_set(:Boolean, Grape::API::Boolean)
70
+ end
75
71
 
76
- def inject_api_helpers_to_mod(mod, &block)
77
- mod.extend(BaseHelper) unless mod.is_a?(BaseHelper)
78
- yield if block
79
- mod.api_changed(self)
80
- end
72
+ def inject_api_helpers_to_mod(mod, &block)
73
+ mod.extend(BaseHelper) unless mod.is_a?(BaseHelper)
74
+ yield if block
75
+ mod.api_changed(self)
81
76
  end
82
77
 
83
78
  # This module extends user defined helpers
@@ -98,9 +93,9 @@ module Grape
98
93
  protected
99
94
 
100
95
  def process_named_params
101
- return unless instance_variable_defined?(:@named_params) && @named_params && @named_params.any?
96
+ return if @named_params.blank?
102
97
 
103
- api.namespace_stackable(:named_params, @named_params)
98
+ api.inheritable_setting.namespace_stackable[:named_params] = @named_params
104
99
  end
105
100
  end
106
101
  end
@@ -3,10 +3,6 @@
3
3
  module Grape
4
4
  module DSL
5
5
  module InsideRoute
6
- extend ActiveSupport::Concern
7
- include Grape::DSL::Settings
8
- include Grape::DSL::Headers
9
-
10
6
  # Denotes a situation where a DSL method has been invoked in a
11
7
  # filter which it should not yet be available in
12
8
  class MethodNotYetAvailable < StandardError; end
@@ -35,7 +31,7 @@ module Grape
35
31
  declared_hash(passed_params, options, declared_params, params_nested_path)
36
32
  end
37
33
 
38
- if (key_maps = namespace_stackable(:contract_key_map))
34
+ if (key_maps = inheritable_setting.namespace_stackable[:contract_key_map])
39
35
  key_maps.each { |key_map| key_map.write(passed_params, res) }
40
36
  end
41
37
 
@@ -59,7 +55,7 @@ module Grape
59
55
  end
60
56
 
61
57
  def declared_hash_attr(passed_params, options, declared_param, params_nested_path, memo)
62
- renamed_params = route_setting(:renamed_params) || {}
58
+ renamed_params = inheritable_setting.route[:renamed_params] || {}
63
59
  if declared_param.is_a?(Hash)
64
60
  declared_param.each_pair do |declared_parent_param, declared_children_params|
65
61
  params_nested_path_dup = params_nested_path.dup
@@ -79,7 +75,7 @@ module Grape
79
75
  else
80
76
  # If it is not a Hash then it does not have children.
81
77
  # Find its value or set it to nil.
82
- return unless options[:include_missing] || passed_params.key?(declared_param)
78
+ return unless options[:include_missing] || passed_params.try(:key?, declared_param)
83
79
 
84
80
  rename_path = params_nested_path + [declared_param.to_s]
85
81
  renamed_param_name = renamed_params[rename_path]
@@ -107,7 +103,7 @@ module Grape
107
103
 
108
104
  if type == 'Hash' && !has_children
109
105
  {}
110
- elsif type == 'Array' || (type&.start_with?('[') && type&.exclude?(','))
106
+ elsif type == 'Array' || (type&.start_with?('[') && type.exclude?(','))
111
107
  []
112
108
  elsif type == 'Set' || type&.start_with?('#<Set')
113
109
  Set.new
@@ -123,10 +119,10 @@ module Grape
123
119
  def optioned_declared_params(include_parent_namespaces)
124
120
  declared_params = if include_parent_namespaces
125
121
  # Declared params including parent namespaces
126
- route_setting(:declared_params)
122
+ inheritable_setting.route[:declared_params]
127
123
  else
128
124
  # Declared params at current namespace
129
- namespace_stackable(:declared_params).last || []
125
+ inheritable_setting.namespace_stackable[:declared_params].last || []
130
126
  end
131
127
 
132
128
  raise ArgumentError, 'Tried to filter for declared parameters but none exist.' unless declared_params
@@ -168,7 +164,7 @@ module Grape
168
164
  # @param backtrace [Array<String>] The backtrace of the exception that caused the error.
169
165
  # @param original_exception [Exception] The original exception that caused the error.
170
166
  def error!(message, status = nil, additional_headers = nil, backtrace = nil, original_exception = nil)
171
- status = self.status(status || namespace_inheritable(:default_error_status))
167
+ status = self.status(status || inheritable_setting.namespace_inheritable[:default_error_status])
172
168
  headers = additional_headers.present? ? header.merge(additional_headers) : header
173
169
  throw :error,
174
170
  message: message,
@@ -178,24 +174,6 @@ module Grape
178
174
  original_exception: original_exception
179
175
  end
180
176
 
181
- # Creates a Rack response based on the provided message, status, and headers.
182
- # The content type in the headers is set to the default content type unless provided.
183
- # The message is HTML-escaped if the content type is 'text/html'.
184
- #
185
- # @param message [String] The content of the response.
186
- # @param status [Integer] The HTTP status code.
187
- # @params headers [Hash] (optional) Headers for the response
188
- # (default: {Rack::CONTENT_TYPE => content_type}).
189
- #
190
- # Returns:
191
- # A Rack::Response object containing the specified message, status, and headers.
192
- #
193
- def rack_response(message, status = 200, headers = { Rack::CONTENT_TYPE => content_type })
194
- Grape.deprecator.warn('The rack_response method has been deprecated, use error! instead.')
195
- message = Rack::Utils.escape_html(message) if headers[Rack::CONTENT_TYPE] == 'text/html'
196
- Rack::Response.new(Array.wrap(message), Rack::Utils.status_code(status), headers)
197
- end
198
-
199
177
  # Redirect to a new url.
200
178
  #
201
179
  # @param url [String] The url to be redirect.
@@ -213,7 +191,7 @@ module Grape
213
191
  status 302
214
192
  body_message ||= "This resource has been moved temporarily to #{url}."
215
193
  end
216
- header Grape::Http::Headers::LOCATION, url
194
+ header 'Location', url
217
195
  content_type 'text/plain'
218
196
  body body_message
219
197
  end
@@ -257,18 +235,6 @@ module Grape
257
235
  end
258
236
  end
259
237
 
260
- # Set or get a cookie
261
- #
262
- # @example
263
- # cookies[:mycookie] = 'mycookie val'
264
- # cookies['mycookie-string'] = 'mycookie string val'
265
- # cookies[:more] = { value: '123', expires: Time.at(0) }
266
- # cookies.delete :more
267
- #
268
- def cookies
269
- @cookies ||= Cookies.new
270
- end
271
-
272
238
  # Allows you to define the response body as something other than the
273
239
  # return value.
274
240
  #
@@ -342,7 +308,7 @@ module Grape
342
308
  return if value.nil? && @stream.nil?
343
309
 
344
310
  header Rack::CONTENT_LENGTH, nil
345
- header Grape::Http::Headers::TRANSFER_ENCODING, nil
311
+ header 'Transfer-Encoding', nil
346
312
  header Rack::CACHE_CONTROL, 'no-cache' # Skips ETag generation (reading the response up front)
347
313
  if value.is_a?(String)
348
314
  file_body = Grape::ServeStream::FileBody.new(value)
@@ -371,8 +337,7 @@ module Grape
371
337
  # with: API::Entities::User,
372
338
  # admin: current_user.admin?
373
339
  # end
374
- def present(*args)
375
- options = args.count > 1 ? args.extract_options! : {}
340
+ def present(*args, **options)
376
341
  key, object = if args.count == 2 && args.first.is_a?(Symbol)
377
342
  args
378
343
  else
@@ -423,22 +388,22 @@ module Grape
423
388
  # @return [Class] the located Entity class, or nil if none is found
424
389
  def entity_class_for_obj(object, options)
425
390
  entity_class = options.delete(:with)
426
-
427
- if entity_class.nil?
428
- # entity class not explicitly defined, auto-detect from relation#klass or first object in the collection
429
- object_class = if object.respond_to?(:klass)
430
- object.klass
431
- else
432
- object.respond_to?(:first) ? object.first.class : object.class
433
- end
434
-
435
- object_class.ancestors.each do |potential|
436
- entity_class ||= (namespace_stackable_with_hash(:representations) || {})[potential]
437
- end
438
-
439
- entity_class ||= object_class.const_get(:Entity) if object_class.const_defined?(:Entity) && object_class.const_get(:Entity).respond_to?(:represent)
391
+ return entity_class if entity_class
392
+
393
+ # entity class not explicitly defined, auto-detect from relation#klass or first object in the collection
394
+ object_class = if object.respond_to?(:klass)
395
+ object.klass
396
+ else
397
+ object.respond_to?(:first) ? object.first.class : object.class
398
+ end
399
+
400
+ representations = inheritable_setting.namespace_stackable_with_hash(:representations)
401
+ if representations
402
+ potential = object_class.ancestors.detect { |potential| representations.key?(potential) }
403
+ entity_class = representations[potential] if potential
440
404
  end
441
405
 
406
+ entity_class = object_class.const_get(:Entity) if !entity_class && object_class.const_defined?(:Entity) && object_class.const_get(:Entity).respond_to?(:represent)
442
407
  entity_class
443
408
  end
444
409
 
@@ -447,11 +412,11 @@ module Grape
447
412
  def entity_representation_for(entity_class, object, options)
448
413
  embeds = { env: env }
449
414
  embeds[:version] = env[Grape::Env::API_VERSION] if env.key?(Grape::Env::API_VERSION)
450
- entity_class.represent(object, **embeds.merge(options))
415
+ entity_class.represent(object, **embeds, **options)
451
416
  end
452
417
 
453
418
  def http_version
454
- env.fetch(Grape::Http::Headers::HTTP_VERSION) { env[Rack::SERVER_PROTOCOL] }
419
+ env.fetch('HTTP_VERSION') { env[Rack::SERVER_PROTOCOL] }
455
420
  end
456
421
 
457
422
  def api_format(format)
@@ -3,18 +3,15 @@
3
3
  module Grape
4
4
  module DSL
5
5
  module Logger
6
- include Grape::DSL::Settings
7
-
8
- attr_writer :logger
9
-
10
6
  # Set or retrive the configured logger. If none was configured, this
11
7
  # method will create a new one, logging to stdout.
12
8
  # @param logger [Object] the new logger to use
13
9
  def logger(logger = nil)
10
+ global_settings = inheritable_setting.global
14
11
  if logger
15
- global_setting(:logger, logger)
12
+ global_settings[:logger] = logger
16
13
  else
17
- global_setting(:logger) || global_setting(:logger, ::Logger.new($stdout))
14
+ global_settings[:logger] || global_settings[:logger] = ::Logger.new($stdout)
18
15
  end
19
16
  end
20
17
  end
@@ -3,51 +3,33 @@
3
3
  module Grape
4
4
  module DSL
5
5
  module Middleware
6
- extend ActiveSupport::Concern
7
-
8
- include Grape::DSL::Configuration
9
-
10
- module ClassMethods
11
- # Apply a custom middleware to the API. Applies
12
- # to the current namespace and any children, but
13
- # not parents.
14
- #
15
- # @param middleware_class [Class] The class of the middleware you'd like
16
- # to inject.
17
- def use(middleware_class, *args, &block)
18
- arr = [:use, middleware_class, *args]
19
- arr << block if block
20
-
21
- namespace_stackable(:middleware, arr)
22
- end
23
-
24
- def insert(*args, &block)
25
- arr = [:insert, *args]
26
- arr << block if block
27
-
28
- namespace_stackable(:middleware, arr)
29
- end
30
-
31
- def insert_before(*args, &block)
32
- arr = [:insert_before, *args]
33
- arr << block if block
34
-
35
- namespace_stackable(:middleware, arr)
36
- end
6
+ # Apply a custom middleware to the API. Applies
7
+ # to the current namespace and any children, but
8
+ # not parents.
9
+ #
10
+ # @param middleware_class [Class] The class of the middleware you'd like
11
+ # to inject.
12
+ def use(middleware_class, *args, &block)
13
+ arr = [:use, middleware_class, *args]
14
+ arr << block if block
15
+
16
+ inheritable_setting.namespace_stackable[:middleware] = arr
17
+ end
37
18
 
38
- def insert_after(*args, &block)
39
- arr = [:insert_after, *args]
19
+ %i[insert insert_before insert_after].each do |method_name|
20
+ define_method method_name do |*args, &block|
21
+ arr = [method_name, *args]
40
22
  arr << block if block
41
23
 
42
- namespace_stackable(:middleware, arr)
24
+ inheritable_setting.namespace_stackable[:middleware] = arr
43
25
  end
26
+ end
44
27
 
45
- # Retrieve an array of the middleware classes
46
- # and arguments that are currently applied to the
47
- # application.
48
- def middleware
49
- namespace_stackable(:middleware) || []
50
- end
28
+ # Retrieve an array of the middleware classes
29
+ # and arguments that are currently applied to the
30
+ # application.
31
+ def middleware
32
+ inheritable_setting.namespace_stackable[:middleware] || []
51
33
  end
52
34
  end
53
35
  end
@@ -6,8 +6,6 @@ module Grape
6
6
  # and describe the parameters accepted by an endpoint, or all endpoints
7
7
  # within a namespace.
8
8
  module Parameters
9
- extend ActiveSupport::Concern
10
-
11
9
  # Set the module used to build the request.params.
12
10
  #
13
11
  # @param build_with the ParamBuilder module to use when building request.params
@@ -23,15 +21,15 @@ module Grape
23
21
  # class API < Grape::API
24
22
  # desc "Get collection"
25
23
  # params do
26
- # build_with Grape::Extensions::Hashie::Mash::ParamBuilder
24
+ # build_with :hashie_mash
27
25
  # requires :user_id, type: Integer
28
26
  # end
29
27
  # get do
30
28
  # params['user_id']
31
29
  # end
32
30
  # end
33
- def build_with(build_with = nil)
34
- @api.namespace_inheritable(:build_params_with, build_with)
31
+ def build_with(build_with)
32
+ @api.inheritable_setting.namespace_inheritable[:build_params_with] = build_with
35
33
  end
36
34
 
37
35
  # Include reusable params rules among current.
@@ -55,9 +53,8 @@ module Grape
55
53
  # Collection.page(params[:page]).per(params[:per_page])
56
54
  # end
57
55
  # end
58
- def use(*names)
59
- named_params = @api.namespace_stackable_with_hash(:named_params) || {}
60
- options = names.extract_options!
56
+ def use(*names, **options)
57
+ named_params = @api.inheritable_setting.namespace_stackable_with_hash(:named_params) || {}
61
58
  names.each do |name|
62
59
  params_block = named_params.fetch(name) do
63
60
  raise "Params :#{name} not found!"
@@ -125,10 +122,7 @@ module Grape
125
122
  # requires :name, type: String
126
123
  # end
127
124
  # end
128
- def requires(*attrs, &block)
129
- orig_attrs = attrs.clone
130
-
131
- opts = attrs.extract_options!.clone
125
+ def requires(*attrs, **opts, &block)
132
126
  opts[:presence] = { value: true, message: opts[:message] }
133
127
  opts = @group.deep_merge(opts) if instance_variable_defined?(:@group) && @group
134
128
 
@@ -136,7 +130,7 @@ module Grape
136
130
  require_required_and_optional_fields(attrs.first, opts)
137
131
  else
138
132
  validate_attributes(attrs, opts, &block)
139
- block ? new_scope(orig_attrs, &block) : push_declared_params(attrs, opts.slice(:as))
133
+ block ? new_scope(attrs, opts, &block) : push_declared_params(attrs, opts.slice(:as))
140
134
  end
141
135
  end
142
136
 
@@ -144,10 +138,7 @@ module Grape
144
138
  # endpoint.
145
139
  # @param (see #requires)
146
140
  # @option (see #requires)
147
- def optional(*attrs, &block)
148
- orig_attrs = attrs.clone
149
-
150
- opts = attrs.extract_options!.clone
141
+ def optional(*attrs, **opts, &block)
151
142
  type = opts[:type]
152
143
  opts = @group.deep_merge(opts) if instance_variable_defined?(:@group) && @group
153
144
 
@@ -162,7 +153,7 @@ module Grape
162
153
  else
163
154
  validate_attributes(attrs, opts, &block)
164
155
 
165
- block ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, opts.slice(:as))
156
+ block ? new_scope(attrs, opts, true, &block) : push_declared_params(attrs, opts.slice(:as))
166
157
  end
167
158
  end
168
159
 
@@ -251,7 +242,7 @@ module Grape
251
242
  # @return hash of parameters relevant for the current scope
252
243
  # @api private
253
244
  def params(params)
254
- params = @parent.params(params) if instance_variable_defined?(:@parent) && @parent
245
+ params = @parent.params_meeting_dependency.presence || @parent.params(params) if instance_variable_defined?(:@parent) && @parent
255
246
  params = map_params(params, @element) if instance_variable_defined?(:@element) && @element
256
247
  params
257
248
  end