

See the codes here: module PerThreadRegistry. The implementation is pretty simple, too. In the example above a key "ActiveRecord::RuntimeRegistry" is stored in Thread.current. This feature is accomplished by instantiating the class and storing the instance as a thread local keyed by the class name. Returns a connection handler local to the current thread. Sets a connection handler local to the current thread, and ActiveRecord :: RuntimeRegistry. We could define a class that extends this module: module ActiveRecord class RuntimeRegistry extend ActiveSupport :: PerThreadRegistry attr_accessor :connection_handler end endĪnd invoke the declared instancec accessors as class methods. Instead of polluting the thread locals namespace: Thread. You don't know what's in your Thread.current, and you're gonna have to read every line of codes with Thread.current.Īnd with these two pains, we may ask: What's the better solution? ActiveSupport::PerThreadRegistryĪctiveSupport::PerThreadRegistry module is used to encapsulate access to thread local variables. Or if you are a gem author, that is really something you need to consider. If the other developer picks the same key with yours, and overwrite it somewhere, you app will just break. Someone could accidentally overwrite your data. store endĬodes of the gem are pretty simple, just insert a middleware to Rails and use Thread.current to store variables, and clear Thread.current after every request.īut with Thread.current(or RequestStore.store), there are two pains may bother you later:ġ. And no matter what server you use, you'll get 1 every time: the storage is local to that request. Everywhere you used Thread.current, just change it to RequestStore.store. Steve Klabnik releases a gem called request_store to do that for you. But if you run it with Thin or Puma, you get 1, then 2, then 3. If we ran this on MRI with Webrick, you'd get 1 as output, every time. For example, if we had this in our controller: def index Thread. If you use Thread.current with fancy evented/threaded web servers like Thin or Puma, please watch out! Values can stick around longer that you'd expect, and this can cause bugs. But if you do use fibers, and want your variables to be thread-local, please use Thread.thread_variable_set and Thread.thread_variable_get. Since we rarely use fibers these days, especially for new 2.x Ruby versions, we could assume this is equal to thread-local. If you read the links of ruby-doc carefully, you may notice that actually the variable is fiber-local instead of thread-local. and Thread.= to get and set thread-local variables, respectively. With Thread.current method, you could get the currently executing thread. Programs that require multiple threads of execution are a perfect candidate for Ruby's Thread class. Threads are the Ruby implementation for a concurrent programming model. So we want our global variables to be thread-safe, a.k.a thread-local. So basically, don't use Ruby native global variables, ever. If you know Ruby well, you may know variable with a beginning with $ is global.īut global variables with $ prefix are supposed to be accessible from every single palce of your code, so they are shared among all threads, and that's definitely not what we want, right? So how could we do that? Ruby Global Variables This is more in line with OO design principles.In a Rails application, sometimes you may wanna use global variables for every request, with which you don't have to send the object as a parameter everywhere, like current_user for model layers (which may not be a good idea). This way the data is available where you need it and you can even alter it if you need to, but the structure of your program and the ownership of the data will be clearer. You can define the method globally, but again, I think it's better to encapsulate it in a module or class. So in this case, you would put all the classes that need the offset in the module Foo and create a constant Offset, so then all the classes could access Foo::Offset.ĭefine a method to access the value. There are two techniques that generally achieve the same purpose that I consider cleaner:Ĭreate a constant in a module. I generally prefer to avoid creating global variables.

When you open a class or method, that's a new scope, and locals available in the previous scope aren't available. Variables starting with $ are global, variables with are instance variables, means class variables, and names starting with a capital letter are constants. Variable scope in Ruby is controlled by sigils to some degree.
