Load a collection once from db, use throughout site
I want to load a collection only once from the db so I don't need to do it on each request or store it in cache.
Where can I do this in Rails 3? At one point in the application start cycle?
Al开发者_运维百科so, how will this collection be made available through the site?
It might be simple enough to have a cached class method. This sort of thing comes in handy for the contents of drop-down lists which changes so infrequently it's as good as static:
class Country
def self.cached_list
@cached_list ||= self.all
end
end
Keep in mind that class instance variables will persist for the life-span of the class itself. In the development environment this is one request, but in production this is all requests made to the same process.
In config/initializers/constants.rb,
you can do this:
SECTOR_NAMES = Sector.all.collect{|sector| sector.name}
and SECTOR_NAMES will be a constant available all throughout your app
You can store it in a class variable in one of your models.
class User < ActiveRecord::Base
cattr_reader :special
@@special = User.where(:special => true).all
...
end
It will be evaluated only during the startup of Rails if you have class caching enabled (and that is the default for production environment).
I use the following:
module ReferenceData
def self.included(model)
model.instance_eval do
def self.find_by_sql(*args)
sql = args.first
ReferenceDataCache.get(sql) || ReferenceDataCache.put(sql, super)
end
end
end
end
class ReferenceDataCache
@@cache = {}
def self.find_by_sql(*args)
sql = args.first
ReferenceDataCache.get(sql) || ReferenceDataCache.put(sql, super)
end
def self.put(sql, obj)
Rails.logger.info "[Caching Reference Data Query] #{sql}"
@@cache[sql] = obj unless obj.empty?
return obj
end
def self.get(sql)
if @@cache.has_key?(sql)
return @@cache[sql]
end
nil
end
end
You can then make any class a reference data class by doing:
class Cities < AR:B
include ReferenceData
end
精彩评论