Rails 4.0 expire_fragment / cache expiration non funziona

Ho cercato di utilizzare le funzionalità di cache dei binari, ma non riesco a espirare alcuni frammenti di cache sebbene sembrino scadere. Usando il ‘Russian Doll Caching’ come indicato nel sito del tutorial sui binari, sto usando questa configurazione

        

Scaduto la cache esterna nel controller release_controller.rb, dove uso expire_fragment (“all_available_releases”) per far scadere il frammento. Lo uso in ogni metodo del controller che aggiorna o cancella o aggiunge una voce.

Questo è il log di WEBrick, dove sebbene il frammento di scadenza venga registrato, 5 righe dopo il frammento scaduto vengono lette e usate mentre non dovrebbe. Questo esempio è dopo una chiamata di distruzione.

 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) 

Ho anche provato a utilizzare Rails.cache.delete("all_available_releases") e non ha funzionato neanche.

se cancello (e uno ) dal mio html.erb il caching funziona bene e diventa scaduto ogni volta che dovrebbe.

Credo che il problema è che quando si memorizza nella cache il frammento nella vista, un sumrio della cache viene aggiunto alla chiave di cache (views / all_available_releases / 41cb0a928326986f35f41c52bb3d8352 ), ma expire_fragment non sta usando il digest (views / all_available_releases).

Se si aggiunge skip_digest: true alla chiamata della cache nella vista, si dovrebbe impedire l’utilizzo del digest.

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

I digest di cache sono pensati solo per essere utilizzati con la scadenza automatica della cache. Se è necessario scadere manualmente le chiavi della cache, non è ansible utilizzare i caching della cache.

Jbuilder non supporta skip_digest. Dopo aver percorso molti approcci falliti, ho deciso di condividere le mie risposte in quanto è strettamente correlato, anche se non con una visualizzazione di binari come è il problema sopra.

Ecco un Q / problema correlato in cui DHH essenzialmente dice al ragazzo che non può espirare fragment_caches in modo esplicito. https://github.com/rails/cache_digests/issues/35 Tutto non è quadrato, quindi ecco un modo per aggirare questo:

 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 

quindi puoi explictly espirarlo ovunque, come in un osservatore

 class MenuCacheObserver < ActiveRecord::Observer observe :menu, :menuitem, :menusubnavigation def after_save obj Rails.cache.delete(:clients) end end 

In alcuni casi ciò può avere senso. In generale, nella maggior parte dei casi dovresti usare l'object nell'input della cache, come json.cache! @my_object do json.cache! @my_object do wrapping della vista di jbuilder. In questo modo invaliderebbe quando update_at sull'object cambia.

Mi sono imbattuto in questo problema e il modo in cui mi sono avvicinato era attraverso le espressioni regolari. Potrebbe non essere la soluzione più elegante ma funziona bene.

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

Aggiungere la skip_digest è molto più carino.

In Rails 5 ho skip_digest: true i seguenti passaggi per skip_digest: true la cache senza ricorrere a skip_digest: true . Il nostro problema era che la modifica del valore delle stringhe I18n non si rifletteva nel digest della cache calcolato, in modo che la cache non venisse automaticamente eliminata.

Ecco la vista in cui è definito il blocco della cache:

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

Quindi nella console di rails eseguo:

 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 individuerà il digest in base all’argomento della parola chiave virtual_path .