1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/activesupport/lib/active_support/per_thread_registry.rb
Ryuta Kamizono e0ce6bbd6a Fix kwargs delegation in PerThreadRegistry#method_missing
Without this fix, the delegation will raise the ArgumentError:

```
% bin/test -w test/per_thread_registry_test.rb
Running 1 tests in a single process (parallelization threshold is 50)
Run options: --seed 23992

# Running:

E

Error:
PerThreadRegistryTest#test_method_missing_with_kwargs:
ArgumentError: wrong number of arguments (given 1, expected 0; required keyword: x)
    /Users/kamipo/src/github.com/rails/rails/activesupport/test/per_thread_registry_test.rb:9:in `foo'
    /Users/kamipo/src/github.com/rails/rails/activesupport/lib/active_support/per_thread_registry.rb:55:in `foo'
    /Users/kamipo/src/github.com/rails/rails/activesupport/lib/active_support/per_thread_registry.rb:57:in `method_missing'
    /Users/kamipo/src/github.com/rails/rails/activesupport/test/per_thread_registry_test.rb:13:in `test_method_missing_with_kwargs'
```
2021-08-06 18:24:02 +09:00

61 lines
2 KiB
Ruby

# frozen_string_literal: true
require "active_support/core_ext/module/delegation"
module ActiveSupport
# NOTE: This approach has been deprecated for end-user code in favor of {thread_mattr_accessor}[rdoc-ref:Module#thread_mattr_accessor] and friends.
# Please use that approach instead.
#
# This module is used to encapsulate access to thread local variables.
#
# Instead of polluting the thread locals namespace:
#
# Thread.current[:connection_handler]
#
# you define a class that extends this module:
#
# module ActiveRecord
# class RuntimeRegistry
# extend ActiveSupport::PerThreadRegistry
#
# attr_accessor :connection_handler
# end
# end
#
# and invoke the declared instance accessors as class methods. So
#
# ActiveRecord::RuntimeRegistry.connection_handler = connection_handler
#
# sets a connection handler local to the current thread, and
#
# ActiveRecord::RuntimeRegistry.connection_handler
#
# returns a connection handler local to the current thread.
#
# This feature is accomplished by instantiating the class and storing the
# instance as a thread local keyed by the class name. In the example above
# a key "ActiveRecord::RuntimeRegistry" is stored in <tt>Thread.current</tt>.
# The class methods proxy to said thread local instance.
#
# If the class has an initializer, it must accept no arguments.
module PerThreadRegistry
def self.extended(object)
object.instance_variable_set :@per_thread_registry_key, object.name.freeze
end
def instance
Thread.current[@per_thread_registry_key] ||= new
end
private
def method_missing(name, *args, &block)
# 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, *args, &block)
end
ruby2_keywords(:method_missing)
end
end