module ActiveSupport # 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 Thread.current. # The class methods proxy to said thread local instance. # # If the class has an initializer, it must accept no arguments. module PerThreadRegistry protected def method_missing(name, *args, &block) # :nodoc: # Caches the method definition as a singleton method of the receiver. singleton_class.class_eval do define_method(name) do |*a, &b| per_thread_registry_instance.public_send(name, *a, &b) end end send(name, *args, &block) end private def per_thread_registry_instance Thread.current[name] ||= new end end end