2011-04-25 2 views
4

내가 인증 페이지를 칠 때마다, 나는 SQL 문을 발행 고안주의 사항 :.Rails Devise : 사용자 객체에 대한 devise의 데이터베이스 요청을 캐시하려면 어떻게해야합니까?

사용자 부하 (이 0.2ms) users을 선택 * users FROM LIMIT 1

(I (usersid = 1). 레일 3 btw를 사용하고 있습니다. 그래서 cache_money는 해결책으로 보이고 많은 검색에도 불구하고 아무런 대안도 찾지 못했습니다.)

나는 사용자 모델에서 많은 재정의를 시도했지만 find_by_sql 만 호출 된 것 같습니다. 어느 것이 전체 SQL 문 문자열을 전달받습니다. find_by_id 나 find와 같이 직관적 인 뭔가가 호출되지 않는 것 같습니다. 이 방법을 무시하고 사용자 ID를 수집하고이를 통해 합리적인 캐시 시스템을 만들 수 있습니다.하지만 꽤 엉망입니다.

또한 authenticate_user를 대체하여 하나의 SQL 시도를 차단할 수는 있지만 current_user를 호출하면 다시 시도하는 것처럼 보입니다.

단순히 내 사용자 개체가 거의 변경되지 않고 Memcache 솔루션 대신 DB를 계속 사용하는 슬픈 상태입니다. (그 캐시를 무효로하는 것에 대한 모든 책임을 기꺼이 받아들이라고 가정하십시오 : after_save는 그 해결책의 전부는 아니지만 일부분으로).

+0

Devise는 많은 검사를 수행합니다. 당신을 확인해 * 할 * (보통). 하지만 당신 말이 맞아요, 그 중 일부는 캐시 가능해야합니다. Ruby-Debug를 실행하여 다른 find가 어디에서 왔는지 알아 냈습니까? 나는 소스에서 find_by_sql을 보지 못했습니다. 일반적인 경우는 Devise가 보호하는 페이지를 방문하고 로그인 한 사용자가 사용자가 실제로 유효한지 확인하는 것입니다. 왕복 여행을 캐싱 할 수 있다면 많은 문제를 해결해야합니다. 더 어렵습니다 : Devise 자체가 캐시를 무효화 할 수있는 방법에는 여러 가지가 있습니다. 예를 들어, 사용자가 암호를 다시 설정할 경우. –

답변

1

경고 : 이렇게하는 것이 가장 현명한 방법 일 것입니다.

몇 달 전에이 문제를 쫓았습니다. 내가 발견 - 또는 적어도, 내가 찾은 것 같아요 - 유증 여기에 사용자 개체로드 여기서 https://github.com/plataformatec/devise/blob/master/lib/devise/rails/warden_compat.rb#L31

내가 캐시 대신 인출 할 /initializers/warden.rb에서 그 직렬화 복원 방법에 대한 원숭이 패치를 생성 얻을. 그것은 더럽고 틀렸다고 느꼈지만 효과가있었습니다.

+0

굉장한 아담. 더럽고 틀릴 수도 있지만 실제로 작동합니다. – user724148

1

나는 이것도 애써왔다. 이 일을

덜 복잡한 방법은 사용자 모델에이 클래스의 메소드를 추가하는 것입니다 : 내가 저장에서 전달되는 오브젝트 ID에 모델 이름을 붙이는거야

def self.serialize_from_session(key, salt) 
    single_key = key.is_a?(Array) ? key.first : key 
    Rails.cache.fetch("user:#{single_key}") { User.find(single_key) } 
end 

주/검색 캐쉬로부터의 오브젝트. 당신은 당신의 필요에 맞는 어떤 계획이라도 사용할 수 있습니다.

물론 걱정할 점은 무엇인가 변경되면 캐시에서 사용자를 무효화하는 것입니다. 대신 키의 일부로 세션 ID를 사용하여 캐시에 사용자를 저장하는 것이 좋았지 만 세션은 모델 클래스에서 사용할 수 없으며 Devise가이 메소드에 전달하지 않습니다.

12

다음 코드는 id를 사용하여 사용자를 캐시하고 은 수정 할 때마다 캐시를 ​​무효화합니다.

class User < ActiveRecord::Base 

    after_save :invalidate_cache 
    def self.serialize_from_session(key, salt) 
    single_key = key.is_a?(Array) ? key.first : key 
    user = Rails.cache.fetch("user:#{single_key}") do 
     User.where(:id => single_key).entries.first 
    end 
    # validate user against stored salt in the session 
    return user if user && user.authenticatable_salt == salt 
    # fallback to devise default method if user is blank or invalid 
    super 
    end 

    private 
    def invalidate_cache 
     Rails.cache.delete("user:#{id}") 
    end 
end 
관련 문제