2014-02-13 88 views
7

只是做一些研究缓存分页集合项目的最佳方式。目前使用jbuilder输出JSON并使用各种cache_key选项播放。Rails缓存分页集合

我见过的最好的例子是使用最新记录的updated_at加上集合中的项目数量。

def cache_key 
     pluck("COUNT(*)", "MAX(updated_at)").flatten.map(&:to_i).join("-") 
end 

定义如下:https://gist.github.com/aaronjensen/6062912

然而,这不适用于分页的项目,在那里我总是在我的收藏10项工作。

这是否有任何解决方法?

回答

9

使用分页集合,你只是得到一个数组。任何尝试修改Array以包含缓存键的尝试都会有点复杂。最好的办法就是使用缓存方法在从收集到收集的基础上生成密钥。

您可以将大量事情传递给缓存方法以生成密钥。如果你每页总有10个项目,我认为这个数字不是很有价值。但是,页码和最后更新的项目将会是。

cache ["v1/items_list/page-#{params[:page]}", @items.maximum('updated_at')] do 

会产生这样

v1/items_list/page-3/20140124164356774568000 

一个缓存键与俄罗斯娃娃缓存,你也应该缓存列表

# index.html.erb 
<%= cache ["v1/items_list/page-#{params[:page]}", @items.maximum('updated_at')] do %> 
    <!-- v1/items_list/page-3/20140124164356774568000 --> 
    <%= render @items %> 
<% end %> 

# _item.html.erb 
<%= cache ['v1', item] do %> 
    <!-- v1/items/15-20140124164356774568000 --> 
    <!-- render item --> 
<% end %> 
+0

您还可以添加一个会话密钥,USER_ID等,哈希键进入摘要。 – aceofspades

+0

如果中间的物品得到更新会怎么样? index.html.erb中的父容器不会知道它是正确的吗? – Jamsi

+0

这是俄罗斯娃娃缓存的一部分。 DHH [在这里谈论它](http://signalvnoise.com/posts/3113-how-key-based-cache-expiration-works)#5。 –

2

缓存分页藏品是棘手的每个项目。使用收集计数和最大updated_at通常的技巧大多不适用!

正如你所说,收集计数是一种给定的如此无用,除非你允许动态的per_page值。

最新的updated_at完全依赖于您的收藏的排序。

想象一下,新的记录被添加,并在第一页结束。这意味着一个记录(以前是第1页)现在进入第2页。一个先前的第2页记录现在变为第3页。如果新的第2页记录最近没有更新过,则缓存键保持不变,但集合不是!记录被删除时也会发生同样的情况。

只有当您可以保证新记录始终在最后一页上结束并且没有记录被删除时,使用最新的updated_at是一个可靠的方法。

作为解决方案,除了页码和per page值之外,还可以在缓存键中包含总记录数和总数最大值updated_at。这将需要额外的查询,但可以值得,这取决于您的数据库配置和记录数量。

另一种解决方案是使用考虑到实际集合内容的一些缩减形式的密钥。例如,也考虑到所有记录ID。

如果你使用postgres作为数据库,这个gem可能会帮助你,虽然我从来没有用过它。 https://github.com/cmer/scope_cache_key

与轨道4叉: https://github.com/joshblour/scope_cache_key