17

警告:ここにヌーブ。

これは些細なことですが、ビューの一部をヘルパーに移動することで、ビューをどのように正確に簡略化できるかを理解するのは非常に困難です。たとえば、私はいつもあなたの見解の条件文がヘルパーへの抽出の主要な候補であることを読みましたが、これの例を実際に見つけることができず、これを達成するための私の試みは失敗しました。

たとえば、次のようなものがあるとします。

#index.html.erb

<% for beast in @beasts do -%>
  <% if beast.dead? -%>
    <%= beast.body %>
    <%= link_to "bury", bury_beast_path( :id => beast.id ) %>
  <% else -%>
    <%= beast.body %>
    <%= link_to "kill!", kill_beast_path( :id => beast.id ) %>
  <% end -%>
<% end -%>

これが私の見解にあるのは少し面倒ですが、代わりにこれをヘルパーにどのように正確に移動できますか?そして、可能であれば、それをさらに単純化します。(条件文が悪いことをどこかで読んだことがありますが、条件文なしで何かをプログラムする方法は私を超えています。)

別の例:フォーマットを使用しidbodyタグを作成する必要がありますcontroller_action。私がこれまでに得た最高のものはこれです:

#index.html.erb

<body id="<%= controller_action %>">

…そして…</p>

#application_helper.rb

def controller_action
  @id = @controller.controller_name + "_" + @controller.action_name
end

私は専門家ではありませんが、それでも私にとっては醜いです。

物事をより複雑にするために、ライアン・シンガーは私が好きなことを言いました。ERBを画像タグのように扱い、ヘルパーを使用して「意図を明らかにする」ことです。次に、次の息吹で、ヘルパーにHTMLを含めるべきではないと言って、それが地獄への道です。WTF?両方の互換性はどのようになっていますか?ビューで動作を宣言できるようになった場合、舞台裏でレンダリングされるHTMLがたくさんあるはずです。把握できません。

だから、基本的にはそれだけです。誰かがこれについていくつかの考えを共有することができるか、または私がこの主題についてのいくつかの良い詳細な読書を指摘することができれば幸いです-私はウェブ上で本当に弱い報道を持っていることがわかりました。私はすでにそれを使い果たしてグーグルで検索しましたが、誰が知っていますか。

4

4 に答える 4

27

リファクタリングにより、ビューの保守が容易になります。問題は、リファクタリングされたコードがどこに行くかを選択することです。

2つの選択肢は、パーシャルヘルパーです。どちらをどこで使用するかを規定する決まったルールはありません。ヘルパーにHTMLを含めるべきではないというガイドラインのように、いくつかのガイドラインが浮かんでいます。

一般に、パーシャルは、rubyよりもHTML / ERB/H​​AMLが多いセクションのリファクタリングに適しています。一方、ヘルパーは、最小限のHTMLを使用するか、パラメーターから単純なHTMLを生成するルビーコードのチャンクに使用されます。

ただし、ヘルパーにHTMLをまったく含めないようにする必要があるという感情には同意しません。少しは大丈夫です、ただそれをやり過ぎないでください。ヘルパーの処理方法は、大量のHTMLを生成するためのヘルパーの使用を妨げます。そのため、ヘルパーには最小限のHTMLが含まれていることが推奨されます。レールに同梱されているヘルパーのソースを見ると、ほとんどのヘルパーがhtmlを生成していることがわかります。そうでない少数は、主にパラメータを生成し、一般的な条件を評価するために使用されます。

たとえば、フォームヘルパーまたはlink_toバリアントは、いずれも最初のフォームのヘルパーに適合します。url_forやlogged_inのようなものは?さまざまな認証モデルによって提供されるものは、第2の種類です。

これは、ビューからパーシャルまたはヘルパーのどちらにコードを因数分解するかを決定するために使用する決定チェーンです。

  1. 単一の浅いhtmlタグを生成するステートメントの繰り返しまたはほぼ同一ですか?=>ヘルパー。
  2. 別のヘルパーの引数として使用される一般的な式?=>ヘルパー。
  3. 別のヘルパーの引数として使用される長い表現(4つ以上の用語)?=>ヘルパー。
  4. 4行以上のルビー(HTMLに評価されない)?=>ヘルパー。
  5. 他のほとんどすべて=>部分的。

例として、リファクタリングしようとしているコードを使用します。

私はこのように質問のビューをリファクタリングします:

app / helpers / beast_helper.rb:

def beast_action(beast)
  if beast.dead?
    link_to "bury", bury_beast_path(beast)
  else
    link_to "kill!", kill_beast_path(beast)
  end
end

app / views / beasts / _beast.html.erb:

<%= beast.body %>
<%= beast_action(beast) %>

app / views / beasts / index.html.erb:

<%= render :partial => "beast", :collection => @beasts %>

1ファイルと10行ではなく、3ファイルで、合計10行であるため、技術的に複雑です。ビューは、2つのファイルにまたがる3行を組み合わせたものになりました。最終結果は、コードがはるかに乾燥していることです。複雑さを最小限に抑えながら、他のコントローラー/アクション/ビューでその一部またはすべてを再利用できるようにします。

ボディタグIDも。実際にはcontent_for /yieldを使用する必要があります。そのようなことのために。

app / views / layouts / application.html.erb

...
<body id="<%= yield(:body_id) %>">
...

app / views / beasts / index.html.erb

<% content_for :body_id, controller_action %>
...

これにより、それを必要とする任意のビューでボディのIDをオーバーライドできます。例えば:

app / views / users / Preferences.html.erb

<% content_for :body_id, "my_preferences" %>
于 2010-02-03T20:54:58.273 に答える
8

私が最初にすることはこれです:

#index.html.erb
<%= render @beasts %>

#_beast.html.erb
<%= beast.body %>
<%= link_to_next_beast_action(beast) %>    

#beast_helper.rb
def link_to_next_beast_action(beast)
  if beast.dead?
    link_to "bury", bury_beast_path( :id => beast.id ) 
  else
    link_to "kill!", kill_beast_path( :id => beast.id )
  end
end

私がやったことは、獣のレンダリングをコレクションセマンティクスを使用するパーシャルに分離することです。

次に、kill/buryリンクを表示するためのロジックをビーストヘルパーに移動しました。このように、別のアクションを追加することにした場合(たとえば、「死から蘇らせる」)、ヘルパーを変更するだけで済みます。

これは役に立ちますか?

于 2010-02-03T20:36:59.653 に答える
1

3番目の選択肢は、 Cellsgemのビューモデルを使用することです。これは、Railsのビューレイヤーにオブジェクト指向をもたらす非常に人気のあるフレームワークです。

# app/cells/beast/cell.rb

class Beast::Cell < Cell::Concept
  def show
    return dead if model.dead?
    kill
  end

private
  def dead
    link_to "bury", bury_beast_path( :id => model.id ) 
    # you could render a view here, too!
  end

  def kill
    link_to "kill!", kill_beast_path( :id => model.id )
  end
end

次に、(ビューまたはコントローラーで)ヘルパーを使用してビューモデルをレンダリングします。

# app/views/beasts/index.erb

<%= concept(:beast, @beast).call %>
<%-# this returns the link content %>

それで全部です!別のテストで分離されたこのセルをテストできます。セルは、ビューレンダリング、ビュー継承、その他多くの機能も提供します。

kill例として、リンクのビューを使用できます。

# app/cells/beast/cell.rb

class Beast::Cell < Cell::Concept

  # ..

  def kill
    render :kill
  end
end

これにより、セルのキラービューがレンダリングされます。

# app/cells/beast/views/index.erb

<%= link_to "kill!", kill_beast_path( :id => model.id ) %>

ビューの場所に注意してください。セルディレクトリにうまくパッケージ化されています。

そして、はい、セルはHAMLおよびでサポートされている他のテンプレートエンジンを実行できますAbstractController

于 2014-06-23T23:10:43.917 に答える
0

もう1つの戦略は、テンプレートとヘルパーをまったく使用しないことです。レンダリングについては、次のことができます。

  1. render(:inline =>)を使用して、コントローラーから直接ビューをレンダリングします。それでもビューとコントローラーを正式に分離したい場合は、コントローラーに含めるモジュール/ミックスインを作成できます。
  2. または、独自のビュークラスを作成し、それらを使用して応答をレンダリングします。

この背後にある考え方は、ヘルパーとRails erbテンプレートシステムはOOPを利用しないため、1日の終わりに、各コントローラー/リクエストのニーズに応じて専門化する一般的な動作を定義できないということです。多くの場合、非常によく似たコードのチャンクを書き直すことになりますが、これはメンテナンスの観点からはあまり良くありません。

それでもいくつかのヘルパーメソッド(form_tag、h、raw、...など)が必要な場合は、それらをコントローラー/専用ビュークラスに含めるだけで済みます。

これを参照してください:rails-misapprehensions-helpers-are-shitは、楽しくて便利な記事です。

編集:完全なダッチのように聞こえないように、これを実装することは、アプリケーションの大きさ、およびコードを更新する必要がある頻度に依存すると思います。さらに、設計をプログラマー以外の人に委任している場合、プログラマーはコードを掘り下げる前にいくつかのプログラミングコースに参加している可能性があります。これは、テンプレート構文よりも直接理解しにくいことは確かです。

于 2013-06-10T18:50:18.617 に答える