Rails:在一个表单中多次提交button

说我有一个文章模型,并在文章“新”视图中,我有两个button,“发布”和“保存草案”。

我的问题是如何知道在控制器中单击哪个button。

我已经有了一个解决scheme,但是我认为必须有一个更好的方法。 我目前使用的观点是:

<div class="actions"> <%= f.submit "Publish" %> <%= f.submit "Save Draft", :name => "commit" %> </div> 

所以在控制器中,我可以使用params [:commit]string来处理这个动作。

 def create @article = Article.new(params[:article]) if params[:commit] == "Publish" @article.status = 'publish' // detail omitted end @article.save end 

但我认为使用视图相关的string是不好的。 你能告诉我另一种方法来完成这个吗?

更新 :由于这些button是在相同的forms,他们都去“创build”的行动,这对我来说是好的。 我想要的是在创build行为中处理这个问题,比如给文章模型一个“状态”栏,并保留“公开”或“草稿”。

Railscast第38集中介绍了这一点。 使用params散列来检测哪个button被点击是正确的方法:

视图:

 <%= submit_tag 'Create' %> <%= submit_tag 'Create and Add Another', name: 'create_and_add' %> 

控制器:

 if params[:create_and_add] # Redirect to new form, for example. else # Redirect to show the newly created record, for example. end 

我们解决了在rails中使用高级约束 。

这个想法是有相同的path(因此有相同的命名路线和行动),但约束路由到不同的行动。

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

CommitParamRouting是一个简单的类,有一个matches?的方法matches? 如果提交参数匹配给定的实例attr,则返回true。 值。

这可以作为一个gemcommit_param_matching 。

它也可以在form_for这样的帮手上完成

  <%= f.submit "Publish",name: "publish", class: "tiny button radius success" %> <%= f.submit 'Mark as Draft', name: "draft", class: "tiny button radius " %> 

和控制器上的逻辑是一样的

  if params[:publish] // your code elsif params[:draft] // your code end 

我记得曾经遇到过这个问题。 你不能保留两个button,然后根据params [:commit]调用一些操作。 提交buttononclick打算调用表单引用的url。 有一些不好的方法来获得所需的行为。 保持一个button来调用表单引用的动作,并获得另一个button来调用一个动作,我使用了一个link_to,然后改变了样式来匹配一个button。 此外,也可以使用jQuery来更改表单将调用的url,从而决定在运行时调用哪个操作。 希望这可以帮助。

您还可以在提交button上设置一些data属性,并使用JavaScript来更改form操作,只需单击其中一个button即可

通常我使用John Topley给出的build议(见上面的答案)。 另一种方法是使用JQuery / JS改变表单动作属性 – 点击提交button的例子:

 form_tag({} ,:method => 'post', :id => 'reports_action') do ....... ....... submit_tag 'submit', :onclick => "return changeAction();" end 

接着 …..

 function changeAction(){ $('#reports_action').attr('action','my_new_action'); }