Рельсы 4 фрагмента кеширования для разных просмотров
В моем приложении rails 4 я пытаюсь избавиться от кеширования, но я немного сбит с толку из-за различных версий настроек ключа кеша, помощников кеша и автоматического истечения срока действия.
Итак, позвольте мне спросить это на нескольких примерах. Я не перемещаю примеры к разным вопросам специально, так как я чувствую, что каждый может понять тонкие различия одним взглядом.
1: последние пользователи в боковой панели
Я хотел бы показать последние пользователи. Это, конечно, одинаково для всех пользователей в приложении и отображается на всех страницах. В Railscasts я видел похожий пример, когда он истек, позвонив expire_fragment...
в контроллере. Но согласно другим ресурсам, это должно истечь автоматически, когда что-то меняется (например, регистрация нового пользователя). Итак, мой вопрос: правильно ли я устанавливаю ключ и будет ли он автоматически истек?
_sidebar.html.erb (отображается на всех страницах боковой панели)
<% cache 'latest-users' %>
<%= render 'users/user_sidebar' %>
<% end %>
_users_sidebar.html.erb
<% @profiles_sidebar.each do |profile| %>
<%= profile.full_name %>
........
<% end %>
2: страница выставки продукта
Я хотел бы отобразить данный продукт (только на странице шоу). Это то же самое снова для всех пользователей, но есть больше версий, так как есть больше продуктов. Вопрос опять тот же: правильно ли я настраиваю ключ, и не истечет ли он автоматически?
Продукты / show.html.erb
<% cache @product %>
<%= @product.name.upcase %>
<%= @product.user.full_name %>
<% end %>
3: продукты / индекс (разбито на страницы с волевой страницей)
Здесь я хотел бы кэшировать все продукты на заданной странице нумерации страниц, чтобы продукты кэшировались блоками. Это также одинаково для всех пользователей, и отображается только на products index page
, (Позже я хотел бы реализовать russian-doll-caching
для отдельных продуктов на этой странице.) Мой вопрос: правильно ли я это делаю, и срок его действия истечет?
продукты index.html.erb
<% cache [@products, params[:page]] %>
<%= render @products %>
<% end %>
_product.html.erb
<%= product.name %>
<%= product.user.full_name %>
.....
Пример кода, который я пытался использовать (не уверен, что он хороший):
Сначала с индексной страницей и без русской куклы.
Второй - с русской куклой для шоу-страницы с комментариями.
2 ответа
Существует довольно большая разница между кэшированием одной записи и коллекцией записей.
Вы можете просто сказать, была ли изменена одна запись, посмотрев на метку времени. Метод cache_key по умолчанию работает следующим образом:
Product.new.cache_key # => "products/new" - never expires
Product.find(5).cache_key # => "products/5" (updated_at not available)
Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available)
Однако информация о том, когда коллекция устарела, во многом зависит от того, как она используется.
В вашем первом примере вы действительно заботитесь только о created_at
отметка времени - в других ситуациях вы можете захотеть посмотреть, когда записи обновляются или даже когда связанные записи были вставлены / обновлены. Здесь нет правильного ответа.
1.
Сначала вы бы потянули N количество пользователей, упорядоченных по created_at
:
@noobs = User.order(created_at: :desc).limit(10)
Мы можем просто аннулировать кеш здесь, посмотрев на первого пользователя в коллекции.
<!-- _sidebar.html.erb -->
<% cache(@noobs.first) do %>
<%= render partial: 'users/profile', collection: @noobs %>
<% end %>
Мы можем сделать это, так как знаем, что, если новый пользователь зарегистрирован (а), он ударит предыдущий номер один в слот.
Затем мы можем кешировать каждого отдельного пользователя с помощью русской куклы. Обратите внимание, что поскольку частичное называется profile
частичное передается локальной переменной profile
:
<!-- users/_profile.html.erb -->
<% cache(profile) do %>
<%= profile.full_name %>
<% end %>
2.
Да. Это истечет. Вы могли бы хотеть частичное с русским кешированием куклы как другие примеры.
3.
Для разбитой на страницы коллекции вы можете использовать идентификаторы записей в массиве для создания ключа кэша.
Ред.
Поскольку вы не хотите показывать устаревшее представление продукта, который может быть обновлен, вы также захотите использовать updated_at
как ключ кеша во "внешнем слое" русской куклы.
В этом случае имеет смысл загружать записи целиком. Вы можете игнорировать мой предыдущий комментарий о .ids
,
Продукты /index.html.erb:
<% cache([@products.map(&:id), @products.map(&:updated_at).max]) do %>
<%= render @products %>
<% end %>
Продукты /_product.html.erb:
<% cache(product) do %>
<%= product.name %>
<% end %>
ИМХО, ключ кеша - это дух всей концепции.
Теперь давайте обсудим эти примеры.
- последние пользователи в боковой панели: исправлена строка в качестве ключа кеша
cache_key
может быть views/latest-users/7a1156131a6928cb0026877f8b749ac9
который дайджест 7a11561..
является MD5 литерала блока кеша.
В этом случае срок действия кэша истекает только при изменении шаблона или чего-либо в этом блоке.
<% cache 'latest-users' do %>
<%= render 'users/user_sidebar' %>
<% end %>
- страница показа продукта: объект как ключ кеша
cache_key
может быть views/product/123-20160330214154/9be3eace37fa886b0816f107b581ed67
обратите внимание, что кеш это пространство имен с #{product.to_s}
/#{product.id}
-#{product.updated_at}
,
В этом случае срок действия кэша истекает, когда (1) product.updated_at
изменен или (2) литерал блока кэша изменен.
И обратите внимание, что кэш отличается от другого продукта id
,
<% cache @product %>
<%= @product.name.upcase %>
<%= @product.user.full_name %>
<% end %>
- products/index (разбит на страницы с помощью will-paginate gem): массив в качестве ключа кэша
cache_key
может быть views/product/123-20160330214154/product/456-20160330214154/d5f56b3fdb0dbaf184cc7ff72208195e
не уверен в этом. но в любом случае, это должно быть расширено примерно так.
В этом случае срок действия кэша истекает, когда (1) изменяется либо product-123, либо product-456 (product.updated_at
изменено) или (2) изменен литерал блока кэша.
И кеш отличается от разного контента @products
по их ids
так что нет необходимости добавлять params[:page]
, он будет кэшировать каждую страницу из-за их различных @products
содержание.
<% cache [@products, params[:page]] %>
<%= render @products %>
<% end %>
Вы можете прочитать статью, написанную DHH, в которой очень хорошо описывается кэширование русской куклы. И API документ