Rails 4.0 истекает срок действия фрагмента / кэша не работает
Я пытался использовать возможности кэширования rails, но я не могу истечь некоторый фрагмент кэша, хотя они, кажется, истекают. Используя "кэширование русской куклы" , как указано на сайте учебника rails, я использую эту конфигурацию
<% 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.контроллер РБ, где я использую 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")
и это тоже не сработало.
если я удалить <%cache "all_available_releases"%>
(один <%end%>
) из моего html.erb кэширование работает нормально и истекает, когда это необходимо.
4 ответов
Я считаю, что проблема в том, что когда вы кэшируете фрагмент в своем представлении, дайджест кэша добавляется в ключ кэша (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%>
кэш сборники предназначены только для использования с автоматическим кешем выдыхание. Если вам нужно вручную истечь ключи кэша, вы не можете использовать дайджесты кэша.
Jbuilder не поддерживает skip_digest. После многих неудачных подходов я решил поделиться своими ответами здесь, поскольку это очень связано, хотя и не с представлением rails, как проблема выше.
вот связанный вопрос 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
тогда вы можете объяснить истекает это где угодно, как в observer
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 объекта.
просто столкнулся с этой проблемой сам, и то, как я подошел к ее решению, было через регулярные выражения. Это может быть не самое элегантное решение, но работает нормально.
ActionController::Base.new.expire_fragment(%r{offer_#{@offer.id}/*})
добавление skip_digest намного приятнее.
в Rails 5 я сделал следующие шаги, чтобы разбить кэш, не прибегая к skip_digest: true
. Наша проблема заключалась в том, что изменение значения строк I18n не отражается в вычисляемом дайджесте кэша, поэтому кэш не будет автоматически разорен.
вот представление, в котором определен блок кэша:
/ views/layouts/_footer.html.slim
- cache :footer do
span= t('shared.footer')
затем в консоли rails я запускаю:
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
аргумент сайта.