A web application is all about posting and retrieving data. You go to Twitter, and follow somebody, you posted data at Twitter. You like a Facebook page; you posted data at Facebook servers. Even if you simply log in, it also means you posted data like the IP you singed in from, the time at which you signed in and the things like that. Posting data is much crucial in web applications that HTML provides us a tag for it called form that is exclusively used for posting and getting data from the remote servers.
Let’s take a look at a very simple form tag in HTML, and see how it does its job:
<form method='POST' action='/users'> <label name='first_name'>First Name:</label> <input type='text' name='first_name' id='first_name'><br> <label name='last_name'>Last Name:</label> <input type='text' name='last_name' id='last_name'><br> <label name='number'>Age:</label> <input type='age' name='age' id='age'><br> <input type='submit' value='Create User'> </form>
It will render the following view in HTML:
This form will work properly, and will submit the data to the action value, in our case /users , but to create a form like this always from scratch is a kind of pain, and Rails – like always – is here to rescue us. Let’s have a look at the options provided by Rails to generate a from tag through helper methods:
form_for is a helper method to generate a form tag, but it is strictly associated with models in Rails. You can only specify the fields that actually exist at the database level. Let’s say we have a table called users in our database:
This implies that we can only specify these fields in form_for , and nothing else.
<%= form_for @user do |f| %> <%= f.label :first_name %> <%= f.text_field :first_name %><br> <%= f.label :last_name %> <%= f.text_field :last_name %><br> <%= f.label :age %> <%= f.number_field :age %><br> <%= f.submit 'Create User' %> <% end %>
As you can see that we can only create those fields that exist in our database, and form_for automatically automagically infers the action value from the state of @user .
If @user is a new object, the form will be submitted to /users with the POST request, and if @user already exists in the database, it will post the form to /users/<:id> , where <:id>
refers to the id of the @user object in the database with PUT or PATCH method.
Here’s a summary of what we can/can’t do with form_for :
- We can’t use form_for for a field that doesn’t exist the table like if we want a form for search functionality in the users, we’d have to go for other option.
- In form_for , we nearly never have to specify the method and url options, it saves us space and time.
- form_for works smoothly for nested resources: it automagically infers the things for us.
- In case of editing @user , we can use the same form , and it will come filled with the values that exist in database.
- It automatically wraps the name s for our fields like user[first_name] , user[last_name] , something we would have to do ourselves in other cases.
Though it requires us to pass the url and method , but is far more flexible than form_for . We can use whatever field we would like to post to server unlike form_for in which we have to specify only fields that belong to a model. For example:
<%= form_tag "/search", method: 'POST' %> <%= label_tag(:q, "Search for:") %> <%= text_field_tag(:q) %> <%= submit_tag("Search") %> <% end %>
As you can see that we manually have to provide url and method . Also, We would get data at the server through params[:q], not like params[:user][:q], because form_tag sends the data in plain, unlike form_for which wraps the thing in the model name.
So here’s a summary of the points for form_tag usages:
- form_tag can send values that do not exist in your table.
- form_tag is great for building search form. If we had to do the same thing in form_for, we would have to have a model called Search first.
- We can generate all the input tags that we could generate in form_for , so form_tag is equivalent to form_for in generating input tags.
- While editing something, we need to fill the form_tag with appropriate values ourselves, something that form_for manually did for us.
So as you can see that form_for is great for creating and editing models, while form_tag handles the non-table fields like search and other query parameters. Which one to use really depends on your web application and its needs, but choosing an efficient method will surely save you time and extra lines of you code in your application.