2013-07-03 16 views
27

私はrailsのキャッシュ機能を使用しようとしていますが、有効期限が切れていますが、一部のキャッシュフラグメントを期限切れにできません。に私はexpire_fragment(「all_available_releases」)を使用しrelease_controller.rbコントローラ、外側のキャッシュを期限切れに「ロシア人形のキャッシング」などのレールチュートリアルサイトで指摘を使用して、私はこの構成にRails 4.0 expire_fragment/cache expiration not working

<% 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%>  

を使用していますフラグメントを期限切れにする。私はエントリを更新または削除または追加するコントローラのすべてのメソッドでこれを使用します。

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")を使用してみました、それはどちらか動作しませんでした。

<%cache "all_available_releases"%>(と1つは<%end%>)を私のhtml.erbから削除すると、キャッシュはうまく動作し、いつでも期限切れになります。

答えて

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をサポートしていません。多くの失敗したアプローチへの道をたどった後、私はここで私の答えを共有することを決めました。

ここで、DHHは本質的に、彼がfragment_cachesを明示的に期限切れにできないことを男に知らせる関連Q/issueです。 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 

オブザーバーで、これは意味を行うことができるように、あなたは明示的に、このどこかを期限切れにすることができます。一般的な注意点として、ほとんどの場合、キャッシュ入力にオブジェクトを使用する必要があります。たとえば、json.cache! @my_object doはjbuilderビューをラップします。そうすれば、オブジェクトの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') 

は、次にレールコンソールで私が実行します。

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

cache_fragment_namevirtual_pathキーワード引数に基づいてダイジェストを把握します。