Rails 5, ability to create module and class level variables on per thread basis
Rails already provides methods for creating class level and module level variables in the form of cattr_* and mattr_* suite of methods.In Rails 5, we can go a step further and create thread specific class or module level variables.Here is an example which demonstrates an example on how to use it.
module CurrentScope thread_mattr_accessor :user_permissions end class ApplicationController < ActionController::Base before_action :set_permissions def set_permissions user = User.find(params[:user_id]) CurrentScope.user_permissions = user.permissions end end
CurrentScope.user_permissions will be available till the lifetime of currently executing thread and all the code after this point can use this variable.
For example, we can access this variable in any of the models without explicitly passing
current_user from the controller.
class BookingsController < ApplicationController def create Booking.create(booking_params) end end class Booking < ApplicationRecord validate :check_permissions private def check_permissions unless CurrentScope.user_permissions.include?(:create_booking) self.errors.add(:base, "Not permitted to allow creation of booking") end end end
It internally uses Thread.current#= method, so all the variables are scoped to the thread currently executing. It will also take care of namespacing these variables per class or module so that
RequestScope.user_permissions will not conflict with each other.
If you have used PerThreadRegistry before for managing global variables, ###code
Globals are generally bad and should be avoided but this change provides nicer API if you want to fiddle with them anyway!