ActiveRecord: Understanding CurrentAttributes

current_user is a daily companion in Controllers and Views. However, the moment you need that information inside a Model to validate a business rule, things get tricky. Many developers end up passing the user as a parameter everywhere. But did you know Rails has a native solution for this?

CurrentAttributes is the official bridge to carry context from the Controller to the Model cleanly and safely.

The Problem: Argument Pollution

Imagine a method in your model that checks if a user can edit a record. Currently, it likely needs to receive the user as an argument:

1
2
3
def editable_by?(user)
  self.author == user || user.admin?
end

While this works, if you have a call chain (Controller -> Service -> Model), you are forced to “carry” that user all the way down. This pollutes your method signatures and makes the code more rigid and harder to read.

The Solution: Centralizing Context

CurrentAttributes allows you to create a central repository for the request. Instead of passing the user manually, your Model simply asks Rails: “Who is the user right now?”.

How it transforms the code:

  1. Setup (app/models/current.rb):
    1
    2
    3
    
    class Current < ActiveSupport::CurrentAttributes
      attribute :user
    end
    
  2. In the Controller: You set the value once at the beginning of the request.
    1
    
    Current.user = current_user # The user coming from your authentication system
    
  3. In the Model: The method becomes much cleaner.
    1
    2
    3
    
    def can_be_edited?
      self.author == Current.user || Current.user.admin?
    end
    

Behind the Scenes: Thread Isolation

The most common concern is: “Is this safe? Won’t one user see another’s data?”. The answer is no.

Rails uses what is called Thread Isolation. Every request on your server runs in its own “bubble” (thread). Rails ensures that Current.user in Thread A never leaks into Thread B. Furthermore, at the end of every request, Rails automatically wipes (resets) this object, ensuring the next visitor starts with a clean slate.

Why It Matters