2011-02-23 6 views
6

저는 내 앱용 캐싱을 구현하려는 레일 초보자입니다. 다음과 같이 나는 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가 처음으로 내 컨트롤러에 충돌하고 제품 동작을 캐시합니다.

2) 로그 아웃하고 사용자 B로 로그인해도 사용자 A로 로그인되며 사용자 A가 아니라 사용자 B가 아닌 제품을 보여줍니다. 내 컨트롤러에도 충돌하지 않습니다.

아마도 키가 경로 일 것입니다. 내 memcached 콘솔에서 동일한 키를 기반으로 가져 오는 것입니다.

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

조치 캐싱은 내가 사용해야하는 것이 아닙니까? 사용자 특정 제품을 캐시하고 표시하려면 어떻게해야합니까?

도움 주셔서 감사합니다.

답변

14

첫 번째 문제는 require_user에 대한 before_filter가 동작 캐시 이후이므로 실행되지 않는다는 것입니다. 이 페이지 캐싱과 정확히 같은 일을하고있는 캐시

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 

이렇게하면 각 사용자별로 별도의 캐시를 가질 수 있습니다.

+0

감사합니다. 쿼리 캐시 사용에 대한 마지막 제안으로 끝 맺었습니다. 목록의 한 제품에 대한 일부 속성이 업데이트 될 때 'products/{# user.id}'에 대한 전체 캐시를 완전히 무효화하는 방법에 대한 아이디어는 ... product (10) .price? – truthSeekr

+1

원하는 경우 개별 제품을 모두 캐시하지 않고 캐시 할 수 있으므로 무효화 된 캐시 값을보다 효과적으로 제어 할 수 있습니다. 이것은 양날의 칼입니다. 캐시를 무효화하고 싶을수록 캐시가 무효화되고 복잡해질수록 캐시 문을 개별적으로 작성해야합니다. 전체 제품 목록 캐시를 무효화하는 것이 좋습니다. 아마이 작업을 수행하는 것이 가장 간단 할 것입니다. 이 접근법에서 성능 문제가 발생하기 시작했다면 더 자세히 살펴보고 더 자세한 캐시를 작성하십시오.지나치게 최적화하지 마십시오. –

+0

도움을 주셔서 감사 드리며 조언을드립니다. – truthSeekr

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 
관련 문제