Patm
Patm

Reputation: 2075

Caching a model with many associations in Rails

I have a model with about 70 rows that is static(and likely will be forever). The information in this table is used in hundreds of places throughout my site and in my API. It is also associated with several other models that are not so small.

I'm trying to figure out the best way to go about caching this so I can avoid having to go to the DB every time to access it. I've looked at Redis and Memcached and understand how I could use these tools. However, I'm hoping there is a way to do this without having to change all the references to this data (ie - The ActiveRecord calls and associations). What would be my best bet?

Upvotes: 2

Views: 787

Answers (1)

tadman
tadman

Reputation: 211590

A simple way to perform this is to simply cache the results somewhere in your class:

class MyThing < ActiveRecord::Base
  def self.cached_all
    @cached_all ||= self.all
  end
end

The caveat here is that if you do change something you have no way of force-expiring it, so you'll have to restart your server process. For some things this isn't an issue, like lists of countries, time-zones, and so forth, where the rate of change is very limited.

It's probably best if you cache the data in a format suitable for retrieval, such as a Hash indexed by ID, making it easy to use:

class MyThing < ActiveRecord::Base
  def self.cached_all
    @cached_all ||= Hash[self.all.collect { |m| [ m.id, m ] }]
  end
end

For those situations where you need more control over caching, you can go the Memcached route using the Rails.cache facility. It's also worth noting that caching models with a large amount of data you never use is a bad idea, so be sure to keep them slim. Don't load in giant binary attachments, for instance, unless they're required.

Keep in mind there's no magical way to make other models use this cache, so you'll have to refer to it deliberately in each case where you would otherwise bang against the database table. For instance:

def cached_my_thing
  MyThing.cached_all[self.my_thing_id]
end

Upvotes: 1

Related Questions