我正在制作一个显示餐馆菜单的页面。我有2个型号:FoodMenu has_many:产品和产品belongs_to:food_menu。我没有这两种型号的控制器。相反,我使用“pages_controller.rb”来显示每个FoodMenu及其产品的“菜单”操作:
def menus
@food_menus = FoodMenu.includes(:products).all
end
我想在菜单页面(localhost:3000 /菜单)中使用Action Caching,这是有效的,但是当我更新,创建或销毁产品时,我无法使缓存过期。
在“pages_controller.rb”的顶部,我有:
caches_action :menus
cache_sweeper :pages_sweeper
我尝试使用此处的示例代码为app / sweepers中的Product和FoodMenu模型创建单独的清扫器: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
答案 0 :(得分:0)
我终于明白了!我能够让片段和动作缓存都能正常工作。从服务器日志来看,Action Caching似乎要快得多,因此我正在部署它。
对于片段缓存,我创建了一个&#34; food_menu_sweeper.rb&#34;它会观察FoodMenu和Product,并使我在partial中创建的片段过期,如下所示:
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放在&#34; application_controller.rb&#34;!这一重要提示来自阅读此SO条目:Rails - fragment cache not expiring
cache_sweeper :food_menu_sweeper
这一切都像一个魅力。刷新页面时,将从缓存中读取片段,并且不会进行数据库调用。更新产品或food_menu后,将清除缓存并显示新数据,然后缓存。
对于Action Caching,我补充道:
caches_action :menus
在我的&#34; pages_controller.rb&#34;中,然后从部分中删除了片段缓存,并替换了
expire_fragment("menu items")
food_menu_sweeper.rb中的,附:
expire_action(:controller => '/pages', :action => 'menus')
这里的关键是&#34; pages&#34;之前的主要斜线,我通过这个SO条目找到了:rails caching: expire_action in another namespace
如果没有前导斜线,我就会得到一个&#34;无法将符号转换为整数&#34;通过ActiveAdmin界面更新项目时出错。
Yay for determination,Google和Stack Overflow!