Rails 4.0.0.0 Russian Doll Caching with belongs_to model
Asked Answered
C

1

6

I have set up a cache in my model like

def self.latest(shop_id)
    Inventory.where(:shop_id => shop_id).order(:updated_at).last
end

and in my view

<% cache ['inventories', Inventory.latest(session[:shop_id])] do %>

   <% @inventories.each do |inventory| %>

      <% cache ['entry', inventory] do %>     

     <li><%= link_to inventory.item_name, inventory %></li>

So, here I can have many shops, each with an inventory of stock items. Will the above cache work at all for different shops?

I think it's possible that even displaying the view in a different shop will break the cache. Or, any shop adding an inventory item will break the cache.

Can I use Russian Doll caching like this or do I need to use Inventory.all in my model?

Caricaria answered 3/7, 2013 at 6:54 Comment(0)
G
3

Your idea is close, but you need to include the shop_id, the count, and the maximum updated_at of each shop's inventory into your cache key. Your outer cache needs to get busted when a shop's item gets deleted too, and that isn't covered under a max id or updated_at alone.

You can expand your custom cache key helper method to make this work. This allows you to create unique top level caches that only get busted when a member of that set gets added, updated or deleted. In effect, this gives a unique outer cache for each shop_id. Thus when one shop's inventory is changed, it doesn't affect another shop's cache.

Here is an example, based on ideas in the edge rails documentation:

module InventoriesHelper
  def cache_key_for_inventories(shop_id)
    count          = Inventory.where(:shop_id => shop_id).count
    max_updated_at = Inventory.where(:shop_id => shop_id).maximum(:updated_at).try(:utc).try(:to_s, :number)
    "inventories/#{shop_id}-#{count}-#{max_updated_at}"
  end
end

Then in your view:

<% cache(cache_key_for_inventories(session[:shop_id])) do %>
  ...
<% end %>
Goshawk answered 23/7, 2013 at 22:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.