Railsモデル、ビュー、コントローラー、ヘルパー:どこに行くの?


155

Ruby on Rails開発(または一般にMVC)では、ロジックを配置する場所に関してどのようなクイックルールに従う必要がありますか。

肯定で答えてください-「これをここ配置しないください」ではなく、ここ配置してください」

回答:


173

MVC

コントローラー:ここに、ユーザーが何を望んでいるか、何を与えるかを決定すること、ユーザーがログインしているかどうか、特定のデータを表示するかどうかなどを決定することに関するコードをここに配置します。最後に、コントローラーはリクエストを調べます表示するデータ(モデル)とレンダリングするビューを決定します。コードをコントローラーに入れるべきかどうか疑問がある場合は、おそらく入れるべきではありません。コントローラは細くしてください。

ビュー:ビューには、データ(モデル)を表示するための最小限のコードのみを含める必要があります。多くの処理や計算を行わないでください。モデルによって計算(または要約)されたデータ、またはコントローラーから生成されたデータを表示する必要があります。ビューが本当にモデルまたはコントローラーでは実行できない処理を実行する必要がある場合は、ヘルパーにコードを配置します。ビューに多数のRubyコードがあると、ページのマークアップが読みにくくなります。

モデル:データに関連するすべてのコード(ユーザー、投稿、アカウント、友達など、サイトを構成するエンティティ)が存在する場所にモデルを配置する必要があります。コードでエンティティに関連するデータを保存、更新、または要約する必要がある場合は、ここに配置します。ビューやコントローラー全体で再利用できます。


2
人々は脂肪モデルから離れ始めています。私のモデルはデータ構造として考えるのが好きです。次に、動作を実装するRubyオブジェクトをいくつか記述し、モデルで初期化します(モデルは、文字列や配列をRailsの外部のオブジェクトのデータとして扱うのと同じ方法でデータとして扱います)。ここだこの技術の例との良好な映像が。
ジョシュアチーク

@AdamDonahue脂肪のものは良いものと見なすことができるとは思いません。何トンもの責任は、サービスに所属する方が良いです。
fatuhoku 2016

35

pauliephonicの回答に追加するには:

ヘルパー:ビューの作成を容易にする関数。たとえば、ウィジェットのリストを常に繰り返して価格を表示している場合は、それをヘルパーに入れます(実際の表示用のパーシャルとともに)。または、ビューを乱雑にしたくないRJSがある場合は、ヘルパーに入れます。


実際には、ヘルパーにsign_inメソッドも配置していませんか?RoRのチュートリアルはここ>>>示唆したようにruby.railstutorial.org/book/...
イワン王を

14

MVCパターンは実際にはUIのみに関係し、他には何も関係ありません。ロジックではなくビューを制御するため、コントローラーに複雑なビジネスロジックを配置しないでください。コントローラーは適切なビューの選択に関与し、より複雑なものをドメインモデル(モデル)またはビジネスレイヤーに委任する必要があります。

ドメイン駆動設計には、サービスの概念があります。これは、さまざまなタイプのオブジェクトのオーケストレーションを必要とするロジックを追加する場所です。これは、通常、自然にModelクラスに属さないロジックを意味します。

私は通常、サービス層を自分のアプリケーションのAPIと考えています。私のサービスレイヤーは通常、作成しているアプリケーションの要件にかなり密接にマッピングします。したがって、サービスレイヤーは、アプリの下位レベルにあるより複雑な相互作用の単純化として機能します。つまり、サービスレイヤーをバイパスして同じ目標を達成できます。しかし、それを機能させるには、もっと多くの手段を講じる必要があります。

ここではRailsについて話しているのではなく、特定の問題に対処する一般的なアーキテクチャスタイルについて話していることに注意してください。


これは素晴らしい答えです:)
Carlos Martinez



7

認可/アクセス制御に関連するものをコントローラに入れてください。

モデルはすべてデータに関するものです。検証、関係、CRUD、ビジネスロジック

ビューとは、データを表示することです。入力のみを表示および取得します。

コントローラーとは、モデルからビュー(およびビュー)に、およびビューからモデルに送信されるデータを制御することです。コントローラはモデルなしでも存在できます。

私は、コントローラーを、顧客(要求)を、窓口係(質問)に質問する適切なカウンターに誘導する警備員/受付係と考えます。次に窓口係(ビュー)が行き、見たことのないマネージャー(モデル)から回答を受け取ります。次に、要求はセキュリティガード/受付(コントローラー)に戻り、マネージャー(モデル)が他の窓口(ビュー)の質問に答えて答えた別の窓口(ビュー)に行くように指示されるまで待ちます。 。

同様に、窓口係(ビュー)に何かを伝えたい場合、マネージャーがあなたの情報を受け入れたかどうかを2番目の窓口係が教えてくれることを除いて、ほとんど同じことが起こります。また、マネージャーにその情報を伝える権限がないため、警備員/受付係(コントローラー)がハイキングに行くように指示した可能性もあります。

