From c8e5b0b53129e378ce18faf73898e5448e73ac81 Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Tue, 9 Jan 2024 16:42:56 -0500 Subject: [PATCH] Avoid definition of methods in `CurrentAttributes` at runtime Replacing on the fly a `method_missing` by a generated method sound like a nice trick, but it's not as good as it sound for optimization, as the method will be generated by the first request to use it, preventing the ISeq from being is shared memory. Instead we can eagerly define a delegator when instance methods are defined, and keep a regular `method_missing + send` for the very rare cases not covered. Co-Authored-By: Jean Boussier --- .../lib/active_support/current_attributes.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/activesupport/lib/active_support/current_attributes.rb b/activesupport/lib/active_support/current_attributes.rb index 9c592a7e2df..0a377bf727a 100644 --- a/activesupport/lib/active_support/current_attributes.rb +++ b/activesupport/lib/active_support/current_attributes.rb @@ -164,16 +164,18 @@ module ActiveSupport end def method_missing(name, ...) - # Caches the method definition as a singleton method of the receiver. - # - # By letting #delegate handle it, we avoid an enclosure that'll capture args. - singleton_class.delegate name, to: :instance - - send(name, ...) + instance.public_send(name, ...) end def respond_to_missing?(name, _) - super || instance.respond_to?(name) + instance.respond_to?(name) || super + end + + def method_added(name) + return if name == :initialize + return unless public_method_defined?(name) + return if respond_to?(name, true) + singleton_class.delegate(name, to: :instance, as: self) end end