在我看来,您最好的选择是为每个Show
包含呈现页面所需的所有关系的预取数据的编组对象缓存。我使用 Redis 作为我的缓存,但您也可以使用 Memcache 或类似的东西。
shows = user.tv_shows.map do |show|
if cached_show = $redis.get("shows:#{show.id}")
# use the cached object
Marshal.load(cached_show)
else
# cache has expired or was never created
show.prefetch!
# set the cache for the next visit and have it expire after +TIMEOUT+
$redis.setnx("shows:#{show.id}", TIMEOUT, Marshal.dump(show))
show
end
end
在转储对象之前预取所有关系很重要,否则在解组缓存对象后会访问数据库。
下面是一个预取的例子:
class Show
def prefetch!
@actors ||= actors
self
end
def actors
@actors || 1.upto(10).map do |n|
Actor.new(n)
end
end
end
class Actor
def initialize(n)
puts "initialize actor #{n}"
end
end
show = Show.new.prefetch!
cache = Marshal.dump(show)
Marshal.load(cache).actors.length # uses value stored in @actors
show2 = Show.new
cache2 = Marshal.dump(show2)
Marshal.load(cache2).actors.length # calls database