Кэширование в Rails 3: как использовать очиститель с кэшированием действий и фрагментов для истечения срока действия кеша?

Я работаю над страницей, которая отображает меню ресторана. У меня есть 2 модели: FoodMenu has_many: products и Product own_to: food_menu. У меня нет контроллеров ни для одной из моделей. Вместо этого я использую "pages_controller.rb" для отображения каждого FoodMenu и его продуктов с действием "меню":

def menus
 @food_menus = FoodMenu.includes(:products).all
end

Я хочу использовать кэширование действий для страницы меню (localhost: 3000 / menus), которая работает, но я не могу добиться истечения срока действия кеша при обновлении, создании или уничтожении продукта.

Вверху "pages_controller.rb" у меня есть:

caches_action :menus
cache_sweeper :pages_sweeper

Я попытался создать отдельные подметальные машины для моделей Product и FoodMenu в app / sweepers, используя приведенный здесь пример кода: http://guides.rubyonrails.org/caching_with_rails.html#sweepers, но это не сработало. Затем я прочитал в SO-записи, что уборщик должен наблюдать за всеми моделями, которые использует контроллер, поэтому я предположил, что это означает, что мне нужно создать «pages_sweeper.rb», который наблюдает за моделями Product и FoodMenu и истекает срок действия « меню "действие. Это тоже не сработало. Что я делаю неправильно? Вот что у меня сейчас в "pages_sweeper.rb":

class PagesSweeper < ActionController::Caching::Sweeper
 observe Product, FoodMenu 

 # If our sweeper detects that a Product was created call this
 def after_create(product)
  expire_cache_for(product)
 end

 # If our sweeper detects that a Product was updated call this
 def after_update(product)
  expire_cache_for(product)
 end

 # If our sweeper detects that a Product was deleted call this
 def after_destroy(product)
   expire_cache_for(product)
 end

 def after_create(food_menu)
  expire_cache_for(food_menu)
 end

 # If our sweeper detects that a FoodMenu was updated call this
 def after_update(food_menu)
   expire_cache_for(food_menu)
 end

 # If our sweeper detects that a FoodMenu was deleted call this
 def after_destroy(food_menu)
   expire_cache_for(food_menu)
 end


 private
 def expire_cache_for(product)
 # Expire the menus action now that we added a new product
 expire_action(:controller => 'pages', :action => 'menus')

 # Expire a fragment
 expire_fragment('all_available_products')
 end

 def expire_cache_for(food_menu)
 # Expire the menus page now that we added a new FoodMenu
 expire_action(:controller => 'pages', :action => 'menus')

 # Expire a fragment
 expire_fragment('all_available_food_menus')
 end
end     

person monfresh    schedule 02.01.2012    source источник


Ответы (1)


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

Для кэширования фрагментов я создал food_menu_sweeper.rb, который отслеживает и FoodMenu, и Product, и истекает срок действия фрагмента, который я создал в партиале, например:

class FoodMenuSweeper < ActionController::Caching::Sweeper
 observe FoodMenu, Product

 def after_save(food_menu)
   expire_cache(food_menu)
 end

 def after_destroy(food_menu)
   expire_cache(food_menu)
 end

 def after_save(product)
   expire_cache(product)
 end

 def after_destroy(product)
   expire_cache(product)
 end

 private

 def expire_cache(food_menu)
  expire_fragment("menu items")
 end

 def expire_cache(product)
  expire_fragment("menu items")
 end

end

Вот фрагмент в партиале:

<% cache("menu items") do %>
  <% for food_menu in FoodMenu.full_list %> 
    ...
<% end %>
<% end %>

FoodMenu.full_list вызывается внутри фрагмента для кеширования запроса к базе данных, который определен в модели food_menu.rb:

def self.full_list
  FoodMenu.includes(:products).all
end

Затем нужно поместить cache_sweeper в "application_controller.rb"! Этот важный намек пришел из чтения этой записи SO: Rails - срок действия кэша фрагментов не истекает

 cache_sweeper :food_menu_sweeper

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

Для кэширования действий я добавил:

caches_action :menus

в моем "pages_controller.rb", затем удалил кеш фрагментов из партиала и заменил

expire_fragment("menu items")

в food_menu_sweeper.rb, с:

expire_action(:controller => '/pages', :action => 'menus')

Ключевым моментом здесь была косая черта перед «страницами», которую я нашел с помощью этой записи SO: rails caching: expire_action в другом пространстве имен

Без ведущей косой черты я получал ошибку «Невозможно преобразовать символ в целое число» при обновлении элементов через интерфейс ActiveAdmin.

Ура за решимость, Google и Stack Overflow!

person monfresh    schedule 03.01.2012
comment
Означает ли это, что кеширование фрагментов и кеширование действий нельзя использовать в одной и той же стратегии кеширования, т.е. в одной или другой стратегии? У меня проблемы с истечением срока действия кеша фрагментов, который находится в партиале, являющемся частью представления, в котором я использую caches_action. - person Pete; 16.02.2012