DEV Community

Jan Peterka
Jan Peterka

Posted on

Managing current user in Rails, our way - part 1

I'm working on ~15 years old Rails application at my $DAYJOB and sometimes (loads of times, actually) there is some quirky code that we are not really happy with these days.

One example which I stumbled across years ago and tried to make sense of (and clean a bit) multiple times, mostly unsuccessfully, was how we manage current user.

You see, in modern Rails apps, this is usually either managed by gems like devise, or using Current attributes, possibly with code from authentication generator introduced in Rails 8.

Not us. We have our custom code that contains some of the oldest code in our project, and which (considering it's authentication) I am pretty afraid to touch.

However, we are slightly getting to somewhat better version of our code, and in this post, I will try to describe our original code, why we wanted to change it and how we did it (or failed to do).

Let's begin.

Part 0 - let's paint a scene

Core of our current user logic are two methods, defined on ApplicationController - current_user and current_user=.
That's not that crazy - if you have experience with devise or similar, that's pretty common thing. Yes, maybe you have log_in instead of current_user=, but well, it's pretty ok.

current_user can have multiple different types:
On the beginning of request (or before first calling current_user or current_user=), it was nil.
Then, it could be set to two values:
1) instance of User
2) value :false

Wait, what? :false? Yeah, weird.
It was the way how to say "we know it's anonymous user", in opposite of nil representing "we just have no idea yet.
So even though te implementation was weird, the general approach of three possible values ("we don't know", "we know they are unknown", "we can link them to our users") made sense and was a starting point for the following changes.

Last thing was that we used was Thread.current (and around it our PORO CurrentThread) to be able to access current user not only from controllers and templates, but also, sparingly, from models or background job.

We had some suspicion it leaks and it brought us some overall doubt about this part of code.

So, after a lot of tinkering, thinking, head scratching and writing and deleting of code, we were able to make some improvements, discover interesting patterns and look into many things Rails does "magically" for us, until it doesn't.

Top comments (0)