Подтвердить что ты не робот

Rails 4.0 expire_fragment/cache expiration не работает

Я пытаюсь использовать возможности кэширования рельсов, но я не могу закончить некоторые фрагменты кеша, хотя они, похоже, истекли. Используя "Russian Caching 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, где, хотя фрагмент expire регистрируется, 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, кеширование прекратится и истекает всякий раз, когда это необходимо.

4b9b3361

Ответ 1

Я считаю, что проблема заключается в том, что при кэшировании фрагмента в вашем представлении кэш-ключ добавляется кэш файл (views/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%>

Сборники кэша предназначены только для использования с автоматическим истечением срока действия кеша. Если вам нужно вручную истечь ключей кеша, вы не можете использовать дайджесты кэша.

Ответ 2

Jbuilder не поддерживает skip_digest. После многих неудачных подходов я решил поделиться своими ответами здесь, поскольку он очень связан, хотя и не с просмотром рельсов, как это было выше.

Вот связанный вопрос Q/, в котором DHH по существу говорит парню, что он не может истекать явно. 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. Таким образом, это приведет к недействительности при изменении update_at на объекте.

Ответ 3

Просто наткнулся на эту проблему сам и способ, которым я обращался к этому, заключался в регулярных выражениях. Это может быть не самое элегантное решение, но оно отлично работает.

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

Добавление skip_digest намного приятнее.

Ответ 4

В 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.