2009-07-22 18 views
14

私のコントローラにいくつかの変数を保存したいとします。私は1つのアクションでそれを初期化し、別のアクションでインクリメントし、別のアクションでインクリメントしたい。 @fooでこの変数を宣言するだけでは、それを作成したアクションの後に@fooが死んでしまうため、動作しません。
私はこの変数をモデルに保存したくありません。コントローラ内の複数のアクションにインスタンス変数を格納するにはどうすればよいですか?

この変数をセッションに保存する以外に保存する方法はありますか?
私はこの単純な問題に数回遭遇したようですが、それを解決する最善の方法を知りたいと思います。

答えて

22

コントローラアクションへの各呼び出しは、ステートレスです。コントローラの動作が終了した後は、何も使用できません。要求ごとに新しいコントローラインスタンスが作成され、要求の最後に破棄されます。

セッションまたはデータベースモデルに格納したくない場合は、その変数を特定のセッションに固有にしたい場合は、多くのオプションがありません。

すべてのセッションでグローバルであれば@instance_variableではなく@@class_variableに入れることができますが、複数のRailsプロセス(それぞれ独自のコピーを持つ)を開始すると面倒なことがあります。スレッドセーフなモードで実行していると、厄介な並行性のバグに終わる可能性があります。

は、私はあなたがmemcachedのようなものを見てことができると思いますが、あなたはまだ(それはグローバルでない限り)いくつかのuser_id、または他のセッションのマーカーに

7

あなたはRails.cacheに建てを利用することができ、そのキーする必要があるだろうあなたが値を格納するためのメカニズムですが、最初の答えで説明したように、user_idのようなものでキーを押さなければなりません。これは、異なるストレージメカニズムを使用してバックアップすることができるので、良い方法です。

Rails.cache.write(:foo) 
# in later action 
Rails.cache.read(:foo) 

もう1つ注目すべき点は、Flash値を最後の2つ以上の要求よりも最後にするためのkeepメソッドを提供するフラッシュハッシュです。

だから、アクション1であなたは価値作成することができます。あなたがそれにアクセスし、あなたはそれがより多くの後続のアクションのために生きて滞在したい場合は、再度保つ呼び出すことができるアクション2では

flash[:foo] = some_value 
flash.keep(:foo) 

を。

flash[:foo] #use it for something 
flash.keep(:foo) # keep it for another request 

httpリクエストのコンテキスト内できれいに行うのはちょっと難しいことです。

+0

キャッシュは良いアイデアですが、複数のWebサーバーがある場合は、Flashメソッドが機能しないと思います。 – Scott

+0

セッションが実際にセッションに保存されているため、セッションの格納場所によって異なります。たとえば、セッションが無効になっている場合はflash.nowが動作します。 – paulthenerd

+0

キャッシュは正しい考えです。しかし、MemoryStoreを使用している場合は、プロセスごとのメモリであるため、すべての要求を処理する単一のプロセスがない限り、後続の要求はメモリ内にあるプロセスにヒットしません。メモリストアがmemcachedによってバックアップされている場合は、はるかに良いでしょう。 –

1

単純なカウントまたは文字列の場合は、セッションに格納するのが最善の解決策だと思います。そうすれば、複数のWebサーバーを使用している場合はそこにあります。

なぜこれに対してセッションを使用しないのですか?

+0

私はRailsでかなり新しく、セッションは*重要なもの*はユーザーIDのようなものだと仮定しました。カウンターとしては些細なものではありません。ありがとう。 –

11

あなたはなぜセッションを使用しないのでしょうか?あなたのアクションで直接セッションを扱うのが気に入らなければ、生存している@fooインスタンス変数をフィルタでエミュレートすることができます。このような何か?

class FooController < ApplicationController 
    before_filter :load_foo 
    after_filter :save_foo 

    private 
    def load_foo 
     @foo = session[:foo] || 0 
    end 

    def save_foo 
     session[:foo] = @foo 
    end 

end 

あなたの行動は@countインスタンス変数を介して値を操作することができるようになりますと、これは自動的にセッションに永続化されます。

1

セッションは噛んだりしません。

また、これを実行するためのセッションがおそらく最善の方法です。

関連する問題