私の意見では、あなたの最善の策は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