Rails Helpers (link_to, imag_tag, and form_for) 2020
We can use any HTML code we want for view, however, Rails includes a number of built-in methods called helpers. They create HTML for us so we can write Ruby and let Rails generate the HTML.
So, instead of writing:
<a href = 'URL'>Text to be linked</a>
We can use the Rails link_to helper, like this:
<%= link_to 'Text to be linked', 'URL' %>
Though this doesn't do too much for us, we can leave out some of the HTML code.
The link_to helper is more interesting when we use it to help us generate the URL, instead of specifying it explicitly.
For example, we can specify the controller and action we want the link to invoke, and any parameters that we want to pass to it, and let the link_to generate the URL dynamically:
<%= link_to 'View Post', :controller => 'post', :action => 'view_post', :id => post.id %>
Here is an example from the "blog" app in Getting Started with Rails.
In app/views/welcome/index.html.erb file, we have the link_to method:
<h1>Hello, Rails!</h1> <%= link_to 'My Blog', controller: 'articles' %>
The link_to method is one of Rails' built-in view helpers. It creates a hyperlink based on text to display and where to go - in this case, to the path for articles.
Let's add links to the other views as well, starting with adding this "New Article" link to app/views/articles/index.html.erb, placing it above the <table> tag:
<h1>Listing articles</h1> <%= link_to 'New article', new_article_path %> <table> <tr> <th>Title</th> <th>Text</th> </tr> <% @articles.each do |article| %> <tr> <td><%= article.title %></td> <td><%= article.text %></td> </tr> <% end %> </table>
Now, add another link in app/views/articles/new.html.erb, underneath the form, to go back to the index action:
<%= form_for :article, url: articles_path do |f| %> <p> <%= f.label :title %><br> <%= f.text_field :title %> </p> <p> <%= f.label :text %><br> <%= f.text_area :text %> </p> <p> <%= f.submit %> </p> <% end %> <%= link_to 'Back', articles_path %>
Finally, add a link to the app/views/articles/show.html.erb template to go back to the index action as well, so that people who are viewing a single article can go back and view the whole list again:
<p> <strong>Title:</strong> <%= @article.title %> </p> <p> <strong>Text:</strong> <%= @article.text %> </p> <%= link_to 'Back', articles_path %>
Another common helper is image_tag. Instead of using:
<img src = '/images/filename'>
we can write Ruby code that looks like this:
<%= image_tag 'filename' %>
Rails assumes, by default, that all images are in a directory called images, so we don't need to include the directory as part of the filename.
The "blog" app which is a sample used in this section is available Getting Started with Rails.
To create a form within a template, we will use a form builder. The primary form builder for Rails is provided by a helper method called form_for:
<%= form_for :article do |f| %> <p> <%= f.label :title %><br> <%= f.text_field :title %> </p> <p> <%= f.label :text %><br> <%= f.text_area :text %> </p> <p> <%= f.submit %> </p> <% end %>
When we call form_for, we pass it an identifying object for this form. In this case, it's the symbol :article. This tells the form_for helper what this form is for.
Inside the block for this method, the FormBuilder object (f) is used to build two labels and two text fields, one each for the title and text of an article.
Finally, a call to submit on the f object will create a submit button for the form.
If we inspect the HTML that is generated, by viewing the source of the page, we will see that the action attribute for the form is pointing at /articles/new:
<form action="/articles/new" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="kwwp33Mi/eAv4lHCB1a3nbNVFb9P0F3Uk4hIA54K/IXnFwFCoHpFYETHnm/BoSRJKzNnxOz827Y3k96LCnDMmA==" />
This is a problem because this route goes to the very page that we're on right at the moment, and that route should only be used to display the form for a new article.
So, the form needs to use a different URL in order to go somewhere else. This can be done quite simply with the :url option of form_for.
Typically in Rails, the action that is used for new form submissions like this is called "create", and so the form should be pointed to that action.
So, we need to edit the form_for line inside app/views/articles/new.html.erb to look like this:
<%= form_for :article, url: articles_path do |f| %>
Here, we're passing the articles_path helpert o the :url option.
Let's look at the output from rake routes:
The articles_path helper tells Rails to point the form to the URI Pattern associated with the articles prefix; and the form will (by default) send a POST request to that route. This is associated with the create action of the current controller, the ArticlesController.
With the form and its associated route defined, we will be able to fill in the form and then click the submit button to begin the process of creating a new article.
However, when we submit the form, we'll get an error which says we need to have the create action which is saving our new article to the database.
When a form is submitted, the fields of the form are sent to Rails as parameters. These parameters can then be referenced inside the controller actions, typically to perform a particular task.
To see what these parameters look like, change the create action to this:
def create render plain: params[:article].to_json end
At "Save Article", we get:
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization