views:

24

answers:

2

Say I have a system table 'categories' with 2 fixed records. The user will not be allowed to delete these 2 but may wish to add their own to extend their list. I need to be able to pull out the 'garden' category at certain times, e.g when creating a garden project.

A class attribute reader that returns the garden instance would do the job, but I would like to know how this can be improved with caching?

I believe memoization would only work per process which is almost pointless here. I would like it to be set once (perhaps the first time it's accessed or on app start-up) and just remain in cache for future use.

Example setup:

class Project < ActiveRecord::Base
  belongs_to :category
end

class Category < SystemTable
  cattr_reader :garden
  def self.garden
    @@garden ||= self.find_by_name('garden')
  end  
end
+1  A: 

Interlock, a plugin which works with memcached, will automatically cache any instances that are made by a straight 'find' using id. Similarly, you can bypass interlock and just cache the object in memcached manually. Class-level variables is a dirty and potentially bug-causing solution (and i'm not even sure if it works). There's plenty of info on installing and using memcached/memcache-client on the web.

Max Williams
I must say I don't feel particularly comfortable with this approach. I need the categories in the DB and I don't want to rely on knowing the ID of the records. Do you have an idea for an improved approach? I will look at Interlock/memcached. Thanks for your response.
tsdbrown
I've just looked at your post: http://webcrisps.wordpress.com/2010/01/07/dynamically-add-class-methods-in-rails/ Since writing that would you still recommend it as that seems to fit this situation perfectly!? I would just need to add a condition to only pull out the non-customer based records.
tsdbrown
Not really - my approach creates a convenience method but it doesn't cache the result, and so doesn't add any performance. It's just for convenience, ie to save me a bit of typing in my code.
Max Williams
+1  A: 

How about the approach shown below, which will retrieve the garden instance once when the Category class is loaded:

class Category < SystemTable 
  GARDEN = self.find_by_name('garden')
end

Now whenever you need the garden category you can use Category::GARDEN.

John Topley