Views, layouts and partials

Ruby on Rails · Essentials · 12 min

Views are what users see, and partials and helpers keep them consistent and DRY.

Views are ERB templates in app/views/<controller>/<action>.html.erb. <%= expr %> outputs the result, HTML-escaped by default, which protects against XSS. <% code %> runs Ruby without output, for loops and conditionals. Avoid raw and html_safe on user input.

The layout app/views/layouts/application.html.erb wraps every page; <%= yield %> marks where the action's template goes. Templates can fill named regions with content_for :title and the layout reads them with yield :title.

Partials are reusable fragments whose file names start with an underscore: _article.html.erb. Render one with <%= render "form", article: @article %> or, for a collection, <%= render @articles %>, which renders articles/_article once per record with a local article. Collection rendering is faster than looping and calling render yourself.

Helpers are Ruby methods available in views:

  • link_to "Edit", edit_article_path(@article) and button_to "Delete", @article, method: :delete.
  • image_tag, time_ago_in_words, pluralize(3, "comment"), number_to_currency, truncate, simple_format.
  • Your own in app/helpers.

Show flash messages in the layout with notice and alert. Use dom_id(@article) for consistent element ids, which Turbo uses as well. Keep logic out of views: compute data in the controller or a model method and give the view simple values.

Example

<%# app/views/layouts/application.html.erb %>
<html>
  <head><title><%= content_for(:title) || "Blog" %></title></head>
  <body>
    <% if notice %><p class="notice"><%= notice %></p><% end %>
    <%= yield %>
  </body>
</html>

<%# app/views/articles/index.html.erb %>
<% content_for :title, "All articles" %>
<h1>Articles (<%= pluralize(@articles.size, "article") %>)</h1>
<%= render @articles %>   <%# renders _article.html.erb for each %>
<%= link_to "New article", new_article_path %>

<%# app/views/articles/_article.html.erb %>
<article id="<%= dom_id(article) %>">
  <h2><%= link_to article.title, article %></h2>
  <p><%= truncate(article.body, length: 120) %></p>
  <small><%= time_ago_in_words(article.created_at) %> ago</small>
</article>

Remember

  • <%= %> outputs escaped HTML; <% %> runs code
  • Layouts wrap pages via yield; partials (_name) are reusable fragments
  • render @collection renders a partial per record efficiently

Watch out for

  • Calling html_safe or raw on user-supplied content, which disables escaping and allows XSS.

Check yourself

  1. What does <%= render @articles %> do?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: guides.rubyonrails.org/layouts_and_rendering.html