Rails Action Caching for user specific records

放肆的年华 提交于 2019-12-07 02:13:25

问题


I am a rails newbie trying to implement caching for my app. I installed memcached and configured it in my development.rb as follows:

config.action_controller.perform_caching             = true
config.cache_store = :mem_cache_store

I have a controller ProductsController that shows user specific products when they are logged in.

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

The problem is that when I login as

1) User A for the first time, rails hits my controller and caches the products action.

2) I logout and login as User B, it still logs me in as User A and shows products for User A and not User B. It doesn't even hit my controller.

The key probably is the route, in my memcached console I see that it's fetching based on the same key.

20 get views/localhost:3000/products
20 sending key views/localhost:3000/products

Is action caching not what I should use? How would I cache and display user specific products?

Thanks for your help.


回答1:


The first problem is that your before_filter for require_user is after the action caching, so that won't run. To fix that, use this controller code:

class ProductsController < ApplicationController
  before_filter :require_user
  caches_action :index, :layout => false

  def index
    @products = @user.products              
  end
end

Second, for action caching you are doing the exact same thing as page caching, but after filters are run, so your @user.products code won't run. There are a couple of ways to fix this.

First, if you want you can cache the action based on the parameters that are passed to the page. For example, if you pass a user_id parameter, you could cache based on that parameter like this:

caches_action :index, :layout => false, :cache_path => Proc.new { |c| c.params[:user_id] }

Second, if you want to simply cache the query and not the entire page, you should remove action caching entirely and only cache the query, like this:

def index
  @products = Rails.cache.fetch("products/#{@user.id}"){ @user.products }
end

This should help you get on your way to having a separate cache for each user.




回答2:


Building on Pan Thomakos's answer, if you're inheriting from a controller which handles authentication you need to copy the before_filter from the parent class. For example:

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


来源:https://stackoverflow.com/questions/5095732/rails-action-caching-for-user-specific-records

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!