Benito Serna Tips and tools for Ruby on Rails developers

A form with two buttons with formation and formmethod

June 8, 2023

Imagine that you are building a custom CMS. Within the form to edit an Article, you need to have two buttons: a normal “Save” button and a new “Save and publish” button. And maybe, additionally, you will need a third button to delete the article.

To achieve this, you can use the formaction and formmethod attributes.

Changing the action with formaction

To add the “Save and publish” button, use the formaction attribute to override the action in the form:

<%= form_with model: article do |form| %>
  ...
  <%= form.button "Save" %>
  <%= form.button "Save and publish", formaction: save_and_publish_article_path %>
<% end %>

This sends the form, along with all the field information, to the path you defined in formaction. To process the information in a new controller action, define a route:

resources :articles do
  patch :save_and_publish, on: :member
end

Then, create the new controller action:

def save_and_publish
  if @article.update_and_publish(article_params)
    redirect_to article
  else
    render :edit, status: :unprocessable_entity
  end
end

Changing the method with formmethod

To add the “Delete” button, use the formmethod attribute to let HTML override the declared method attribute:

<%= form_with model: article do |form| %>
  ...
  <%= form.button "Save" %>
  <%= form.button "Delete", formmethod: :delete, data: { confirm: "Are you sure?" } %>
<% end %>

Most browsers don’t support overriding form methods declared through formmethod other than “GET” and “POST”. Rails works around this issue by emulating other methods over POST through a combination of formmethod, value, and name attributes.

<form accept-charset="UTF-8" action="/articles/1" method="post">
  <input name="_method" type="hidden" value="patch" />
  <input name="authenticity_token" type="hidden" value="..." />
  <!-- ... -->

  <button type="submit" name="button">Save</button>
  <button type="submit" formmethod="post" name="_method" value="delete" data-confirm="Are you sure?">Delete</button>
</form>

Related articles

Weekly tips and tools for Ruby on Rails developers

I send an email each week, trying to share knowledge and fixes to common problems and struggles for ruby on rails developers, like How to fetch the latest-N-of-each record or How to test that an specific mail was sent or a Capybara cheatsheet. You can see more examples on Most recent posts or All post by topic.