つまり、メタファーを拡大するために、私のステレオタイプで非現実的な世界では、窓口係(ビュー)はかわいくて頭が空いていて、あなたの言うことを信じることが多いです。行くべきではなく、マネージャーは本当に醜いと意味がありますが、すべてを知っており、何が真で何がそうでないかを伝えることができます。


4

適切に分離するのに役立つ1つのことは、「ローカル変数をコントローラーからビューに渡す」アンチパターンを回避することです。これの代わりに:

# app/controllers/foos_controller.rb:
class FoosController < ApplicationController

  def show
    @foo = Foo.find(...)
  end

end

#app/views/foos/show.html.erb:
...
<%= @foo.bar %>
...

ヘルパーメソッドとして利用できるゲッターに移動してみてください。

# app/controllers/foos_controller.rb:
class FoosController < ApplicationController

  helper_method :foo

  def show
  end

  protected

  def foo
    @foo ||= Foo.find(...)
  end

end

#app/views/foos/show.html.erb:
...
<%= foo.bar %>
...

これにより、「@ foo」に何が入れられ、どのように使用されるかを簡単に変更できます。コントローラーとビューをより複雑にすることなく、それらの間隔を広げます。


ええと… これを行う理由について、いくつかの正当な理由/シナリオを追加していただけますか。これはKISSとYAGNIを壊し、非常に臭いです(もう1つの決まり文句で投げるだけです)
Sixty4Bit

2
1)Railsは、コントローラーのインスタンス変数をビューインスタンスにコピーするために多くの魔法をかけます。2)提案された実装は、アクセスされた場合にのみfooもロードします。これにより、ある程度の作業が節約される場合があります。重要な答えは本当に1)です。
webmat 2008年

11
ため息これはひどい。Railsインスタンス変数の共有は、アンチパターンではなく機能です。それは、ユビキタスで低メンタルオーバーヘッドの構文糖であり、現実世界の問題を引き起こすことはめったにありません。気に入らない場合は問題ありませんが、バロックの非標準構造を使用してコーディングすると、事態はさらに悪化します。この場合、効果的にfooをグローバル(とにかくコントローラーごと)変数にします。スコープを劇的に拡大することで、変数のスコープの悪用を修正しようとするのは非常に皮肉なことです。
gtd 2010年

1
買ってないよ、dasil003。範囲fooのは@foo同じである-それらは両方とも<ControllerClass、要求>ペアにスコープされています。さらに、ゲッターバージョンを使用Fooすることで、ビューがオブジェクトにアクセスする方法を変更することなく、オブジェクトの検索/保存/キャッシュの方法を変更できます。
James

1
「インスタンス変数を渡す」アンチパターンを意味していると思います。インスタンス変数は、深くネストされたパーシャルであっても、レンダリング全体の状態をリークします。ソリューションも状態をリークしますが、再割り当てを許可しないため、インスタンス変数よりもわずかに優れています。ローカルを渡すことは、メソッドを呼び出すようなものであるため、実際には最高です。ローカルはパーシャルからは見えません。この回答を参照してください。
ケルビン

2

まあ、それは一種のロジックが対処しなければならないものに依存しています...

多くの場合、コントローラーを小さくしたまま、モデルにより多くのものをプッシュすることは理にかなっています。これにより、モデルが表すデータにアクセスする必要がある場所から、このロジックを簡単に使用できるようになります。ビューにはロジックがほとんど含まれていません。だから本当に、一般的に、あなたは自分自身を繰り返さないように努力するべきです。

また、グーグルを少し見ると、何がどこに行くのかについてのいくつかのより具体的な例がわかります。

モデル:検証要件、データ関係、メソッドの作成、メソッドの更新、メソッドの破棄、メソッドの検索(これらのメソッドのジェネリックバージョンだけでなく、赤で人を見つけるなど、多くのことをしている必要があることに注意してください)姓で髪、次にロジックを抽出して、find_redH_by_name( "smith")またはそのようなものを呼び出すだけでよいようにします。

ビュー:これは、データの処理ではなく、データのフォーマットに関するすべてです。

コントローラ:これはデータ処理が行われる場所です。インターネットから:「コントローラーの目的は、ユーザーが要求したアクションに応答し、ユーザーが設定したパラメーターを取り、データを処理し、モデルとやり取りして、要求されたデータを最終的な形式で見る。"

お役に立てば幸いです。


0

簡単に言えば、一般的に、 モデルにはテーブルに関連するすべてのコード、単純または複雑な関係(複数のテーブルを含むSQLクエリと考えてください)、ビジネスロジックを使用して結果に到達するためのデータ/変数の操作があります。 。

コントローラーには、要求されたジョブに関連するモデルへのコード/ポインターがあります。

ビューはユーザー入力/相互作用を受け入れ、結果の応答を表示します。

これらから大きく逸脱すると、その部分に不要な負担がかかり、アプリケーション全体のパフォーマンスが影響を受ける可能性があります。


-1

テスト、テスト...モデルにできるだけ多くのロジックを入れれば、適切にテストできます。単体テストはモデルのテストによってデータとその形成方法をテストし、機能テストはコントローラーのテストによってルーティングまたは制御される方法をテストするため、データの整合性をテストすることはできません。モデル。

j

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.