Skip to content

Commit 2d94dd8

Browse files
authored
Reduce object allocation while compiling (#2496)
* Only 1 to_hash to prepare_path * Use inheritable_setting.namespace_stackable and inheritable_setting.namespace_inheritable instead * Use `include` instead of `send(:include)` * Use `include` instead of `send(:include)` * small refactor * Add CHANGELOG entry * Return if helpers.empty? instead. * Update CHANGELOG.md Object allocation instead of just hash
1 parent 1cf4a80 commit 2d94dd8

File tree

7 files changed

+34
-22
lines changed

7 files changed

+34
-22
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* [#2464](https://github.com/ruby-grape/grape/pull/2464): The `length` validator only takes effect for parameters with types that support `#length` method - [@OuYangJinTing](https://github.com/OuYangJinTing).
1717
* [#2485](https://github.com/ruby-grape/grape/pull/2485): Add `is:` param to length validator - [@dakad](https://github.com/dakad).
1818
* [#2492](https://github.com/ruby-grape/grape/pull/2492): Fix `Grape::Endpoint#inspect` method - [@ericproulx](https://github.com/ericproulx).
19+
* [#2496](https://github.com/ruby-grape/grape/pull/2496): Reduce object allocation when compiling - [@ericproulx](https://github.com/ericproulx).
1920
* Your contribution here.
2021

2122
### 2.1.3 (2024-07-13)

lib/grape/dsl/helpers.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,22 @@ module ClassMethods
3333
# end
3434
#
3535
def helpers(*new_modules, &block)
36-
include_new_modules(new_modules) if new_modules.any?
37-
include_block(block) if block
36+
include_new_modules(new_modules)
37+
include_block(block)
3838
include_all_in_scope if !block && new_modules.empty?
3939
end
4040

4141
protected
4242

4343
def include_new_modules(modules)
44+
return if modules.empty?
45+
4446
modules.each { |mod| make_inclusion(mod) }
4547
end
4648

4749
def include_block(block)
50+
return unless block
51+
4852
Module.new.tap do |mod|
4953
make_inclusion(mod) { mod.class_eval(&block) }
5054
end
@@ -58,7 +62,7 @@ def make_inclusion(mod, &block)
5862

5963
def include_all_in_scope
6064
Module.new.tap do |mod|
61-
namespace_stackable(:helpers).each { |mod_to_include| mod.send :include, mod_to_include }
65+
namespace_stackable(:helpers).each { |mod_to_include| mod.include mod_to_include }
6266
change!
6367
end
6468
end

lib/grape/endpoint.rb

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,10 @@ def initialize(new_settings, options = {}, &block)
114114
# Update our settings from a given set of stackable parameters. Used when
115115
# the endpoint's API is mounted under another one.
116116
def inherit_settings(namespace_stackable)
117-
inheritable_setting.route[:saved_validations] += namespace_stackable[:validations]
117+
parent_validations = namespace_stackable[:validations]
118+
inheritable_setting.route[:saved_validations].concat(parent_validations) if parent_validations.any?
118119
parent_declared_params = namespace_stackable[:declared_params]
119-
120-
inheritable_setting.route[:declared_params].concat(parent_declared_params.flatten) if parent_declared_params
120+
inheritable_setting.route[:declared_params].concat(parent_declared_params.flatten) if parent_declared_params.any?
121121

122122
endpoints&.each { |e| e.inherit_settings(namespace_stackable) }
123123
end
@@ -205,7 +205,9 @@ def map_routes
205205
end
206206

207207
def prepare_path(path)
208-
path_settings = inheritable_setting.to_hash[:namespace_stackable].merge(inheritable_setting.to_hash[:namespace_inheritable])
208+
namespace_stackable_hash = inheritable_setting.namespace_stackable.to_hash
209+
namespace_inheritable_hash = inheritable_setting.namespace_inheritable.to_hash
210+
path_settings = namespace_stackable_hash.merge!(namespace_inheritable_hash)
209211
Path.new(path, namespace, path_settings)
210212
end
211213

@@ -288,19 +290,22 @@ def run
288290
def build_stack(helpers)
289291
stack = Grape::Middleware::Stack.new
290292

293+
content_types = namespace_stackable_with_hash(:content_types)
294+
format = namespace_inheritable(:format)
295+
291296
stack.use Rack::Head
292297
stack.use Class.new(Grape::Middleware::Error),
293298
helpers: helpers,
294-
format: namespace_inheritable(:format),
295-
content_types: namespace_stackable_with_hash(:content_types),
299+
format: format,
300+
content_types: content_types,
296301
default_status: namespace_inheritable(:default_error_status),
297302
rescue_all: namespace_inheritable(:rescue_all),
298303
rescue_grape_exceptions: namespace_inheritable(:rescue_grape_exceptions),
299304
default_error_formatter: namespace_inheritable(:default_error_formatter),
300305
error_formatters: namespace_stackable_with_hash(:error_formatters),
301-
rescue_options: namespace_stackable_with_hash(:rescue_options) || {},
302-
rescue_handlers: namespace_reverse_stackable_with_hash(:rescue_handlers) || {},
303-
base_only_rescue_handlers: namespace_stackable_with_hash(:base_only_rescue_handlers) || {},
306+
rescue_options: namespace_stackable_with_hash(:rescue_options),
307+
rescue_handlers: namespace_reverse_stackable_with_hash(:rescue_handlers),
308+
base_only_rescue_handlers: namespace_stackable_with_hash(:base_only_rescue_handlers),
304309
all_rescue_handler: namespace_inheritable(:all_rescue_handler),
305310
grape_exceptions_rescue_handler: namespace_inheritable(:grape_exceptions_rescue_handler)
306311

@@ -315,9 +320,9 @@ def build_stack(helpers)
315320
end
316321

317322
stack.use Grape::Middleware::Formatter,
318-
format: namespace_inheritable(:format),
323+
format: format,
319324
default_format: namespace_inheritable(:default_format) || :txt,
320-
content_types: namespace_stackable_with_hash(:content_types),
325+
content_types: content_types,
321326
formatters: namespace_stackable_with_hash(:formatters),
322327
parsers: namespace_stackable_with_hash(:parsers)
323328

@@ -328,7 +333,9 @@ def build_stack(helpers)
328333

329334
def build_helpers
330335
helpers = namespace_stackable(:helpers)
331-
Module.new { helpers&.each { |mod_to_include| include mod_to_include } }
336+
return if helpers.empty?
337+
338+
Module.new { helpers.each { |mod_to_include| include mod_to_include } }
332339
end
333340

334341
private :build_stack, :build_helpers
@@ -347,7 +354,7 @@ def lazy_initialize!
347354
@lazy_initialize_lock.synchronize do
348355
return true if @lazy_initialized
349356

350-
@helpers = build_helpers.tap { |mod| self.class.send(:include, mod) }
357+
@helpers = build_helpers&.tap { |mod| self.class.include mod }
351358
@app = options[:app] || build_stack(@helpers)
352359

353360
@lazy_initialized = true

lib/grape/middleware/error.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def default_options
2626

2727
def initialize(app, *options)
2828
super
29-
self.class.send(:include, @options[:helpers]) if @options[:helpers]
29+
self.class.include(@options[:helpers]) if @options[:helpers]
3030
end
3131

3232
def call!(env)
@@ -79,15 +79,15 @@ def default_rescue_handler(exception)
7979
end
8080

8181
def rescue_handler_for_base_only_class(klass)
82-
error, handler = options[:base_only_rescue_handlers].find { |err, _handler| klass == err }
82+
error, handler = options[:base_only_rescue_handlers]&.find { |err, _handler| klass == err }
8383

8484
return unless error
8585

8686
handler || method(:default_rescue_handler)
8787
end
8888

8989
def rescue_handler_for_class_or_its_ancestor(klass)
90-
error, handler = options[:rescue_handlers].find { |err, _handler| klass <= err }
90+
error, handler = options[:rescue_handlers]&.find { |err, _handler| klass <= err }
9191

9292
return unless error
9393

spec/grape/extensions/param_builders/hash_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def app
2929

3030
describe 'in an api' do
3131
before do
32-
subject.send(:include, Grape::Extensions::Hash::ParamBuilder) # rubocop:disable RSpec/DescribedClass
32+
subject.include Grape::Extensions::Hash::ParamBuilder # rubocop:disable RSpec/DescribedClass
3333
end
3434

3535
describe '#params' do

spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def app
2929

3030
describe 'in an api' do
3131
before do
32-
subject.send(:include, Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder) # rubocop:disable RSpec/DescribedClass
32+
subject.include Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder # rubocop:disable RSpec/DescribedClass
3333
end
3434

3535
describe '#params' do

spec/integration/hashie/hashie_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
describe 'in an api' do
3030
before do
31-
subject.send(:include, Grape::Extensions::Hashie::Mash::ParamBuilder)
31+
subject.include Grape::Extensions::Hashie::Mash::ParamBuilder
3232
end
3333

3434
describe '#params' do

0 commit comments

Comments
 (0)