Rails设计:我如何(mem)缓存设备对用户对象的数据库请求?

use*_*148 6 ruby-on-rails devise

每次我访问经过身份验证的页面时,我都会注意到发布了一个SQL语句:

用户负载(0.2ms)SELECT users.*FROM usersWHERE(users.id= 1)LIMIT 1

(我正在使用Rails 3顺便说一句..所以cache_money似乎是一个解决方案,尽管有很多搜索我找不到替代品).

我在用户模型中尝试了很多覆盖,似乎只调用了find_by_sql.哪个传递了整个SQL语句的字符串.像find_by_id或find这样直观的东西似乎没有被调用.我可以'覆盖这个方法并收集用户ID并从中做一个合理的缓存系统 - 但这非常难看.

我也尝试重写authenticate_user,我可以拦截一次SQL尝试但是然后调用current_user似乎再次尝试.

简单地说,我的用户对象很少变化,并且它是一个悲伤的状态,以便为此而不是内存缓存解决方案.(假设我愿意接受使用以下内容来使所述缓存失效的所有责任:after_save作为部分但不是所有解决方案)

Mic*_*c92 13

以下代码将通过其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
Run Code Online (Sandbox Code Playgroud)


Ada*_*bin 1

警告:很可能有更好/更聪明的方法来做到这一点。

几个月前我就解决了这个问题。我发现——或者至少我想我发现——Devise在这里加载用户对象: https: //github.com/plataformatec/devise/blob/master/lib/devise/rails/warden_compat.rb#L31

我在 /initializers/warden.rb 中为该反序列化方法创建了一个猴子补丁,以执行缓存获取而不是获取。这感觉又脏又错,但它确实有效。