Posted at

Deviseで使用するmodelのインスタンスをキャッシュする

More than 5 years have passed since last update.

ログを見てるとDeviseのユーザーがログイン状態にあるかどうかのチェックで毎回SQLをはいているので、この部分をキャッシュできないかな?とDeviseとWardenのコードを追ってみました。

https://github.com/plataformatec/devise

https://github.com/hassox/warden

(ここではUserモデルがDeviseを使用してるとします。)

かなり省略しますが、最終的にはwarden_compat.rb内の deserializeが呼ばれ

      klass = ActiveSupport::Inflector.constantize(klass_name)

if klass.respond_to? :serialize_from_session
klass.serialize_from_session(*args)
else
Rails.logger.warn "[Devise] Stored serialized class #{klass_name} seems not to be Devise enabled anymore. Did you do that on purpose?"
nil
end

そこでserialize_from_sessionを呼んでいます。

devise内のauthenticatable.rbを見ると


authenticatable.rb

    def serialize_from_session(key, salt)

record = to_adapter.get(key)
record if record && record.authenticatable_salt == salt
end

どうやらここでUserデータを読み込んでいて、このモジュール自体はUserモデルでインクルードしているので、この部分をUserモデル上でオーバーライドすればできそうです。

  def self.serialize_from_session(key, salt)

Rails.cache.fetch("#{User.name}_#{key[0]}") {
record = to_adapter.get(key)
record if record && record.authenticatable_salt == salt
}
end

もちろん適切なキャッシュのクリアは必要ですが、こんな感じでUserのデータをキャッシュできます。