Disabling ActiveRecord query caching when needed

Posted by Luke Francl
on Monday, August 18

In Rails 2.0 and later, all requests are wrapped in a block that enables query caching.

What this means is that if you execute the exact same query in a single request, the previous results of the query will be returned instead of fetching them from the database again.

Controller actions are wrapped with this automatically, but you can also enable it elsewhere like this:

1
2
3
User.cache do
  # do stuff with caching turned on.
end

However, sometimes you do not want this to happen. For example, if you want to fetch random records from the database, having this cached will cause you to get the same record each time you query.

Fortunately, the cache is easy to disable for parts of your code, with the uncached method (see also):

1
2
3
4
5
6
7
8
9
10
class User < ActiveRecord::Base
  def self.random
    # query for example purposes only -- 
    # ordering by rand() is slow, see here: 
    # http://jan.kneschke.de/projects/mysql/order-by-rand
    uncached do 
      find(:first, :order => "rand()") 
    end
  end
end

Disabling the cache only affects the code within the block, so unlike clearing the cache (which would also work) the rest of your code will still get the benefit of the query cache.

Comments

Leave a response

  1. Pete SchwambAugust 20, 2008 @ 02:10 PM

    Thanks Luke… I just hit a bug caused by sql query caching (select nextval(some_seq)) in my code, and wasn’t sure how to turn it off.

  2. Luke FranclAugust 20, 2008 @ 05:58 PM

    Another good case when you’d need to use this! Glad it helped, Pete.

  3. vestersSeptember 11, 2008 @ 04:18 PM

    Hey Luke.

    Thanks for a great tip – you really helped me out.

    I love that people like you take the time to write these things down so others can gain from it.

    Cheers!

  4. Luke FranclSeptember 12, 2008 @ 12:30 PM

    Thanks vesters!