30

Rails のキャッシング機能を使用しようとしましたが、有効期限が切れているように見えますが、一部のキャッシュ フラグメントを期限切れにすることができません。Railsチュートリアルサイトで指摘されているように「Russian Doll Caching」を使用して、この構成を使用しています

<% 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 行後に期限切れのフラグメントが読み取られ、使用されるべきではないときに使用されます。この例は、destroy 呼び出しの後です。

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"%>(および 1 つを) 削除すると、キャッシングは正常に機能し、必要なときに期限切れになります。<%end%>

4

4 に答える 4

61

ビューにフラグメントをキャッシュすると、キャッシュ ダイジェストがキャッシュ キー (views/all_available_releases/ 41cb0a928326986f35f41c52bb3d8352 ) に追加されますが、expire_fragment はダイジェスト (views/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%>

キャッシュ ダイジェストは、自動キャッシュ期限切れで使用することのみを目的としています。キャッシュ キーを手動で期限切れにする必要がある場合は、キャッシュ ダイジェストを使用できません。

于 2013-07-12T16:18:12.480 に答える
4

Jbuilder は skip_digest をサポートしていません。多くの失敗したアプローチに道を譲った後、上記の問題のようにレールビューではありませんが、関連性が高いため、ここで私の回答を共有することにしました。

これは関連する Q/issue で、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

いくつかのケースでは、これは理にかなっているかもしれません。一般的な注意として、ほとんどの場合json.cache! @my_object do、jbuilder ビューをラップするように、キャッシュ入力でオブジェクトを使用する必要があります。そうすれば、オブジェクトの updated_at が変更されると無効になります。

于 2014-05-21T12:26:15.477 に答える