Using form_with vs form_for vs form_tag

  

source code form.jpg

Prior to Rails 5.1, Rails provided 2 form helpers, form_for and form_tag. You use form_for with a model and form_tag for custom URLs. Both generate HTML for a form. There are only a few minor differences so Rails 5.1 combined the two. You should now be using form_with.

form_with can do what the two old methods can do. When you pass a model, it acts the same as form_for. For example, if you have a Message model,

<%= form_with model: Message.new do |form| %>
  <%= form.text_field :subject %>
<% end %>

would generate

<form action="/messages" method="post" data-remote="true">
  <input type="text" name="subject">
</form>

If you have an existing model, the form will have the values filled in and the action would contain the ID i.e. it would go to the show action on the controller.

# controller
# @message = Message.first 

<%= form_with model: @message do |form| %>
  <%= form.text_field :subject %>
<% end %>

The form is similar to the one above. Because @message is an existing object, the generated form is different.

<form action="/messages/1" method="post" data-remote="true">
  <input type="hidden" name="_method" value="patch">
  <input type="text" name="message[subject]" value="<the subject of the message>">
</form>

If you don't pass a model, form_with behaves like form_tag.

<%= form_with url: messages_path do |form| %>
  <%= form.text_field :subject %>
<% end %>

would generate

<form action="/messages" method="post" data-remote="true">
  <input type="text" name="subject">
</form>

Options

form_with submits are remote by default (data-remote="true"). You can change this by using local: true. This is the opposite from the old methods where the default is local and you have to specify remote: true to make it remote.

<%= form_with(model: Message.new, local:true) do |form| %>
  <%= form.text_field :subject %>
<% end %>

You can also specify options available with form_for and for_tag like id, class, html, and data.

<%= form_with(model: Message.new, data: { behavior: "autosave" }, html: { name: "go" }) do |form|
  <%= form.text_field :subject %>
<% end %>

Free Ebook: PaaS Is Dead

Platform as a Service (PaaS) is experiencing a digital transformation, and despite what some may argue, it’s far from dead. Learn why PaaS continues to prove it has a promising future for DevOps.

PaaS Is Dead

Related posts

Ruby on Rails vs PHP

May 16, 2018

There’s more than one way to build a web application. No matter what type of application you are

Read More

What to Look for When Considering Application Hosting

May 8, 2018

Cloud computing has made hosting business-critical applications easier and less expensive.

Read More

5 Commercial Use Cases Continue to Prove the Value of Ruby on Rails

April 11, 2018

Ruby on Rails continues to gain popularity as an effective platform for developing web and

Read More

Christopher Rigor

 
Christopher Rigor is a Senior Technical Evangelist at Engine Yard. He’s a long time Rails user, system administrator, and recently became a contributor of RailsInstaller. Previously, he was the DevOps Support Manager for Asia-Pacific at Engine Yard.
Find me on:

Comments

Subscribe Here!