2 ms·
> When experienced programmers utilize global variables whenever it makes sense, it tends to bite future generations. Usually. There is one pattern I keep usi
by kayodelycaon 5y ago
> When experienced programmers utilize global variables whenever it makes sense, it tends to bite future generations.
Usually.
There is one pattern I keep using in Rails to inject the current_user for the request into the model layer. At the beginning of a request, Thread.current[:current_user] gets set to the current_user. At the end of the request, it's cleared.
For those unfamiliar, each Thread has its own Hash object and [] and []= instance methods to access it. It's a way to create global variables scoped to the current thread. To hide this implementation detail, I wrap this functionality in ApplicationRecord.current_user and ApplicationRecord.current_user= methods so no one accidentally uses :curent_user.
The most common use case for this is to automatically set created_by and updated_by on a model, the same way created_at and updated_at are set.
Cron jobs can do something like ApplicationRecord.current_user = User.cron_user if needed. Ideally, I would set this in a CronTask parent class so current_user is always available in the model layer.
I always document these methods and explain exactly what is happening and why. Abstracting away from the implementation detail mitigates most of the problems with a global variable. Obviously, the Thread.current method does not work at all if you're using an event or actor driven architecture. Rails does a thread (or process) per request, so this works extremely well.
- lucumo 5y ago> It's a way to create global variables scoped to the current thread. That's not a global variable; that's a thread-scoped variable. (It's also not (really) mutable. It gets initialized at the start of the scope and gets removed at the end of scope.)