web-dev-qa-db-ja.com

Railsの同じフォームに複数の送信ボタンを作成するにはどうすればよいですか?

複数の送信ボタンが必要です。

Contact_Callのインスタンスを作成するフォームがあります。

1つのボタンで通常どおり作成されます。

もう1つのボタンはそれを作成しますが、デフォルトとは異なる:attribute値を持つ必要があり、コントローラーで使用される別の関連するモデルに属性を設定する必要もあります。

それ、どうやったら出来るの?ルートを変更できないので、[:params]によって取得される別の変数を送信する方法はありますか?

そして、その場合、コントローラーで何をし、caseステートメントを設定しますか?

91
Timothy T.

複数の送信ボタンを作成し、それぞれに異なる値を提供できます。

<% form_for(something) do |f| %>
    ..
    <%= f.submit 'A' %>
    <%= f.submit 'B' %>
    ..
<% end %>

これは出力します:

<input type="submit" value="A" id=".." name="commit" />
<input type="submit" value="B" id=".." name="commit" />

コントローラー内では、送信されたボタンの値はパラメーターcommitによって識別されます。値を確認して、必要な処理を実行します。

def <controller action>
    if params[:commit] == 'A'
        # A was pressed 
    elsif params[:commit] == 'B'
        # B was pressed
    end
end

ただし、これにより、ビューがコントローラーに緊密に結合されることに注意してください。

125
Anurag

また、送信ボタンでformaction属性を使用する別のアプローチもあります。

<% form_for(something) do |f| %>
    ...
    <%= f.submit "Create" %>
    <%= f.submit "Special Action", formaction: special_action_path %>
<% end %>

標準の作成ボタンは変更する必要がないため、コードはクリーンなままです。特別なボタンのルーティングパスを挿入するだけです。

formaction:
入力要素が送信ボタンまたは画像である場合、入力要素によって送信された情報を処理するプログラムのURI。指定されている場合、要素のフォームの所有者のアクション属性をオーバーライドします。ソース: [〜#〜] mdn [〜#〜]

60
patpir

または、どのボタンが押されたかを認識して、属性名を変更できます。

<% form_for(something) do |f| %>
    ..
    <%= f.submit 'A', name: 'a_button' %>
    <%= f.submit 'B', name: 'b_button' %>
    ..
<% end %>

params[:commit]値を単にチェックするのではなく、paramsキーの存在をチェックする必要があるため、少し不快です。どちらが押されたかに応じてparams[:a_button]またはparams[:b_button]を受け取ります。

29
masciugo

Gemを使用せずに@ vss123によって提案されたものと同様のソリューション:

resources :plan do
  post :save, constraints: lambda {|req| req.params.key?(:propose)}, action: :propose
  post :save, constraints: lambda {|req| req.params.key?(:finalize)}, action: :finalize
end

多くの場合、送信ボタンの値は国際化/翻訳されているため、値の使用を避け、代わりに入力名を使用しています。また、ルートファイルがすぐに乱雑になるため、これを使いすぎないようにします。

12

Railsで 高度な制約 を使用して解決しました。

考え方は同じパス(したがって同じ名前のルートとアクション)を持ち、制約は異なるアクションにルーティングすることです。

resources :plan do
  post :save, constraints: CommitParamRouting.new("Propose"), action: :propose
  post :save, constraints: CommitParamRouting.new("Finalize"), action: :finalize
end

CommitParamRoutingは、matches?メソッドを持つ単純なクラスです。このメソッドは、コミットパラメーターが指定されたインスタンスattrに一致する場合にtrueを返します。値。

これはgem commit_param_matching として利用可能です。

9
siliconsenthil

古い質問ですが、同じ状況に対処しているので、解決策を投稿すると思いました。コントローラーロジックとビューボタンの間に矛盾が生じないように、コントローラー定数を使用しています。

class SearchController < ApplicationController
  SEARCH_TYPES = {
    :searchABC => "Search ABCs",
    :search123 => "Search 123s"
  }

  def search
    [...]
    if params[:commit] == SEARCH_TYPES[:searchABC]
      [...]
    elsif params[:commit] == SEARCH_TYPES[:search123]
      [...]
    else
      flash[:error] = "Search type not found!"]
      [...]
    end
  end
  [...]          
end

そして、ビューで:

<% form_for(something) do |f| %>
    [...]
    <%= f.submit SearchController::SEARCH_TYPES[:searchABC] %>
    <%= f.submit SearchController::SEARCH_TYPES[:search123] %>
    [...]
<% end %>

このように、テキストは1つの場所にのみ存在します-コントローラーの定数として。ただし、これをどのようにi18nするかについてはまだ考えていません。

3
Draknor

Nested_form_fieldsのおかげでフォーム上に可変数の送信ボタンがあるため、名前を使用するだけでは十分ではありませんでした。最終的にフォームに非表示の入力フィールドを含め、フォーム送信ボタンの1つが押されたときにJavascriptを使用して入力しました。

1
Shawn Walton