Cache your partials, not the other way around.
It might seem nice and tidy to do this:
# items/index.json.jbuilder
json.items @items do
json.partial! "item", item: item
end
# items/show.json.jbuilder
json.item do
json.partial! "item", item: @item
end
# items/_items.json.jbuilder
json.cache! item do
json(item, :id, :name, ...)
end
The templates are DRY and things are organized.
But tucking the call to cache! into the _item partial is a performance hit. Consider:
# items/index.json.jbuilder
json.items @items do
json.cache! item do
json.partial! "item", item: item
end
end
# items/show.json.jbuilder
json.item do
json.cache! item do
json.partial! "item", item: @item
end
end
# items/_items.json.jbuilder
json(item, :id, :name, ...)
While slightly more repetitive, this structure saves the calls to partial! once the cache is warm. Loading a partial isn't free, and the time it takes to load one up adds up when aggregated over x items per request, and y requests per minute.
Written by Kamil Tusznio
Related protips
4 Responses
I'd love your feedback on this: https://github.com/joshblour/jbuilder_cache_multi
it uses fetch_multi in rails 4 to read all keys at once from the cache.
At first I was doing it the first way you described, then the second way, then I wrote this plugin to make it even faster.
Hey, that seems like a nice approach! Does it work with Rails 3?
It does! The thing is that Rails 3 doesn't give you a fetch_multi method, so it's up to whichever cache you are using to implement it. If the method doesn't exist, the gem will fall back on iterating over the collection (the second way you describe) so it becomes more of a convenience method than anything else :)
Thanks for pointing this out. I think the |item|
block parameter is missing in your examples though.