2013-07-03 83 views
27

我一直在尝试使用rails的缓存功能,但我无法过期某些缓存片段,虽然它们似乎过期了。使用“俄罗斯套娃缓存”在轨为指出教程网站,我使用这个配置Rails 4.0 expire_fragment/cache过期不起作用

<% cache "all_available_releases" do %> 
<% @releases.each do |release| %> 
    <% cache(release) do %> 
    <html code with> 
    <%ruby code @release.name blah blah blah%> 
    <%end%> 
<%end%> 
<%end%>  

我到期的release_controller.rb控制器,在这里我用expire_fragment(“all_available_releases”)外缓存来到期片段。我用它来更新或删除或添加条目的控制器的每种方法。

这是WEBrick的日志,虽然过期的片段获得注册,但5行后,过期的片段被读取和使用,而不应该。这个例子是在一个销毁电话之后。

Processing by ReleasesController#destroy as HTML 
    Parameters: {"authenticity_token"=>"***/***/********************+********=", "id"=>"2"} 
    Release Load (0.1ms) SELECT "releases".* FROM "releases" WHERE "releases"."id" = ? LIMIT 1 [["id", "2"]] 
    (0.1ms) begin transaction 
    SQL (2.0ms) DELETE FROM "releases" WHERE "releases"."id" = ? [["id", 2]] 
    (148.0ms) commit transaction 
Expire fragment views/all_available_releases (0.1ms) 
Redirected to http://127.0.0.1:3000/releases 
Completed 302 Found in 180ms (ActiveRecord: 150.2ms) 


Started GET "/releases" for 127.0.0.1 at 2013-07-03 13:09:51 +0300 
Processing by ReleasesController#index as HTML 
Read fragment views/all_available_releases/41cb0a928326986f35f41c52bb3d8352 (0.1ms) 
    Rendered releases/index.html.erb within layouts/application (0.6ms) 
Completed 200 OK in 5ms (Views: 4.0ms | ActiveRecord: 0.0ms) 

我甚至使用Rails.cache.delete("all_available_releases")尝试,它也不能工作。

如果我从我的html.erb中删除<%cache "all_available_releases"%>(和一个<%end%>),那么缓存工作正常,只要应该就会过期。

回答

57

我认为问题是,当你在你看来缓存片段缓存摘要被添加到缓存键(视图/ all_available_releases/41cb0a928326986f35f41c52bb3d8352),但expire_fragment未使用摘要(浏览量/ all_available_releases )。

如果您将skip_digest: true添加到视图中的缓存调用,它应该防止使用摘要。

<% cache "all_available_releases", skip_digest: true do %> 
<% @releases.each do |release| %> 
    <% cache(release) do %> 
    <html code with> 
    <%ruby code @release.name blah blah blah%> 
    <%end%> 
<%end%> 
<%end%> 

缓存摘要仅用于自动缓存到期。如果您需要手动过期缓存密钥,则不能使用缓存摘要。

+1

这正是我的问题,谢谢。 –

+0

这给我带来了很多麻烦。谢谢! – Finbarr

+2

谢谢,这是记录在哪里? – bonyiii

4

Jbuilder不支持skip_digest。在经历了许多失败的方法之后,我决定在这里分享我的答案,因为它与高度相关,尽管不是像上述问题那样使用钢轨视图。

下面是一个相关的Q /问题,DHH实质上告诉他他不能明确地过期fragment_caches。 https://github.com/rails/cache_digests/issues/35 一切不成方形所以这里是解决的办法:

class MenuController 
    def index 
    json = Rails.cache.fetch('clients') do 
     @items = Menu.all 
     render_to_string(template: 'menu/index', locals: {items: @items}) 
    end 
    render json: json 
    end 
end 

那么你可以显式地以观察员

class MenuCacheObserver < ActiveRecord::Observer 
    observe :menu, :menuitem, :menusubnavigation 

    def after_save obj 
    Rails.cache.delete(:clients) 
    end 
end 

到期此任何地方,像在少数情况下,这可能是有意义的。一般情况下,在大多数情况下,您应该在缓存输入中使用该对象,如包装jbuilder视图的json.cache! @my_object do。这样,当对象上的updated_at发生变化时,它将会失效。

+0

它看起来像jbuilder现在支持skip_digest(我使用2.4.0) - 以下为我工作 'json.cache! ['v1',my_obj.cache_key],skip_digest:true,expires_in:6.hours do json.partial! 'path/to/my/partial',obj:my_obj end' – MaximusDominus

0

刚刚遇到这个问题我自己和我接触到处理它的方式是通过正则表达式。它可能不是最优雅的解决方案,但它工作正常。

ActionController::Base.new.expire_fragment(%r{offer_#{@offer.id}/*}) 

虽然添加skip_digest更好。

0

在Rails 5中,我采取了以下步骤来破解缓存,而不诉诸于skip_digest: true。我们的问题是,更改I18n字符串的值并不反映在计算出的缓存摘要中,因此缓存不会自动获取。

这里是高速缓存块被定义的视图:

/ views/layouts/_footer.html.slim 
- cache :footer do 
    span= t('shared.footer') 

然后,在轨道控制台I运行:

fragment = ActionController::Base.new.view_context.cache_fragment_name(:footer, virtual_path: 'layouts/_footer.html.slim') 
ActionController::Base.new.expire_fragment(fragment) 

cache_fragment_name将根据virtual_path关键字参数计算出的摘要。