我在_profile.html.erb
部分:
<% 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
角色的用户身份登录,然后以具有其他角色的用户身份登录,我看到显示的缓存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 %>
当以管理员用户身份登录为非管理员用户时,它仍然给我相同的缓存结果。
编辑3
以下是cache
块,用于调用调用_profile.html.erb
的集合:
<% 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 %>
答案 0 :(得分:2)
您的父缓存阻止子缓存正确执行其工作。您可以删除父缓存,也可以将其移至顶部,然后每个子项可以分开
将<% 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 %>
答案 1 :(得分:2)
根据rails的文档,您可以简单地将所有依赖项命名为缓存名称。请参阅ActionView::Helpers::CacheHelper#cache
由于您正在嵌套缓存(或称为Russian Doll Caching),因此您需要在outest缓存块中命名嵌套缓存中的所有依赖项。像这样:
<% cache [@profiles, current_user, current_user.roles] do <%>
# ...
<% end %>
查看ActionView::Helpers::CacheHelper#fragment_name_with_digest方法,它只是使用您传入的任何内容来构建缓存名称。因此,您只需要确保任何可能发生变化的内容都包含在任何受影响的缓存块中。
似乎不是这种情况,但只需记住一点,记得在缓存名称中添加一个版本,并在模板发生更改时碰撞版本。您将需要碰撞所有外部块的版本。或者选择使用已经附带Rails 4的cache digest gem。
让我们在这里找出所有变量。您有父视图,它呈现@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
选项。并且“如果您的集合缓存依赖于多个源(尽量避免这样做以保持简单),您可以将所有这些依赖项命名为块的一部分,该块返回一个数组”根据here和here 。
<%= render partial: "profile", collection: profiles, cached: -> profile { [ profile, current_user, current_user.admin?, @selected_profile ] } %>
您不需要在部分中使用另一个缓存块。