2

この質問は、「MVCの明らかな違反であるため」というような、1行のアサーションで繰り返し尋ねられ、回答されています。率直に言って、私はそれを得ていない。実際、コントローラ内にセッションを置くことは、ApplicationControllerがMVCの命令ではなく、ラック呼び出しを介してネットワークレイヤに向かうアーティファクトにすぎないと感じています。私の問題を説明しましょう。Modelレイヤーでセッションハッシュを参照してみませんか?

認証をゼロから転がすと、簡単なテスト(セッションはテストフレームワークでは利用できません)を明示する能力がないため、苦労して苦労していました。私の認証方式は、ほとんどの場合、セッションのハッシュを永続化レイヤーとして使用して、「現在のユーザー」のUserモデルのIDを保持したかったのです。コントローラーの人工物よりも、まるでモデルのような感じがしませんか?

「典型的な」セッションコントローラ(Ryan Batesの優れたスクリーンキャストからのもの)を見るたびに、コードの匂いがはっきりと分かります。残りの部分とにこの概念をシャベルに必死、私たちのような不健康な言語を参照してください。私には

def create 
    user = User.find_by_email(params[:session][:email]) 
    if user && user.authenticate(params[:session][:password]) 
    session[:user_id] = user.id 
    redirect_to root_url, notice: "Logged in!" 
    else 
    flash.now.alert = "Email or password is invalid" 
    render "new" 
    end 
end 

を、これはコードのにおい、リファクタリングのために叫んされて明らかにoverlogickedコントローラです!しかし、私たちはできません。どうして?ああ、MVCに違反しているためセッションへの参照を残して、永続化弁護士としてモデルに使用します。 WTF?私たちがこのREST RESOURCE /セッションに電話をかけたいと思うようなことはあなたに何か言っていませんか?

なぜこれが単なる単純であるかを確認するには、ログインビュー(手書きのhtml)、または「_タグ」APIの使用を見てください。このコードを実行するActiveModelモデルがあれば、作成コードは通常の足場のように見えるか、おそらくは「respond_with」の1ライナーに縮小される可能性があります。

def create 
    recognition = Recognition.new(params[:user]) 
    if recognition.save 
    redirect_to root_url, :notice => "Thank you for signing up!" 
    else 
    render "new" 
    end 
end 

次に、これらのすべてのビューの手作業でコーディングされたHTMLを見てみましょう。 Recognitionがセッション(またはコントローラレイヤの責任ではない他の手段)によって保持されているモデルの場合、フォームビルダーまたはsimple_formを使用してフォームを生成することができます。もちろん、単にセッションのハッシュを「new_login」クラスのRecognitionのメソッド、たとえばRecognition.on(session).new(params[:recognition])に渡すこともできますが、それは必然的に醜いと思われます。アプリケーション層で後でcurrent_user参照を使用したいと思うかもしれませんが、おそらくRecognition.on(session).current_userはシングルトンパターンを使用する方法に似ていますか?

厳密なBDDを使用して認証パッケージを構築しようとしましたが、正にこの部分をスパイクしていないと教えてください。 Recognitionモデルがあれば、この全体がハッカーのない単体テストの単純なセットに縮小されます。さて、代わりに、統合テストのための "唯一の"ユースケース、ActiveControllerモジュールの魔法の侵入、およびlogged_in_as述語の受け入れテストを迅速に行うためのハッキングがあります。

私はActiveModelの全ポイントがこのような再考とリファクタリングを容易にすると考えていました。すべてのモデルが "the"データベースを使用するわけではありません。どうして、「セッション?

私はあまりにも長い間、この匂いを "宝石と混乱しないでください"という言葉で埋めています。私はそれらを見る必要はありません。もはや!私は今から熱狂者たちを拒絶するつもりだと思う。申し訳ありませんが、セッションは、MVCのModelレイヤーで操作する必要がある持続レイヤーです。コントローラーランドに住んでいる理由は、コントローラーが理論的なMVCの魔法よりもラックオブジェクトであるという醜いエレガントな事実に関係していると思います。

もう一度、セッション層にアクセスするよりエレガントな方法は、コントローラーにロジックを持たせるよりですか?

答えて

1

たぶんそれは私ですが、私はそのコントローラでコードのにおいを嗅ぐことはありません。私はそれがコントローラ対モデルに入るべきだと思うものに依存すると思います。

私は人々が時には不健全な極端な "スキニーコントローラ"のアイデアを取ると思う。はい、モデルに含めることができるすべてがモデル上にあることを望みますが、コントローラはアプリケーション状態に基づいてモデルを変更するために存在し、設計目標を達成できるようにする必要があります。すべてのコントローラーを次のようなものにしてください:

def create 
    Creator.create(params) # Pass all params to the creator model, which will automatically detect what object you're trying to create, make it, and then render the appropriate view 
end 

def show 
    Shower.show(params) # Find the model object and the view based on the params and render them together 
end 

あなたのコードを更新して維持しようとする人々に心配の分離と悪夢の問題を引き起こすという考え方に挑戦します。コントローラは、モデルオブジェクトやそれらのモデルのメソッドを呼び出してアプリケーション状態を作成し、永続化する必要があります。また、モデルはアプリケーションの状態に依存しないようにする必要があります。それらをあまりにも強く結びつけると、モデルのビューとコントローラコードが完成します。その時点で、アプリケーションのどこに何があるかを判断することが非常に難しくなります。

これがあなたが望む目的であり、それがあなたの目標に役立つと思うなら、それを求めてください。しかし、あなたのコードは保守がより困難になり、他の人が理解するのが難しくなります。 MVCは懸念を分離する賢明な方法であり、コードを他の人にはあまり驚かせないからです。

あなたが提案しているセッションモデルは、実際にはかなり良いアイデアなので、すでに存在しています。 ;)authlogicフレームワークにはSessionsモデルがあります。authlogicを使用してログインするときは、paramsオブジェクトを使用して新しいUserSessionを作成します。 UserSessionsはmodelsフォルダ内に存在し、コントローラ認識モデルクラスに認証の要点を抽象化するためだけに存在します。それが探しているものなら、すでにあなたのために行われています!ドキュメントと使用例についてはthe authlogic github repositoryをご覧ください。

実際のActiveRecordモデルには、どんな種類のコントローラー状態も渡すことができません。コントローラがモデルを操作し、その操作の結果をHTMLとしてレンダリングできるようにします - これはそのためのものです!

+0

ありがとうございました。興味深いことに、Railsは、モデル、per_seではなく、あなたが記述する1ライナーに進化しました。コントローラーのメカニックは、実際には、モデルレイヤーの呼び出し後にrespond_withを使用するために3.Xで進化しました。私が提案した変更はコントローラをモデルに還元するのではなく、データベースの永続化されたコンテンツが使用されているのと同じようにコントローラの不要なロジックをモデル呼び出しに減らします。 – wizardwerdna

関連する問題