为什么此缓存语句不写我期望的密钥



我在 _profile.html.erb partial中有一个:

<% cache [current_user.roles.first, profile, @selected_profile, params[:rating]] do %>

但这是我在服务器日志中看到的:

Read fragment views/profiles/26-20161212033839290582/profiles/52-20161213010040474070/profiles/14-20161213015458288839/profiles/34-20161212035644491093/profiles/33-20161212035644237925/profiles/38-20161207092843851446/profiles/35-20161212040016291016/profiles/36-20161212040016565707/profiles/4-20161213021028862933/profiles/39-20161207092843925084/profiles/46-20161207092844067579/profiles/47-20161207223703646028/profiles/37-20161212040016656625/660bdc6ad0b20e4c5329112cf79946f7 (0.1ms)

我什么都看不到roles

发生的事情是,如果我以admin角色登录使用用户,然后以其他角色登录,我会看到显示的Cached profiles,就像我是管理员一样,而不是其他用户具有正确的视图。

可能导致这一点,我该如何修复?

编辑1

如果将cache语句更改为:

<% cache [current_user, profile, @selected_profile, params[:rating]] do %>

和刷新,这就是日志的样子:

Write fragment views/users/2-20161218005548388099/profiles/37-20161212040016656625///bb163edd4a8c7af2db71a04243338e7b (0.1ms)
  Rendered collection of profiles/_profile.html.erb [1 times] (25.4ms)
Write fragment views/profiles/26-20161212033839290582/profiles/52-20161213010040474070/profiles/14-20161213015458288839/profiles/34-20161212035644491093/profiles/33-20161212035644237925/profiles/38-20161207092843851446/profiles/35-20161212040016291016/profiles/36-20161212040016565707/profiles/4-20161213021028862933/profiles/39-20161207092843925084/profiles/46-20161207092844067579/profiles/47-20161207223703646028/profiles/37-20161212040016656625/83ddeaa031bf68e602ce66af2d268317 (0.1ms)

编辑2

当我 binding.pry进入 _profile.html.erb时,我会得到以下内容:

[3] pry(#<#<Class:0x007f968480ec98>>)> current_user.roles.first
=> #<Role:0x007f969e4422a8 id: 1, name: "admin", resource_id: nil, resource_type: nil, created_at: Mon, 12 Sep 2016 00:38:47 UTC +00:00, updated_at: Mon, 12 Sep 2016 00:38:47 UTC +00:00>

我什至尝试了以下内容:

<% cache [current_user.roles.first.name, profile, @selected_profile, params[:rating]] do %>

,当登录作为非Admin用户与管理用户时,它仍然给我带来相同的缓存结果。

编辑3

这是调用调用_profile.html.erb的集合的cache块:

  <% cache @profiles do %>
    <div class="wrapper wrapper-content">
    <% @profiles.to_a.in_groups_of(3, false).each do |profiles| %>
        <div class="row">
            <%= render partial: "profile", collection: profiles %>
        </div>
    <% end %>
    </div>
  <% end %>

您的父母缓存阻止孩子缓存正确地完成工作。您可以删除父缓存,也可以将其移至顶部,然后每个孩子都可以分开

用:

替换<% cache @profiles do %>
<% cache [current_user.roles.first.try(:name), @profiles, @selected_profile, params[:rating]] do %>

,然后内部_profile.html.erb

<% cache [current_user.roles.first.try(:name), profile, @selected_profile, params[:rating]] do %>

根据Rails的文档,您可以将所有依赖项称为缓存名称。请参阅ActionView :: Helpers :: Cachehelper#Cache

由于您是在嵌套缓存(或称为俄罗斯娃娃缓存),因此您需要在最高的缓存块中命名嵌套缓存中的所有依赖项。这样的东西:

<% cache [@profiles, current_user, current_user.roles] do <%>
  # ...
<% end %>

查看ActionView :: Helpers :: Cachehelper#fragment_name_with_digest方法,它只是使用您传递的任何内容来构建缓存名称。因此,您只需要确保任何可能更改的东西都包含在任何受影响的高速缓存块中。

如果您使用的是Rails 3

似乎并非如此,而是要记住的东西,请记住在缓存名称中添加一个版本,并在模板发生更改时将版本撞到版本。您将需要为所有外部块的版本碰到版本。或选择使用Rails 4。

编辑

让我们在这里确定所有变量。您的父视图呈现@profiles的集合。如果当前用户是管理员,则视图将根据当前用户而改变。在这种情况下,不确定params[:rating]为什么重要。而且我不确定@selected_profile是什么。但我认为应该包括在内。

这是我要做的。

# In User model, add a method to tell if it's an admin
# because "user.roles.first" seems fragile to me. what if the "roles" collection is sorted differently?
def admin?
  roles.where(name: 'admin').present?
end
# In the view
<% cache [@profiles, current_user, current_user.admin?, @selected_profile] do %>
  # ...

渲染集合时,您实际上可以通过cached选项传递。并且"如果您的集合缓存取决于多个来源(尝试避免这种情况以使事情变得简单),则可以将所有这些依赖项命名为返回数组的块的一部分。根据这里和这里。

<%= render partial: "profile", collection: profiles, cached: -> profile { [ profile, current_user, current_user.admin?, @selected_profile ] } %>

,您不需要在部分中有另一个缓存块。

最新更新