Skip to content

Commit a8dada4

Browse files
committed
Remove namespace_stackable and namespace_inheritable from public API
- Refactor internal implementation to use inheritable_setting directly - Remove public access to namespace_stackable and namespace_inheritable methods - Update DSL modules to use internal configuration access - Add equality methods to Namespace class for proper comparison - Update tests to reflect internal API changes - Maintain backward compatibility for public-facing methods
1 parent 6dc01a7 commit a8dada4

24 files changed

+274
-299
lines changed

lib/grape/api/instance.rb

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,9 @@ def call!(env)
8282

8383
# (see #cascade?)
8484
def cascade(value = nil)
85-
if value.nil?
86-
inheritable_setting.namespace_inheritable.key?(:cascade) ? !namespace_inheritable(:cascade).nil? : true
87-
else
88-
namespace_inheritable(:cascade, value)
89-
end
85+
return inheritable_setting.namespace_inheritable.key?(:cascade) ? !inheritable_setting.namespace_inheritable(:cascade).nil? : true if value.nil?
86+
87+
inheritable_setting.namespace_inheritable[:cascade] = value
9088
end
9189

9290
def compile!
@@ -103,35 +101,6 @@ def recognize_path(path)
103101

104102
protected
105103

106-
# Execute first the provided block, then each of the
107-
# block passed in. Allows for simple 'before' setups
108-
# of settings stack pushes.
109-
def nest(*blocks, &block)
110-
blocks.compact!
111-
if blocks.any?
112-
evaluate_as_instance_with_configuration(block) if block
113-
blocks.each { |b| evaluate_as_instance_with_configuration(b) }
114-
reset_validations!
115-
else
116-
instance_eval(&block)
117-
end
118-
end
119-
120-
def evaluate_as_instance_with_configuration(block, lazy: false)
121-
lazy_block = Grape::Util::Lazy::Block.new do |configuration|
122-
value_for_configuration = configuration
123-
self.configuration = value_for_configuration.evaluate if value_for_configuration.try(:lazy?)
124-
response = instance_eval(&block)
125-
self.configuration = value_for_configuration
126-
response
127-
end
128-
if base && base_instance? && lazy
129-
lazy_block
130-
else
131-
lazy_block.evaluate_from(configuration)
132-
end
133-
end
134-
135104
def inherited(subclass)
136105
super
137106
subclass.reset!
@@ -187,8 +156,9 @@ def call(env)
187156
# errors from reaching upstream. This is effectivelly done by unsetting
188157
# X-Cascade. Default :cascade is true.
189158
def cascade?
190-
return self.class.namespace_inheritable(:cascade) if self.class.inheritable_setting.namespace_inheritable.key?(:cascade)
191-
return self.class.namespace_inheritable(:version_options)[:cascade] if self.class.namespace_inheritable(:version_options)&.key?(:cascade)
159+
namespace_inheritable = self.class.inheritable_setting.namespace_inheritable
160+
return namespace_inheritable[:cascade] if namespace_inheritable.key?(:cascade)
161+
return namespace_inheritable[:version_options][:cascade] if namespace_inheritable[:version_options]&.key?(:cascade)
192162

193163
true
194164
end
@@ -219,11 +189,12 @@ def collect_route_config_per_pattern(all_routes)
219189
last_route = routes.last # Most of the configuration is taken from the last endpoint
220190
next if routes.any? { |route| route.request_method == '*' }
221191

192+
namespace_inheritable = self.class.inheritable_setting.namespace_inheritable
222193
allowed_methods = routes.map(&:request_method)
223-
allowed_methods |= [Rack::HEAD] if !self.class.namespace_inheritable(:do_not_route_head) && allowed_methods.include?(Rack::GET)
194+
allowed_methods |= [Rack::HEAD] if !namespace_inheritable[:do_not_route_head] && allowed_methods.include?(Rack::GET)
224195

225-
allow_header = self.class.namespace_inheritable(:do_not_route_options) ? allowed_methods : [Rack::OPTIONS] | allowed_methods
226-
last_route.app.options[:options_route_enabled] = true unless self.class.namespace_inheritable(:do_not_route_options) || allowed_methods.include?(Rack::OPTIONS)
196+
allow_header = namespace_inheritable[:do_not_route_options] ? allowed_methods : [Rack::OPTIONS] | allowed_methods
197+
last_route.app.options[:options_route_enabled] = true unless namespace_inheritable[:do_not_route_options] || allowed_methods.include?(Rack::OPTIONS)
227198

