I want my @current_user in my model: A Lesson in Abstraction

This method was adapted from this blog post.

So, you are creating a thing (record) or maybe you are updating it. You’ve added created_by and updated_by fields to your model, and you’ve made these integers with the intention of them both being foreign keys to the Users model.

Maybe you’ve even setup a belongs_to relationsion to your User model like so:

class Thing
 belongs_to :creator, :foreign_key => ‘created_by’, :class_name => ‘User’
 belongs_to :updater, :foreign_key => ‘updated_by’, :class_name => ‘User’

(this way you can refer to thing.creator and thing.updater)

Now, you want to actually set these fields when you create a record or update a record. Problem is, your current_user method is a controller method, and isn’t available in your model layer.

Well, this IS a problem. There are many ways to hack it- but here’s the best approach. I’m going to do this backwards for clarity.

1. Make user_info.rb in your models directory

module UserInfo
 def current_user

 def self.current_user=(user)
  Thread.current[:user] = user

2. Now you need the TrackUsers class, which is real simple. Make another file in your models class called “track_users.rb”. Notice that we’re mixing in the UserInfo module we just created.

module TrackUsers
 # mix me into the OBSERVER for any class you want to set the created_by, updated_by fields
 include UserInfo
 def before_update(record)
  record.updated_by = if current_user
 def before_create(record)
  record.created_by = if current_user

3. Make an observer class for Thing (you can make this in your models folder). Call the file “thing_observer.rb”. Notice that all this basically does is mix in the TrackUsers module.

class ThingObserver < ActiveRecord::Observer
 include TrackUsers

4. Setup an Observer for your (this goes inside the do |config| block)

 config.active_record.observers = [

5. In your ApplicationController add this:

 before_filter :set_user

 # … some more of your code …

 def set_user
  if current_user
   UserInfo.current_user = current_user

Leave a Reply


Your email address will not be published. Required fields are marked *