Spec-Zone.ru › Ruby on Rails 6.0

модуль ActionView::Helpers::CacheHelper

Публичные методы экземпляра

cache(name = {}, options = {}) { || ... } Показать исходный код
# File actionview/lib/action_view/helpers/cache_helper.rb, line 166
def cache(name = {}, options = {}, &block)
  if controller.respond_to?(:perform_caching) && controller.perform_caching
    name_options = options.slice(:skip_digest, :virtual_path)
    safe_concat(fragment_for(cache_fragment_name(name, name_options), options, &block))
  else
    yield
  end

  nil
end

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

Лучший способ использования — это использование кэширования с истечением срока действия на основе ключей в сочетании с хранилищем кэша, таким как Memcached или Redis, которое автоматически удаляет устаревшие записи.

При использовании этого метода укажите зависимость кэша как имя кэша, например:

<% cache project do %>
  <b>All the topics on this project</b>
  <%= render project.topics %>
<% end %>

Этот подход предполагает, что при добавлении новой темы вы будете обновлять проект. Ключ кэша, сгенерированный этим вызовом, будет чем-то вроде:

views/template/action.html.erb:7a1156131a6928cb0026877f8b749ac9/projects/123
      ^template path           ^template tree digest            ^class   ^id

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

Если кэш вашего шаблона зависит от нескольких источников (старайтесь избегать этого, чтобы всё было проще), вы можете указать все эти зависимости в качестве элементов массива:

<% cache [ project, current_user ] do %>
  <b>All the topics on this project</b>
  <%= render project.topics %>
<% end %>

Это включит обе записи в ключ кэша, и обновление любой из них приведёт к истечению срока действия кэша.

Хеш шаблона

Хеш шаблона, который добавляется к ключу кэша, вычисляется путём взятия MD5 от содержимого всего файла шаблона. Это гарантирует, что ваши кэши автоматически истекают при изменении файла шаблона.

Обратите внимание, что MD5 вычисляется для всего файла шаблона, а не только для того, что находится внутри вызова do/end кэша. Поэтому возможно, что изменение чего-либо вне этого вызова всё равно приведёт к истечению срока действия кэша.

Кроме того, инструмент вычисления хеша автоматически просмотрит ваш файл шаблона в поисках явных и неявных зависимостей и включит их в хеш.

Инструмент вычисления хеша можно пропустить, передав skip_digest: true в качестве параметра в вызов cache:

<% cache project, skip_digest: true do %>
  <b>All the topics on this project</b>
  <%= render project.topics %>
<% end %>

Неявные зависимости

Большинство зависимостей шаблонов можно вывести из вызовов render в самом шаблоне. Вот несколько примеров вызовов render, которые Cache Digests умеет декодировать:

render partial: "comments/comment", collection: commentable.comments
render "comments/comments"
render 'comments/comments'
render('comments/comments')

render "header" translates to render("comments/header")

render(@topic)         translates to render("topics/topic")
render(topics)         translates to render("topics/topic")
render(message.topics) translates to render("topics/topic")

Однако не все вызовы render можно вывести таким образом. Вот несколько примеров того, что нельзя вывести:

render group_of_attachments
render @project.documents.where(published: true).order('created_at')

Вам придётся переписать их в явном виде:

render partial: 'attachments/attachment', collection: group_of_attachments
render partial: 'documents/document', collection: @project.documents.where(published: true).order('created_at')

Явные зависимости

Иногда у вас будут зависимости шаблонов, которые вообще нельзя вывести. Это обычно случается, когда у вас есть отрисовка шаблонов, которая происходит в помощниках. Вот пример:

<%= render_sortable_todolists @project.todolists %>

Вам нужно будет использовать специальный формат комментариев для вызова этих зависимостей:

<%# Template Dependency: todolists/todolist %>
<%= render_sortable_todolists @project.todolists %>

В некоторых случаях, например, при настройке единого наследования таблиц, у вас может быть много явных зависимостей. Вместо написания каждого шаблона вы можете использовать символ подстановки для соответствия любому шаблону в каталоге:

