Submit same form to different actions

2019-07-14 00:26发布

问题:

Depending on which submit button a user selects, (Cat and Dog in this case), I'd like to submit the form to the right controller action using the right http verb.

In this case, there is one text input. If the user presses Cat I'd like to POST to Cats#create and if Dog to PUT to Dogs#update.

How would I build the form?

Edit

Using the formaction attribute I'm able to PUT to Dogs#update

<%= form_for(cat) do |f| %>

  <div class="field">
    <%= f.label :name %>
    <%= f.text_field :name %>
  </div>


  <div class="actions">
    <%= f.submit "Cat" %>
    <%= f.submit "Dog", formaction: dog_path(Dog.first) %>
    <%#= f.submit "Cat", name: 'route_to[cat]' %>
    <%#= f.submit "Dog", name: 'route_to[dog]' %>
  </div>
<% end %>

The problem is I want to POST to Dogs#create, is this possible with formaction?

Edit

There is a railscast about building the logic the controller based on the name of the button pressed. But I want to put the logic about which HTTP verb, controller, and action in the submit button itself. Is this possible?

回答1:

You could create the simple form with some fields and submit button. And then create similar form but with hidden fields which will be filled when user fills the first form's fields (use javascript for that) and visible submit button. So user fills the first form visible fields, javascript code copies the values to the second form's corresponding hidden fields. User has two submits to click on. For @items you could have hidden fields too and manually set fields' values within @items values.

Or an alternative solution which works in my project and could fit your needs probably. To use it you need to introduce some condition which will "decide" what controller and action should be used.

Your view:

<% if condition %>
  <%= form_tag controller: "foos", action: "create", method: :post %>
  <%= render partial: 'form', locals: {button_name: "Foo"} %>
<% else %>
  <%= form_tag controller: "bars", action: "update", method: :put do %>
  <%= render partial: 'form', locals: {button_name: "Bar"} %>
<% end %>

Your _form partial:

<%# Your form and @items fields %>    
<%= submit_tag button_name %>

That solution gives you one single form and submit button for this form. What form it will be (for Foos or Bars) depends on condition.



回答2:

In this case creating a Cat and updating a Dog were related enough that it makes sense to handle both in the CatsController with a case statement and use a :name attribute on on the submit button.

For example:

app/views/cats/new.html.erb:

<%= form_tag(cats_path, multipart: true, role: "form") do %>
  <%= button_tag 'Cat', name: 'route_to[cat]'%>
  <%= button_tag 'Dog', name: 'route_to[dog]' %>
<% end %>

app/controllers/cats_controller.rb:

def create
  case route_to params
  when :cat
    # create a cat
  when :dog
    # update a dog
  end
end
.
.
.
private

  def route_to params
    params[:route_to].keys.first.to_sym
  end