модуль ActionView::Helpers::CacheHelper
Публичные методы экземпляра
# File actionview/lib/action_view/helpers/cache_helper.rb, line 161
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, которое автоматически удалит старые записи. Подробнее о кэшировании на основе ключей см.: signalvnoise.com/posts/3113-how-key-based-cache-expiration-works
При использовании этого метода укажите зависимость кэша как имя кэша, например:
<% cache project do %> <b>All the topics on this project</b> <%= render project.topics %> <% end %>
Этот подход предполагает, что при добавлении новой темы вы будете изменять проект. Ключ кэша, сгенерированный по этому вызову, будет чем-то вроде:
views/projects/123-20120806214154/7a1156131a6928cb0026877f8b749ac9
^class ^id ^updated_at ^template tree digest Таким образом, кэш автоматически обновляется всякий раз, когда изменяется updated_at проекта.
Если кэш вашего шаблона зависит от нескольких источников (старайтесь избегать этого для простоты), вы можете назвать все эти зависимости в виде массива:
<% cache [ project, current_user ] do %> <b>All the topics on this project</b> <%= render project.topics %> <% end %>
Это включит обе записи в часть ключа кэша, и обновление любой из них приведет к истечению срока действия кэша.
Хеш шаблона
Хеш шаблона, который добавляется к ключу кэша, вычисляется путем взятия MD5 от содержимого всего файла шаблона. Это гарантирует, что ваши кэши автоматически истекают при изменении файла шаблона.
Обратите внимание, что MD5 вычисляется для всего файла шаблона, а не только для того, что находится внутри вызова cache/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 прочитать несколько шаблонов из кэша сразу вместо одного вызова на шаблон.
Шаблоны в коллекции, которые еще не кэшированы, записываются в кэш.
Идеально работает вместе с кэшированием фрагментов шаблонов. Например, если шаблон, который рендерит коллекция, кэширован так:
# projects/_project.html.erb <% cache project do %> <%# ... %> <% end %>
Любой рендеринг коллекции найдет эти кэшированные шаблоны при попытке одновременного чтения нескольких шаблонов.
Если ваш кэш коллекции зависит от нескольких источников (старайтесь избегать этого для простоты), вы можете назвать все эти зависимости в виде блока, который возвращает массив:
<%= render partial: 'projects/project', collection: @projects, cached: -> project { [ project, current_user ] } %> Это включит обе записи в часть ключа кэша, и обновление любой из них приведет к истечению срока действия кэша.
# File actionview/lib/action_view/helpers/cache_helper.rb, line 206
def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil)
if skip_digest
name
else
fragment_name_with_digest(name, virtual_path)
end
end Этот помощник возвращает имя ключа кэша для данного вызова кэша фрагмента. Передавая skip_digest: true в cache, можно вручную обойти вычисление хеша фрагментов кэша. Это полезно, когда фрагменты кэша нельзя вручную истечь, если вы не знаете точного ключа, что имеет место при использовании memcached.
Хеш будет сгенерирован с использованием virtual_path: , если он предоставлен.
# File actionview/lib/action_view/helpers/cache_helper.rb, line 178
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 %>
# File actionview/lib/action_view/helpers/cache_helper.rb, line 194
def cache_unless(condition, name = {}, options = {}, &block)
cache_if !condition, name, options, &block
end Кэшировать фрагменты представления, если condition не равно true
<% cache_unless admin?, project do %> <b>All the topics on this project</b> <%= render project.topics %> <% end %>
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.