简体   繁体   English

Rails Action Caching用于用户特定的记录

[英]Rails Action Caching for user specific records

I am a rails newbie trying to implement caching for my app. 我是Rails新手,正在尝试为我的应用程序实现缓存。 I installed memcached and configured it in my development.rb as follows: 我安装了memcached并将其配置在development.rb中,如下所示:

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. 我有一个控制器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

The problem is that when I login as 问题是当我登录为

1) User A for the first time, rails hits my controller and caches the products action. 1)第一次用户A,Rails击中了我的控制器并缓存了产品操作。

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. 2)我以用户B的身份注销并登录,它仍然以用户A的身份登录并显示用户A而不是用户B的产品。它甚至没有击中我的控制器。

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. 谢谢你的帮助。

The first problem is that your before_filter for require_user is after the action caching, so that won't run. 第一个问题是您的require_user的before_filter在操作缓存之后,因此不会运行。 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. 其次,对于动作缓存,您正在执行与页面缓存完全相同的操作,但是在运行过滤器之后,因此您的@ user.products代码将不会运行。 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: 例如,如果传递user_id参数,则可以基于该参数进行缓存,如下所示:

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. 这应该可以帮助您为每个用户使用单独的缓存。

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. 基于Pan Thomakos的答案,如果您要从处理身份验证的控制器继承,则需要从父类中复制before_filter。 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM