2017-10-26 5 views
0

私が行っていることを達成するためのより良い方法はありますか?セミグローバルレール部分

  • /views/shared/フォルダには、電子メールの送信に使用されているフォームのすべてのフィールドが含まれています。
  • 上記部分(render partial: 'shared/email_fields' locals: localsここでlocalsはデフォルト変数のハッシュです)をレンダリングするデフォルトのオプションを持つヘルパーメソッドです。
  • 上記のヘルパーメソッドを呼び出し、FormBuilderオブジェクトまたはname html属性の先頭を含む文字列を渡す電子メールを送信するすべてのフォームのヘルパーメソッドです。

私がいる問題:電子メールフォームのほとんどはlocalsハッシュに追加のオプションを追加し、グローバルな部分が肥大化になってきているように私は感じるようになる私にもたらされる若干異なります。このようにグローバルなパーシャルを使用する方法はありますか?

私はそれぞれのフォームを完全に別々にすることを考えましたが、それは維持とDRYには悪いことです。私はグローバルパーシャルの中でレンダリングされるパーシャルの名前を渡すことを考えましたが、これらのフォームのいくつかは同じオプションを必要とし、異なるコントローラからレンダリングされます。グローバルは/views/shared/フォルダにあります。今、私は肥大化したグローバル部分に固執しています。

助けていただけたら幸いです!

答えて

1

ここで私はそれをやっています。これは奇妙に聞こえるだろうが、私と一緒に耐える。

私のアプリケーションには基本的に2つの形式があります。 javacriptを使用して送信するフォームについては、次のようになります。

#views/shared/_remote_form.html.haml 

= form_tag @presenter.form_path, 
    remote: true, 
    id: @presenter.form_id, 
    class: @presenter.form_classes, 
    data: @presenter.form_data, 
    method: @presenter.form_method do 
    .well 
     = @presenter.form_inner 
     .form-controls-container 
     .form-controls-wrapper 
      = @presenter.form_controls 

ご覧のとおり、私はプレゼンターを使用しています。プレゼンターは、関連するコントローラー内でコントローラー変数としてインスタンス化され、プレゼンターが部分的に使用できるようになります。次のようなものがあります:

プレゼンターがフォームのさまざまな部分をレンダリングできるように、コントローラを渡しています。

すべてFormPresentersは、フォームで呼び出される各メソッドのスタブ付きメソッドを持つFormPresenterBaseから継承します。このようなもの:

class FormPresenterBase 

    def initialize(controller) 
    @controller = controller 
    end 

    def form_path 
    root_path 
    end 

    def form_id 
    'bogus-form-id' 
    end 

    def form_classes 
    'something-bogus' 
    end 

    def form_inner; end 

    def form_controls; end 

    ... 

end 

私はエラーの束を常に投げずにフォームをブートアップします。当然ながら、スタブされたフォームは実際には機能しませんが、各FormPresenterがスタブされたメソッドを実際の値でオーバーライドするので大丈夫です。したがって、次のようなものがあります。

class NewFooFormPresenter < FormPresenterBase 

    def form_path 
    new_for_form_path 
    end 

    def form_id 
    'new-foo-form' 
    end 

    def form_classes 
    'something-not-bogus' 
    end 

    # The form fields could be unique to this form. Or, I might have a set of common 
    # fields that I use across multiple forms. I just decide which partial has the 
    # correct set of fields and render it here. 
    def form_inner 
    render partial: 'new_inner_fields' 
    end 

    # The controls are also rendered from partials. Here, I want to have an okay 
    # button and a cancel button. So, I just call the correct partial that 
    # renders those. I call html_safe on the resultant string so that it renders 
    # correctly. 
    def form_controls 
    [:okay, :cancel].each_with_object("") do |control_sym, to_return| 
     render partial: "shared/form_widgets/#{control_sym.to_s}_button" 
    end.html_safe 

    end 

    ... 

end 

もちろん、私は自分のFormPresentersで扱いにくいことがあります。共通のメソッドを共有するファミリがある場合は、すべてをDRYに保つために継承またはモジュールの追加を使用できます。

基本的なフォームウィジェット(フィールドの組み合わせ、コントロールなど)をすべてパーシャルとして設定したら、プレゼンターでミックスして自分の心に喜ばせることができます。そして、(少なくともフォームのために)、私は基本的に、残りの人生のために別の部分を書く必要はありません。私は新しい変種が必要なときはいつでも、私は新しいFormPresenterをスピンアップし、それをカスタマイズして私が望むフォームを与える。

実際には、それよりももう少し多くのことがありますが、うまくいけば、これはあなたに猫を肌に触れる別の方法の感覚を与えます。

+0

これはRails 5のものですか? (私たちは4.2.5にしかいません)以前はプレゼンターやプレゼンターの話は聞いたことがありません。 –

+0

いいえ、「プレゼンター」はパターンです。それらは普通の古いルビーオブジェクトです。 Ryan Bates氏は、このトピックについてかなり優れた入門的なRails Castを持っています。最近私は、アプリケーションをさらにコンポーネント化するために、 'Widget'という新しいカスタムPOROクラスを作成しました。しかし、それはまったく狂った話です。 – jvillian

+1

これは最初は非常に奇妙に思えましたが、Rails Castを見てから、これがどうなるのでしょうか。情報をありがとう! –

0

アプローチは、各フォームに対して別々の部分を持つことです。フォームに共通する項目をすべて取り、部分的に配置します。その後、個々のフォームパーシャル内の「共通アイテム」部分を参照することができます。あなたのフォームがどのように構造化されているかにもよりますが、いくつかの「共通アイテム」部分があるかもしれませんが、それは問題ありません。目標は、コードを整理してDRYに保つことです。