Skip to content

Commit a562a50

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 a562a50

28 files changed

+274
-316
lines changed

.rubocop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Style/Send:
3535
Enabled: true
3636

3737
Metrics/AbcSize:
38-
Max: 50
38+
Max: 80 # TODO: revert to 50 once the refactor of public api is done.
3939

4040
Metrics/BlockLength:
4141
Max: 30

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* [#2603](https://github.com/ruby-grape/grape/pull/2603): Remove `namespace_stackable_with_hash` from public interface and move to internal InheritableSetting - [@ericproulx](https://github.com/ericproulx).
2020
* [#2604](https://github.com/ruby-grape/grape/pull/2604): Enable branch coverage - [@ericproulx](https://github.com/ericproulx).
2121
* [#2605](https://github.com/ruby-grape/grape/pull/2605): Add Rack 3.2 support with new gemfile and CI integration - [@ericproulx](https://github.com/ericproulx).
22+
* [#2607](https://github.com/ruby-grape/grape/pull/2607): Remove namespace_stackable and namespace_inheritable from public API - [@ericproulx](https://github.com/ericproulx).
2223
* Your contribution here.
2324

2425
#### Fixes

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

0 commit comments

Comments
 (0)