在研究了DHH和其他关于基于密钥的缓存过期和俄罗斯娃娃缓存的博客文章之后,我仍然不确定如何处理一种关系类型.具体来说,是一种has_many
关系.
我将分享我对示例应用程序的研究结果.这是一个故事讲述,所以坚持下去.假设我们有以下ActiveRecord模型.我们所关心的只是模型的正确改变cache_key
,对吗?
class Article < ActiveRecord::Base
attr_accessible :author_id, :body, :title
has_many :comments
belongs_to :author
end
class Comment < ActiveRecord::Base
attr_accessible :article_id, :author_id, :body
belongs_to :author
belongs_to :article, touch: true
end
class Author < ActiveRecord::Base
attr_accessible :name
has_many :articles
has_many :comments
end
Run Code Online (Sandbox Code Playgroud)
我们已经有一篇文章,只有一条评论.两者都是由不同的作者.目标是cache_key
在以下情况下对文章进行更改:
因此,默认情况下,我们对案例1和案例2都有好处.
1.9.3-p194 :034 > article.cache_key
=> "articles/1-20130412185804"
1.9.3-p194 :035 > article.comments.first.update_attribute('body', 'First Post!')
1.9.3-p194 :038 > article.cache_key
=> "articles/1-20130412185913"
Run Code Online (Sandbox Code Playgroud)
但不是案例3.
1.9.3-p194 :040 > article.author.update_attribute('name', 'Adam A.')
1.9.3-p194 :041 …
Run Code Online (Sandbox Code Playgroud) ruby caching ruby-on-rails fragment-caching russian-doll-caching
只是对缓存分页项目集合的最佳方法进行一些研究.目前使用jbuilder输出JSON并且一直在玩各种cache_key选项.
我见过的最好的例子是使用最新记录的updated_at加上集合中的项目数量.
def cache_key
pluck("COUNT(*)", "MAX(updated_at)").flatten.map(&:to_i).join("-")
end
Run Code Online (Sandbox Code Playgroud)
这里定义:https://gist.github.com/aaronjensen/6062912
但是这不适用于分页项目,我的集合中总共有10个项目.
这有什么变通方法吗?
我在我的模型中设置了一个缓存
def self.latest(shop_id)
Inventory.where(:shop_id => shop_id).order(:updated_at).last
end
Run Code Online (Sandbox Code Playgroud)
在我看来
<% cache ['inventories', Inventory.latest(session[:shop_id])] do %>
<% @inventories.each do |inventory| %>
<% cache ['entry', inventory] do %>
<li><%= link_to inventory.item_name, inventory %></li>
Run Code Online (Sandbox Code Playgroud)
所以,在这里我可以有很多商店,每个商店都有库存商品库存.以上缓存是否适用于不同的商店?
我认为即使在不同的商店中显示视图也可能会破坏缓存.或者,任何添加库存项目的商店都会破坏缓存.
我可以像这样使用俄罗斯娃娃缓存,还是需要在我的模型中使用Inventory.all?
根据我对Rails中俄罗斯娃娃缓存的理解,当我们进行RDC(俄罗斯娃娃缓存)时,这对于急切的加载相关对象或对象列表是有害的,因为在RDC中我们只是从数据库加载顶级对象,并查找它缓存渲染的模板和服务.如果我们要急切加载相关的对象列表,如果缓存不是陈旧的话,这将是无用的.
我的理解是否正确?如果是,我们如何确保我们在第一次调用时急切加载所有相关对象,以免在第一次加载(缓存不热)时支付N + 1个查询的成本.
caching ruby-on-rails ruby-on-rails-3 russian-doll-caching cache-digests
我有一个Profile#Index
视图,我在这里渲染部分如此:
<% 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, cached: true %>
</div>
<% end %>
</div>
<% end %>
Run Code Online (Sandbox Code Playgroud)
但在我看来app/views/profiles/_profile.html.erb
,我有以下几点:
<% cache profile do %>
<% elsif current_user.has_role?(:coach) && params[:rating].present? %>
<div class="contact-box-footer">
<div class="row text-center avg-ratings">
<div class="col-lg-3">
<span class="label label-success">Speed: <%= profile.ratings.find_by(user: current_user).speed %></span>
</div>
<div class="col-lg-3">
<span class="label label-info tackling">Tackling: <%= profile.ratings.find_by(user: current_user).tackling %></span>
</div>
</div>
</div>
<% …
Run Code Online (Sandbox Code Playgroud) 我有_profile.html.erb
部分内容:
<% cache [current_user.roles.first, profile, @selected_profile, params[:rating]] do %>
Run Code Online (Sandbox Code Playgroud)
然而,这是我在服务器日志中看到的:
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)
Run Code Online (Sandbox Code Playgroud)
我什么roles
也没看到.
发生的事情是,如果我以具有admin
角色的用户身份登录,然后以具有其他角色的用户身份登录,我看到profiles
显示的缓存就像我是管理员而不是具有正确视图的其他用户.
可能导致这种情况的原因以及如何解决?
编辑1
如果我将cache
语句更改为:
<% cache [current_user, profile, @selected_profile, params[:rating]] do %>
Run Code Online (Sandbox Code Playgroud)
并刷新,这是日志的样子:
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)
Run Code Online (Sandbox Code Playgroud)
编辑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, …
Run Code Online (Sandbox Code Playgroud)