在我的rails 4应用程序中,我尝试使用缓存功能,但由于缓存密钥设置,缓存帮助程序和自动过期的不同版本,我感到有点困惑。
因此,让我通过几个例子来问这个问题。我不会故意将这些例子移到不同的问题上,因为我觉得这样一来任何人都可以一眼就看出细微的差异。
1:侧栏中的最新用户
我想显示最新用户。这当然对应用程序中的所有用户都是相同的,并显示在所有页面上。在railscast中,我看到了一个类似的例子,它通过在控制器中调用expire_fragment...
来过期。但是根据其他资源,当事情发生变化时(例如新用户注册),这应该自动失效。所以我的问题是:我是否正确设置密钥并自动过期?
_sidebar.html.erb(显示在侧边栏的所有页面上)
<% cache 'latest-users' %>
<%= render 'users/user_sidebar' %>
<% end %>
_users_sidebar.html.erb
<% @profiles_sidebar.each do |profile| %>
<%= profile.full_name %>
........
<% end %>
2:产品展示页
我想要显示给定的产品(仅在展会页面上)。对于所有用户来说,这是相同的,但是由于有更多产品,因此有更多版本。问题再次相同:我是否正确设置密钥并自动过期?
products / show.html.erb
<% cache @product %>
<%= @product.name.upcase %>
<%= @product.user.full_name %>
<% end %>
3:产品/索引(用will-paginate gem分页)
在这里,我想立即将所有产品缓存在分页的给定页面上,因此产品会以块的形式缓存。对于所有用户也是如此,并且仅显示在products index page
上。 (稍后我想在此页面上为各个产品实施russian-doll-caching
。)我的问题:我这样做是否正确,是否会自动过期?
产品index.html.erb
<% cache [@products, params[:page]] %>
<%= render @products %>
<% end %>
_product.html.erb
<%= product.name %>
<%= product.user.full_name %>
.....
我试图使用的示例代码(不确定它是否是一个好的代码):
首先是索引页面,没有俄罗斯娃娃。
其次是带有评论的节目页面的俄罗斯娃娃。
答案 0 :(得分:2)
现在让我们讨论这些例子。
cache_key
可以是views/latest-users/7a1156131a6928cb0026877f8b749ac9
,摘要7a11561..
是缓存块文字的MD5。
在这种情况下,只有当您更改模块或此块中的任何内容时,缓存才会过期。
<% cache 'latest-users' do %>
<%= render 'users/user_sidebar' %>
<% end %>
cache_key
可以是views/product/123-20160330214154/9be3eace37fa886b0816f107b581ed67
,请注意缓存是名称空间#{product.to_s}
/ #{product.id}
- #{product.updated_at}
。
在这种情况下,缓存在(1)product.updated_at
更改或(2)缓存块文字更改时到期。
请注意,缓存与id
的不同产品不同。
<% cache @product %>
<%= @product.name.upcase %>
<%= @product.user.full_name %>
<% end %>
cache_key
可能views/product/123-20160330214154/product/456-20160330214154/d5f56b3fdb0dbaf184cc7ff72208195e
对此不确定。但无论如何,应该扩展这样的东西。
在这种情况下,当(1)product-123或product-456发生更改(product.updated_at
已更改)或(2)缓存块文字发生更改时,缓存将过期。
缓存与@products
的{{1}}的不同内容不同,因此无需附加ids
,因为它们不同,它会缓存每个不同的页面params[:page]
内容。
@products
答案 1 :(得分:2)
缓存单个记录和记录集合之间存在很大差异。
您可以通过查看时间戳来简单地判断是否已更改单个记录。默认的cache_key方法的工作方式如下:
Product.new.cache_key # => "products/new" - never expires
Product.find(5).cache_key # => "products/5" (updated_at not available)
Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available)
然而,告诉收集何时陈旧,取决于它的使用方式。
在您的第一个示例中,您只关心created_at
时间戳 - 在其他情况下,您可能希望在更新记录时查看,或者甚至在插入/更新相关记录时。这里没有正确答案。
首先,您将提取按created_at
订购的N个用户:
@noobs = User.order(created_at: :desc).limit(10)
我们可以通过查看集合中的第一个用户来使这里的缓存无效。
<!-- _sidebar.html.erb -->
<% cache(@noobs.first) do %>
<%= render partial: 'users/profile', collection: @noobs %>
<% end %>
我们可以这样做,因为我们知道如果注册了一个新用户,他会将前一个号码撞到一个位置。
然后我们可以使用俄语玩偶缓存来缓存每个用户。请注意,由于partial被称为profile
,因此partial传递了局部变量profile
:
<!-- users/_profile.html.erb -->
<% cache(profile) do %>
<%= profile.full_name %>
<% end %>
是。它将过期。 您可能希望像其他示例一样使用俄语玩偶缓存。
对于分页集合,您可以使用数组中记录的ID来创建缓存键。
编辑。
由于您不希望服务于可能更新的产品的陈旧表示,您还希望在俄语玩偶的“外层”中使用updated_at
作为缓存键。
在这种情况下,完全加载记录是有意义的。您可以忽略我之前关于.ids
。
产品/ index.html.erb:
<% cache([@products.map(&:id), @products.map(&:updated_at).max]) do %>
<%= render @products %>
<% end %>
产品/ _product.html.erb:
<% cache(product) do %>
<%= product.name %>
<% end %>