<%# Template Dependency: events/* %>
<%= render_categorizable_events @person.events %>

Это отмечает каждый шаблон в каталоге как зависимость. Для поиска этих шаблонов путь с символом подстановки должен быть абсолютным от app/views или путей, добавленных другими способами с использованием prepend_view_path или append_view_path. Таким образом, символ подстановки для app/views/recordings/events будет recordings/events/* и т. д.

Шаблон, используемый для сопоставления явных зависимостей, — /# Template Dependency: (\S+)/, поэтому важно набирать его именно так. Вы можете объявлять только одну зависимость шаблона в строке.

Внешние зависимости

Если вы используете метод помощника, например, внутри кэшированного блока, и затем обновляете этот помощник, вам также нужно будет обновить кэш. Это не имеет большого значения, как вы это сделаете, но MD5 файла шаблона должен измениться. Одно из рекомендаций — просто сделать это явно в комментарии, например:

<%# Helper Dependency Updated: May 6, 2012 at 6pm %>
<%= some_helper_method(person) %>

Теперь всё, что вам нужно сделать, это изменить эту метку времени при изменении метода помощника.

Кэширование коллекций

При отрисовке коллекции объектов, каждый из которых использует один и тот же фрагмент, можно передать параметр :cached.

Для коллекций, отрисовываемых следующим образом:

<%= render partial: 'projects/project', collection: @projects, cached: true %>

Параметр cached: true заставит Action View's rendering читать несколько шаблонов из кэша одновременно вместо одного вызова на шаблон.

Шаблоны в коллекции, которые ещё не кэшированы, записываются в кэш.

Отлично работает вместе с кэшированием фрагментов шаблонов. Например, если шаблон, который отрисовывает коллекцию, кэшируется, как:

# projects/_project.html.erb
<% cache project do %>
  <%# ... %>
<% end %>

Любые отрисовки коллекций найдут эти кэшированные шаблоны при попытке чтения нескольких шаблонов одновременно.

Если кэш вашей коллекции зависит от нескольких источников (старайтесь избегать этого, чтобы всё было проще), вы можете указать все эти зависимости в качестве элементов массива, возвращаемых блоком:

<%= render partial: 'projects/project', collection: @projects, cached: -> project { [ project, current_user ] } %>

Это включит обе записи в ключ кэша, и обновление любой из них приведёт к истечению срока действия кэша.

cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil, digest_path: nil) Показать исходный код
# File actionview/lib/action_view/helpers/cache_helper.rb, line 211
def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil, digest_path: nil)
  if skip_digest
    name
  else
    fragment_name_with_digest(name, virtual_path, digest_path)
  end
end

Этот помощник возвращает имя ключа кэша для данного вызова фрагмента кэша. Передав skip_digest: true в cache, можно вручную пропустить вычисление хеша фрагментов кэша. Это полезно, когда фрагменты кэша нельзя вручную истечь, если вы не знаете точного ключа, что происходит при использовании memcached.

Хеш будет сгенерирован с использованием virtual_path: если он предоставлен.

cache_if(condition, name = {}, options = {}) { || ... } Показать исходный код
# File actionview/lib/action_view/helpers/cache_helper.rb, line 183
def cache_if(condition, name = {}, options = {}, &block)
  if condition
    cache(name, options, &block)
  else
    yield
  end

  nil
end

Кэшировать фрагменты представления, если condition имеет значение true

<% cache_if admin?, project do %>
  <b>All the topics on this project</b>
  <%= render project.topics %>
<% end %>
cache_unless(condition, name = {}, options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/cache_helper.rb, line 199
def cache_unless(condition, name = {}, options = {}, &block)
  cache_if !condition, name, options, &block
end

Кэшировать фрагменты представления, если condition имеет значение false

<% cache_unless admin?, project do %>
  <b>All the topics on this project</b>
  <%= render project.topics %>
<% end %>

© 2004–2019 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API