web-dev-qa-db-ja.com

Ruby on Rails-モデルからコントローラー変数にアクセスする

モデルのコントローラーに設定されているインスタンス変数にアクセスしようとしています。コントローラーは製品コントローラーであり、モデルは製品モデルです。インスタンス変数は、accountと呼ばれる別のモデルのインスタンスです。

インスタンス変数は@current_account

コードを実行しても何も起こらず、エラーは発生しません。モデルからコントローラーに設定されたアクセスインスタンス変数について何かを読むことができる場所を誰かが知っていますか?

ありがとう

イーフ

20
RailsSon

一般的に、私が取り上げない気の利いた問題については、モデルからコントローラーにアクセスしようとしないでください。

私は次のような同様の問題を解決しました:

class Account < ActiveRecord::Base
  cattr_accessor :current
end

class ApplicationController < ActionController::Base
  before_filter :set_current_account
  def set_current_account
    #  set @current_account from session data here
    Account.current = @current_account
  end
end

次に、Account.currentで現在のアカウントにアクセスします

46
jeem

免責事項:次のコードはMVCの規則に違反しています...

クラス属性を使用すると、スレッドセーフの問題が発生する可能性があります。 Thread.current + around_filterを使用して、コントローラー関連のデータをスレッドレベルで格納し、リクエストが終了する直前にデータがクリアされるようにします。

class ApplicationController < ActionController::Base

  around_filter :wrap_with_hack

  def wrap_with_hack
    # We could do this (greener solution): 
    # http://coderrr.wordpress.com/2008/04/10/lets-stop-polluting-the-threadcurrent-hash/
    # ... but for simplicity sake:
    Thread.current[:controller] = self
    begin
      yield
    ensure
     # Prevent cross request access if thread is reused later
     Thread.current[:controller] = nil
    end
  end
end

これで、現在のコントローラーインスタンスは、Thread.current [:controller]を介したリクエスト処理中にグローバルに使用可能になります。

8
ibaixas

needモデルからコントローラー変数にアクセスする場合、コントローラーはビューとモデルの間のブリッジとして機能するため(少なくともRailsでは)、通常は設計が間違っていることを意味します。コントローラーはモデルから情報を取得します。モデルはすべきではありません。コントローラーについては何も知りませんが、とにかくやりたいのであれば、jeemが言ったようにそれを行うことができますが、私はむしろやりたいです:

 class << self

    attr_accessor :current

 end

の代わりに

cattr_accessor:current

ここで理由がわかります=> cattr_accessorが正常に機能しない

5
raf

直接コメントすることはできないので、ここに投稿します。受け入れられた回答は正しくないようです。 @viseが指摘しているように、クラス変数はリクエスト間で共有されます。したがって、アプリ全体の現在のアカウントが1つしかない場合を除いて、これは期待どおりに動作しません。

詳細については、@ molfが受け入れた回答をここで参照してください: Is Rails shared-nothingまたは個別のリクエストが同じランタイム変数にアクセスできますか?

2
Jacob

質問を正確に理解しているかどうかはわかりませんが、刺します。

モデルからコントローラーインスタンス変数にアクセスする必要がある場合は、それをモデルの属性にするか、ロジックをモデルではなく他のクラスコントローラーに移動する必要があると思います。

1
ghoppe