Wednesday, March 12, 2014

Caching user records when using Authlogic

Today, I ran across another form of this issue with Authlogic. In short, every request in a Rails application using Authlogic with a User model that includes a last_request_at column will cause the updated_at column to change. This can break caching that is based on the last time a user was updated.

last_request_at is one of Authlogic's magic columns and is useful if you want to track users that might be logged in. However, by including this column, every controller request will touch the user record and change updated_at.

If you add last_request_at to your User model, you'll start seeing this in your application logs:

UPDATE "users" SET "last_request_at" = '2014-03-12 20:59:48.314863', "updated_at" = '2014-03-12 20:59:48.320481'

However, if you've added e-tags to a controller based on the updated_at timestamp, you'll now have broken your cache control.  For instance, this will no longer work:


To fix caching based on the User's updated_at timestamp with Authlogic, you can add your own timestamp and maintain it whenever the User record changes. Here is what I came up with:

  1. Add a new column, user_updated_at, to the user model
  2. Whenever a relevant column changes on user, set user_updated_at to Time.now
  3. Change the cache control to be based on user_updated_at instead of updated_at
Here is what that looks like in the User model:


And in the controller:


This made my controller request caching work as expected.  How would you handle this?

1 comment:

  1. There is a 'last_request_update_allowed?' method that Authlogic checks for when setting the 'last_request_at' attribute. You can add a 'last_request_update_allowed?' method to your controller with logic inside to prevent this from happening:

    def last_request_update_allowed?
    action_name != "name_of_action"
    end

    or

    def last_request_update_allowed?
    false
    end

    If you don't want the attribute to be updated for any actions in that controller.

    ReplyDelete