首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails3缓存:如何使用带有Action和片段缓存的清理器来终止缓存?

Rails3缓存:如何使用带有Action和片段缓存的清理器来终止缓存?
EN

Stack Overflow用户
提问于 2012-01-02 12:06:05
回答 1查看 3.2K关注 0票数 2

我正在开发一个显示餐厅菜单的页面。我有两个模型: FoodMenu has_many :products和belongs_to :food_menu。这两个模型我都没有控制器。取而代之的是,我使用"pages_controller.rb“来显示每个FoodMenu及其带有"menus”操作的产品:

代码语言:javascript
复制
def menus
 @food_menus = FoodMenu.includes(:products).all
end

我想对菜单页面(localhost:3000/ menus )使用Action缓存,它正在工作,但我无法在更新、创建或销毁产品时让缓存过期。

在"pages_controller.rb“的顶部,我有:

代码语言:javascript
复制
caches_action :menus
cache_sweeper :pages_sweeper

我尝试使用示例代码http://guides.rubyonrails.org/caching_with_rails.html#sweepers在应用程序/清理器中为Product和FoodMenu模型创建单独的清理器,但不起作用。然后,我在一个SO条目中读到,清扫器应该观察控制器使用的所有模型,所以我假设这意味着我必须创建一个同时观察Product和FoodMenu模型并终止"pages_sweeper.rb“操作的"menus”。这也不管用。我做错了什么?这是我现在在“pages_sweeper.rb”中的内容:

代码语言:javascript
复制
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     
EN

回答 1

Stack Overflow用户

发布于 2012-01-04 05:43:33

我终于想通了!我能够同时使用片段缓存和动作缓存。从服务器日志来看,Action缓存似乎要快得多,所以这就是我要部署的。

对于片段缓存,我创建了一个"food_menu_sweeper.rb“,它同时观察FoodMenu和Product,并使我在部分中创建的片段过期,如下所示:

代码语言:javascript
复制
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

以下是部分代码中的片段:

代码语言:javascript
复制
<% cache("menu items") do %>
  <% for food_menu in FoodMenu.full_list %> 
    ...
<% end %>
<% end %>

在片段中调用FoodMenu.full_list来缓存数据库查询,这在food_menu.rb模型中定义:

代码语言:javascript
复制
def self.full_list
  FoodMenu.includes(:products).all
end

然后,这里的关键是将cache_sweeper放在"application_controller.rb“中!这个关键的提示来自于阅读这篇文章:Rails - fragment cache not expiring

代码语言:javascript
复制
 cache_sweeper :food_menu_sweeper

这一切都像是一种魔力。当我刷新页面时,会从缓存中读取该片段,并且不会进行任何数据库调用。一旦我更新了产品或food_menu,缓存就会被清除,新数据就会出现并被缓存。

对于操作缓存,我添加了:

代码语言:javascript
复制
caches_action :menus

在我的"pages_controller.rb“中,然后从部分中删除片段缓存,并替换

代码语言:javascript
复制
expire_fragment("menu items")

在food_menu_sweeper.rb中,使用:

代码语言:javascript
复制
expire_action(:controller => '/pages', :action => 'menus')

这里的关键字是"pages“前面的斜杠,我是通过SO条目找到的:rails caching: expire_action in another namespace

如果没有前导斜杠,当通过ActiveAdmin接口更新项目时,我会得到一个“无法将符号转换为整数”的错误。

决定,Google,和Stack Overflow!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8697307

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档