views:

75

answers:

1

I have a few models that contain static data, and I'm trying to cache them. I've read the various guides and railscasts on caching and thought it would be simple, but still can't figure it out. For example, I have the following model

class ActionType < ActiveRecord::Base

  def self.find(id)
    Rails.cache.fetch(cache_key) { ActionType.find(id) }
  end 

end

But this is creating the following errors:

wrong number of arguments (2 for 1)

with the following stacktrace

C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/belongs_to_association.rb:49:in `find'
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/belongs_to_association.rb:49:in `send'
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/belongs_to_association.rb:49:in `find_target'
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_proxy.rb:240:in `load_target'
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_proxy.rb:112:in `reload'
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations.rb:1219:in `action_type'

I've recently upgraded to Rails 2.3.3 (from 2.0.1) to take advantage of the caching stuff built into the more recent versions.

Also, fyi, most of these models are simple reference tables with an id and description. However, one has 30 columns and 100+ rows, but is still truly static data that I'd like to cache if possible. All of those 30 columns except one are booleans and small integers (that last one is a short string), so it shouldn't take up too much memory.

+1  A: 

One problem here is trying to override ActiveRecord's find method. I would perhaps create a class method called find_cached or something instead.

With that out of the way, where is your cache_key variable coming from? Consider just using the id, something like

class ActionType < ActiveRecord::Base

  def self.find_cached(id)
    Rails.cache.fetch("action_type_cache/#{id}") { ActionType.find(id) }
  end 

end
Ben
I read that cache_key is a method added in rails 2.1 to ActiveRecord::Base for caching. I tried overriding the find method so that the cache would automagically be called instead of a SQL load for other models that have a relationship with ActionType.
Yes, but cache_key is a instance method, not a class method. So every ActiveRecord object has a cache_key, but it doesn't make sense for it to exist for classes.
Ben
I used your code and it worked, except that it still did a query for the columns on ActionType. So I changed it to ActionType.find(id, :select => "id, desc") and it's throwing another error saying the SQL isn't right; very strange
In the development env, Rails doesn't cache info for columns. If you try it in production mode, it will perform the column info query once, and then cache the results.
Ben