1

languagesほとんどすべてが変更されないテーブルがあります。初期キャッシュ以外で、このテーブルに対するデータベース クエリを回避しようとしています。

class Language < ActiveRecord::Base
  attr_accessible :code, :name, :native_name

  def self.find_by_name_in_cache(name)
    get_all_cached.find {|l| l.name == name}
  end

  def self.find_by_code_in_cache(code)
    get_all_cached.find {|l| l.code == code}
  end

  def self.find_by_id_in_cache(id)
    get_all_cached.find {|l| l.id == id}
  end

  def self.get_all_cached
    Rails.cache.fetch('all_languages') {Language.all}
  end
end

find_in_cache定義したメソッドのいずれかを使用している限り、すべてうまくいきます。

私の質問は、ActiveRelationキャッシングも強制的に使用するにはどうすればよいかということです。

たとえば、次のユーザー モデルを考えてみましょう。

class User < ActiveRecord::Base
  belongs_to :native_language, :class_name => :Language, :foreign_key => :native_language_id
end

にアクセスすると、データベースから@user.native_languageクエリが実行languageされます。これを防ぐためのアイデアをいただければ幸いです。

私は次のことができることを知っています:

class User < ActiveRecord::Base
  belongs_to :native_language, :class_name => :Language, :foreign_key => :native_language_id

  def native_language_cached
    Language.find_by_id_in_cache(self.native_language_id)
  end
end

ただし、多くのテーブルがテーブルを参照しているため、より透過的なソリューションを望んでいました。これらすべてのモデルにメソッドをlanguages追加するのは面倒です。cached

4

1 に答える 1

1

ActiveRecord::QueryCache単一のリクエスト中にクエリをキャッシュするには、ミドルウェアを使用していることを確認する以外に何もする必要はありません。2回呼び出す場合:

2.times{ user.native_language.to_s }

ログに次のようなものが表示されます。

Language Load (0.2ms)   SELECT `languages`.* FROM `languages` WHERE ...
CACHE (0.0ms)  SELECT `languages`.* FROM `languages` WHERE ...

リクエスト全体のキャッシュには、手動キャッシュが必要です。identity_cache gem は、あなたがやろうとしていること (キャッシュの関連付け) に役立つかもしれません。

おそらく最も簡単な方法はexpires_in、あなたが持っているコードにオプションを追加することでしょう。次のようなジェネリックcached_findメソッドを記述できます。

def self.cached_find(id)
  key = model_name.cache_key + '/' + id
  Rails.cache.fetch(key) do
    find(id).tap do |model|
      Rails.cache.write(key, model, expires_in: cache_period)
    end
  end
end

def self.cache_period
  3.days
end

必要な数のモデルで使用するモジュール mixin にすることができます。それはあなた自身の協会の発見を書かなければならないことを意味します. コールバックを使用して行うこともできます。

after_commit do
  Rails.cache.write(cache_key, self, expires_in: self.class.cache_period)
end
于 2013-09-23T20:02:31.360 に答える