228199
@router.associate_routes(last_route.pattern, {
229200
endpoint: last_route.app,

lib/grape/dsl/callbacks.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module Callbacks
1111

1212
%w[before before_validation after_validation after finally].each do |callback_method|
1313
define_method callback_method.to_sym do |&block|
14-
namespace_stackable(callback_method.pluralize.to_sym, block)
14+
inheritable_setting.namespace_stackable[callback_method.pluralize.to_sym] = block
1515
end
1616
end
1717
end

lib/grape/dsl/helpers.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def include_block(block)
5353
def make_inclusion(mod, &block)
5454
define_boolean_in_mod(mod)
5555
inject_api_helpers_to_mod(mod, &block)
56-
namespace_stackable(:helpers, mod)
56+
inheritable_setting.namespace_stackable[:helpers] = mod
5757
end
5858

5959
def include_all_in_scope
@@ -95,7 +95,7 @@ def api_changed(new_api)
9595
def process_named_params
9696
return if @named_params.blank?
9797

98-
api.namespace_stackable(:named_params, @named_params)
98+
api.inheritable_setting.namespace_stackable[:named_params] = @named_params
9999
end
100100
end
101101
end

lib/grape/dsl/inside_route.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def declared(passed_params, options = {}, declared_params = nil, params_nested_p
3131
declared_hash(passed_params, options, declared_params, params_nested_path)
3232
end
3333

34-
if (key_maps = namespace_stackable(:contract_key_map))
34+
if (key_maps = inheritable_setting.namespace_stackable[:contract_key_map])
3535
key_maps.each { |key_map| key_map.write(passed_params, res) }
3636
end
3737

@@ -122,7 +122,7 @@ def optioned_declared_params(include_parent_namespaces)
122122
inheritable_setting.route[:declared_params]
123123
else
124124
# Declared params at current namespace
125-
namespace_stackable(:declared_params).last || []
125+
inheritable_setting.namespace_stackable[:declared_params].last || []
126126
end
127127

128128
raise ArgumentError, 'Tried to filter for declared parameters but none exist.' unless declared_params
@@ -164,7 +164,7 @@ def configuration
164164
# @param backtrace [Array<String>] The backtrace of the exception that caused the error.
165165
# @param original_exception [Exception] The original exception that caused the error.
166166
def error!(message, status = nil, additional_headers = nil, backtrace = nil, original_exception = nil)
167-
status = self.status(status || namespace_inheritable(:default_error_status))
167+
status = self.status(status || inheritable_setting.namespace_inheritable[:default_error_status])
168168
headers = additional_headers.present? ? header.merge(additional_headers) : header
169169
throw :error,
170170
message: message,

lib/grape/dsl/middleware.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,23 @@ def use(middleware_class, *args, &block)
1313
arr = [:use, middleware_class, *args]
1414
arr << block if block
1515

16-
namespace_stackable(:middleware, arr)
16+
inheritable_setting.namespace_stackable[:middleware] = arr
1717
end
1818

1919
%i[insert insert_before insert_after].each do |method_name|
2020
define_method method_name do |*args, &block|
2121
arr = [method_name, *args]
2222
arr << block if block
2323

24-
namespace_stackable(:middleware, arr)
24+
inheritable_setting.namespace_stackable[:middleware] = arr
2525
end
2626
end
2727

2828
# Retrieve an array of the middleware classes
2929
# and arguments that are currently applied to the
3030
# application.
3131
def middleware
32-
namespace_stackable(:middleware) || []
32+
inheritable_setting.namespace_stackable[:middleware] || []
3333
end
3434
end
3535
end

lib/grape/dsl/parameters.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ module Parameters
2929
# end
3030
# end
3131
def build_with(build_with)
32-
@api.namespace_inheritable(:build_params_with, build_with)
32+
@api.inheritable_setting.namespace_inheritable[:build_params_with] = build_with
3333
end
3434

3535
# Include reusable params rules among current.

lib/grape/dsl/request_response.rb

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,42 @@ module RequestResponse
66
# Specify the default format for the API's serializers.
77
# May be `:json` or `:txt` (default).
88
def default_format(new_format = nil)
9-
namespace_inheritable(:default_format, new_format&.to_sym)
9+
return inheritable_setting.namespace_inheritable[:default_format] if new_format.nil?
10+
11+
inheritable_setting.namespace_inheritable[:default_format] = new_format.to_sym
1012
end
1113

1214
# Specify the format for the API's serializers.
1315
# May be `:json`, `:xml`, `:txt`, etc.
1416
def format(new_format = nil)
15-
return namespace_inheritable(:format) unless new_format
17+
return inheritable_setting.namespace_inheritable[:format] if new_format.nil?
1618

1719
symbolic_new_format = new_format.to_sym
18-
namespace_inheritable(:format, symbolic_new_format)
19-
namespace_inheritable(:default_error_formatter, Grape::ErrorFormatter.formatter_for(symbolic_new_format))
20+
inheritable_setting.namespace_inheritable[:format] = symbolic_new_format
21+
inheritable_setting.namespace_inheritable[:default_error_formatter] = Grape::ErrorFormatter.formatter_for(symbolic_new_format)
2022

2123
content_type = content_types[symbolic_new_format]
2224
raise Grape::Exceptions::MissingMimeType.new(new_format) unless content_type
2325

24-
namespace_stackable(:content_types, symbolic_new_format => content_type)
26+
inheritable_setting.namespace_stackable[:content_types] = { symbolic_new_format => content_type }
2527
end
2628

2729
# Specify a custom formatter for a content-type.
2830
def formatter(content_type, new_formatter)
29-
namespace_stackable(:formatters, content_type.to_sym => new_formatter)
31+
inheritable_setting.namespace_stackable[:formatters] = { content_type.to_sym => new_formatter }
3032
end
3133

3234
# Specify a custom parser for a content-type.
3335
def parser(content_type, new_parser)
34-
namespace_stackable(:parsers, content_type.to_sym => new_parser)
36+
inheritable_setting.namespace_stackable[:parsers] = { content_type.to_sym => new_parser }
3537
end
3638

3739
# Specify a default error formatter.
3840
def default_error_formatter(new_formatter_name = nil)
39-
return namespace_inheritable(:default_error_formatter) unless new_formatter_name
41+
return inheritable_setting.namespace_inheritable[:default_error_formatter] if new_formatter_name.nil?
4042

4143
new_formatter = Grape::ErrorFormatter.formatter_for(new_formatter_name)
42-
namespace_inheritable(:default_error_formatter, new_formatter)
44+
inheritable_setting.namespace_inheritable[:default_error_formatter] = new_formatter
4345
end
4446

4547
def error_formatter(format, options)
@@ -49,13 +51,13 @@ def error_formatter(format, options)
4951
options
5052
end
5153

52-
namespace_stackable(:error_formatters, format.to_sym => formatter)
54+
inheritable_setting.namespace_stackable[:error_formatters] = { format.to_sym => formatter }
5355
end
5456

5557
# Specify additional content-types, e.g.:
5658
# content_type :xls, 'application/vnd.ms-excel'
5759
def content_type(key, val)
58-
namespace_stackable(:content_types, key.to_sym => val)
60+
inheritable_setting.namespace_stackable[:content_types] = { key.to_sym => val }
5961
end
6062

6163
# All available content types.
@@ -66,7 +68,9 @@ def content_types
6668

6769
# Specify the default status code for errors.
6870
def default_error_status(new_status = nil)
69-
namespace_inheritable(:default_error_status, new_status)
71+
return inheritable_setting.namespace_inheritable[:default_error_status] if new_status.nil?
72+
73+
inheritable_setting.namespace_inheritable[:default_error_status] = new_status
7074
end
7175

7276
# Allows you to rescue certain exceptions that occur to return
@@ -102,12 +106,12 @@ def rescue_from(*args, &block)
102106
handler ||= extract_with(options)
103107

104108
if args.include?(:all)
105-
namespace_inheritable(:rescue_all, true)
106-
namespace_inheritable(:all_rescue_handler, handler)
109+
inheritable_setting.namespace_inheritable[:rescue_all] = true
110+
inheritable_setting.namespace_inheritable[:all_rescue_handler] = handler
107111
elsif args.include?(:grape_exceptions)
108-
namespace_inheritable(:rescue_all, true)
109-
namespace_inheritable(:rescue_grape_exceptions, true)
110-
namespace_inheritable(:grape_exceptions_rescue_handler, handler)
112+
inheritable_setting.namespace_inheritable[:rescue_all] = true
113+
inheritable_setting.namespace_inheritable[:rescue_grape_exceptions] = true
114+
inheritable_setting.namespace_inheritable[:grape_exceptions_rescue_handler] = handler
111115
else
112116
handler_type =
113117
case options[:rescue_subclasses]
@@ -120,7 +124,7 @@ def rescue_from(*args, &block)
120124
inheritable_setting.namespace_reverse_stackable[handler_type] = args.to_h { |arg| [arg, handler] }
121125
end
122126

123-
namespace_stackable(:rescue_options, options)
127+
inheritable_setting.namespace_stackable[:rescue_options] = options
124128
end
125129

126130
# Allows you to specify a default representation entity for a
@@ -146,7 +150,7 @@ def rescue_from(*args, &block)
146150
def represent(model_class, options)
147151
raise Grape::Exceptions::InvalidWithOptionForRepresent.new unless options[:with].is_a?(Class)
148152

149-
namespace_stackable(:representations, model_class => options[:with])
153+
inheritable_setting.namespace_stackable[:representations] = { model_class => options[:with] }
150154
end
151155

152156
private

lib/grape/dsl/routing.rb

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ def version(*args, &block)
3434

3535
if block
3636
within_namespace do
37-
namespace_inheritable(:version, requested_versions)
38-
namespace_inheritable(:version_options, options)
37+
inheritable_setting.namespace_inheritable[:version] = requested_versions
38+
inheritable_setting.namespace_inheritable[:version_options] = options
3939

4040
instance_eval(&block)
4141
end
4242
else
43-
namespace_inheritable(:version, requested_versions)
44-
namespace_inheritable(:version_options, options)
43+
inheritable_setting.namespace_inheritable[:version] = requested_versions
44+
inheritable_setting.namespace_inheritable[:version_options] = options
4545
end
4646
end
4747

@@ -50,7 +50,9 @@ def version(*args, &block)
5050

5151
# Define a root URL prefix for your entire API.
5252
def prefix(prefix = nil)
53-
namespace_inheritable(:root_prefix, prefix&.to_s)
53+
return inheritable_setting.namespace_inheritable[:root_prefix] if prefix.nil?
54+
55+
inheritable_setting.namespace_inheritable[:root_prefix] = prefix.to_s
5456
end
5557

5658
# Create a scope without affecting the URL.
@@ -64,25 +66,29 @@ def scope(_name = nil, &block)
6466
end
6567

6668
def build_with(build_with)
67-
namespace_inheritable(:build_params_with, build_with)
69+
inheritable_setting.namespace_inheritable[:build_params_with] = build_with
6870
end
6971

7072
# Do not route HEAD requests to GET requests automatically.
7173
def do_not_route_head!
72-
namespace_inheritable(:do_not_route_head, true)
74+
inheritable_setting.namespace_inheritable[:do_not_route_head] = true
7375
end
7476

7577
# Do not automatically route OPTIONS.
7678
def do_not_route_options!
77-
namespace_inheritable(:do_not_route_options, true)
79+
inheritable_setting.namespace_inheritable[:do_not_route_options] = true
7880
end
7981

8082
def lint!
81-
namespace_inheritable(:lint, true)
83+
inheritable_setting.namespace_inheritable[:lint] = true
8284
end
8385

8486
def do_not_document!
85-
namespace_inheritable(:do_not_document, true)
87+
inheritable_setting.namespace_inheritable[:do_not_document] = true
88+
end
89+
90+
def do_not_document?
91+
!!inheritable_setting.namespace_inheritable[:do_not_document]
8692
end
8793

8894
def mount(mounts, *opts)
@@ -183,11 +189,11 @@ def route(methods, paths = ['/'], route_options = {}, &block)
183189
# end
184190
# end
185191
def namespace(space = nil, options = {}, &block)
186-
return Namespace.joined_space_path(namespace_stackable(:namespace)) unless space || block
192+
return Namespace.joined_space_path(inheritable_setting.namespace_stackable[:namespace]) unless space || block
187193

188194
within_namespace do
189195
nest(block) do
190-
namespace_stackable(:namespace, Namespace.new(space, options)) if space
196+
inheritable_setting.namespace_stackable[:namespace] = Grape::Namespace.new(space, options) if space
191197
end
192198
end
193199
end
@@ -242,6 +248,35 @@ def refresh_mounted_api(mounts, *opts)
242248
opts << { refresh_already_mounted: true }
243249
mount(mounts, *opts)
244250
end
251+
252+
# Execute first the provided block, then each of the
253+
# block passed in. Allows for simple 'before' setups
254+
# of settings stack pushes.
255+
def nest(*blocks, &block)
256+
blocks.compact!
257+
if blocks.any?
258+
evaluate_as_instance_with_configuration(block) if block
259+
blocks.each { |b| evaluate_as_instance_with_configuration(b) }
260+
reset_validations!
261+
else
262+
instance_eval(&block)
263+
end
264+
end
265+
266+
def evaluate_as_instance_with_configuration(block, lazy: false)
267+
lazy_block = Grape::Util::Lazy::Block.new do |configuration|
268+
value_for_configuration = configuration
269+
self.configuration = value_for_configuration.evaluate if value_for_configuration.try(:lazy?)
270+
response = instance_eval(&block)
271+
self.configuration = value_for_configuration
272+
response
273+
end
274+
if base && base_instance? && lazy
275+
lazy_block
276+
else
277+
lazy_block.evaluate_from(configuration)
278+
end
279+
end
245280
end
246281
end
247282
end

0 commit comments

Comments
 (0)