2012-03-15 7 views
2

私たちはRails 3.0.6です。Railsコントローラのリクエスト間およびユーザ間でメモリに値を保持しますか?クラス変数を使用しますか?

月に1回しか変更されない番号のリストを維持していますが、ほぼすべてのページリクエストでこのリストにアクセスする必要があります。

リストをデータベースに保存します。

リクエストごとにデータベースにアクセスしてリストを取得するのではなく、効率的なアクセスのためにデータを一度取得してメモリに格納したいと考えています。

各ユーザーセッションでリストを保存する場合は、セッションごとにデータベースをヒットする必要があります。

データベースを一度しかヒットしない方法はありますか。すべてのユーザーとすべてのセッションで値をメモリに保持させる方法はありますか?コントローラーからリストにアクセスする必要があります。コントローラにクラス変数を定義する必要がありますか?

ありがとうございます!

答えて

6

私はRails.cacheがあなたの問題に対する答えだと思います。複数のバックエンドを持つシンプルなインターフェースですが、デフォルトではキャッシュがメモリに保存されますが、既にMemcached、Redisなどをアプリで使用している場合は、代わりにプラグインすることができます。

あなたのApplicationControllerにしてこれに似た何かを投げてみ

def list_of_numbers 
    @list_of_numbers ||= Rails.cache.fetch(:list_of_numbers, :expires_in => 24.hours) do 
    # Read from database 
    end 
end 

それはキャッシュから読み取るしようとしますが、それはそれを見つけられない場合は、集中的なものを行うと、次回

のためにそれを保存します
+0

ありがとうございます!値をクラス変数に格納して、リクエストやアクション間でアクセスできるようにしますか? – Crashalot

+0

ブラッドリーは同じ結論に達しました。私の答えよりももっと速く、より実践的な方法でした。いいえ、Rails.cacheはクラス変数のアプローチを置き換えます。 –

+0

私は忘れてしまったmemoizationを含める方法を更新しました。ありがとうtharrison。インスタンス間のクラスメソッドは非常にめったに良い考えではありません.Railsキャッシュからの読み込みはほぼ無料ですので、メソッドを呼び出すことができます。ここでの唯一の問題は、複数のサーバーを使用している場合に、サーバー間でデータが異なる可能性があることです。そのような状況では、Rails.cacheのバックエンドにMemcachedのようなものを差し込んで見てください –

2

あなたが探しているパターンはシングルトンと呼ばれ、時間の経過とともに変化しないものをキャッシュする簡単な方法です。たとえば、application_controller.rbには次のようなものがよく見られます。メソッドを常に呼び出す

def current_user(user_id) 
    @current_user ||= User.find user_id 
end 

この場合、インスタンス変数@current_userをチェックし、nilでなければそれを返します。それ以外の場合はデータベースルックアップを実行し、結果をインスタンス変数に代入します。

問題はすべてのインスタンスに適用されるため、同様ですがより広いです。

解決策の1つはクラス変数で、これはhttp://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_classes.html#S3に記載されています。上記と同様の解決策がここに適用されます。

これはあなたのケースでは良い解決策かもしれませんが、いくつかの問題があります。具体的には、設定に応じて(これはWebアプリケーションであると仮定します)、Railsの複数のインスタンスが異なるプロセスにロードされ、クラス変数は特定のインスタンスにのみ適用されます。一般的なPassengerモジュール(ApacheとNginx用)は、クラス変数にそのインスタンスすべてがアクセスできるように設定することができます。これは、サーバーが1つだけの場合に効果的です。

しかし、複数のサーバーを使用している場合は、少し複雑になります。確かに、クラス変数を使用して、各サーバーのデータベースに1ヒットする必要があることに同意することができます。これは、変数が...変化するときを除いて素晴らしい作品です!すべてのサーバーで変数を無効にする方法が必要です。どの程度批判的であるかによって、さまざまなエラーが発生する可能性があります(私は難しい方法を学びました:-)。

memcachedと入力します。これは、汎用キャッシングツールである素晴らしいツールです。非常に軽量で、非常にスマートです。特に、サーバーのクラスタ全体に分散キャッシュを作成することができます。値は一度しか格納されません(前述の同期の問題を回避します)。各サーバーは、特定のキャッシュキーを見つけるためにどのサーバーを調べるべきかを知っています。サーバがダウンしたときや、それ以外の不愉快なことが起こったときにも対処します。

セットアップは非常に簡単で、Railsはさまざまなキャッシュのニーズにそれを使用するとほとんど想定しています.Railsの宝石は単にパイと同じくらい簡単です。

クラス変数に格納できる値ほどシンプルではないかもしれないものをキャッシュする他の機会があると仮定すると、それはおそらく最初に開始する場所です。

関連する問題