我是一名铁杆新手试图为我的应用实施缓存。 我安装了memcached并在我的development.rb中配置它,如下所示:
config.action_controller.perform_caching = true
config.cache_store = :mem_cache_store
我有一个控制器ProductsController,它在登录时显示用户特定的产品。
class ProductsController < ApplicationController
caches_action :index, :layout => false
before_filter :require_user
def index
@user.products
end
end
The route for index action is: /products
问题是当我以
身份登录时1)用户A第一次使用rails命中我的控制器并缓存产品操作。
2)我注销并以用户B身份登录,它仍以用户A身份登录并显示用户A而非用户B的产品。 它甚至没有击中我的控制器。
键可能是路径,在我的memcached控制台中,我看到它是基于相同的键获取的。
20 get views/localhost:3000/products
20 sending key views/localhost:3000/products
行动缓存不是我应该使用的吗?我如何缓存和显示用户特定的产品?
感谢您的帮助。
答案 0 :(得分:15)
第一个问题是你的before_filter for require_user是在动作缓存之后,因此不会运行。要解决此问题,请使用此控制器代码:
class ProductsController < ApplicationController
before_filter :require_user
caches_action :index, :layout => false
def index
@products = @user.products
end
end
其次,对于动作缓存,您执行与页面缓存完全相同的操作,但在运行过滤器后,您的@ user.products代码将无法运行。有几种方法可以解决这个问题。
首先,如果您愿意,可以根据传递给页面的参数缓存操作。例如,如果传递user_id参数,则可以基于该参数进行缓存,如下所示:
caches_action :index, :layout => false, :cache_path => Proc.new { |c| c.params[:user_id] }
其次,如果您只想缓存查询而不是整个页面,则应完全删除操作缓存并仅缓存查询,如下所示:
def index
@products = Rails.cache.fetch("products/#{@user.id}"){ @user.products }
end
这可以帮助您开始为每个用户提供单独的缓存。
答案 1 :(得分:0)
根据Pan Thomakos的回答,如果您从处理身份验证的控制器继承,则需要从父类复制before_filter。例如:
class ApplicationController < ActionController::Base
before_filter :authenticate
end
class ProductsController < ApplicationController
# must be here despite inheriting from ApplicationController
before_filter :authenticate
caches_action :index, :layout => false
end