RoR Views and ERB Templates

Views are the HTML pages your users actually see in their browsers. In Rails, views use a format called ERB (Embedded Ruby) that lets you mix Ruby code directly inside HTML. ERB templates have the file extension .html.erb.

ERB: Two Tags You Need to Know

<% Ruby code here %>
  → Runs the Ruby code. Produces NO output on the page.
  → Use for: if/else, loops, variable assignment

<%= Ruby code here %>
  → Runs the Ruby code AND prints the result to the page.
  → Use for: displaying values, calling methods that return text

Think of it this way:

<%  %>  = "Do this but don't show it"
<%= %>  = "Do this AND show the result"

A Basic ERB View

app/views/articles/index.html.erb

<h1>All Articles</h1>

<% if @articles.empty? %>
  <p>No articles yet.</p>
<% else %>
  <% @articles.each do |article| %>
    <div>
      <h2><%= article.title %></h2>
      <p><%= article.body %></p>
      <p>Written on: <%= article.created_at.strftime("%B %d, %Y") %></p>
    </div>
  <% end %>
<% end %>

How ERB Renders

ERB Template:
  <h2><%= article.title %></h2>

Ruby evaluates: article.title = "My First Post"

Final HTML sent to browser:
  <h2>My First Post</h2>

The browser never sees ERB tags. It only receives the final rendered HTML.

The Application Layout

Every view is wrapped inside the application layout. This layout holds the parts that appear on every page: the header, navigation, and footer.

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>My Blog</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag "application" %>
  </head>
  <body>
    <nav>
      <a href="/">Home</a>
      <a href="/articles">Articles</a>
    </nav>

    <main>
      <%= yield %>       ← your view content appears here
    </main>

    <footer>
      <p>Copyright 2024</p>
    </footer>
  </body>
</html>

The yield keyword is the slot where Rails inserts your view's content. The layout provides the shell; each view provides the content inside it.

View Diagram: Layout + View

Browser Request
      |
      v
Layout (application.html.erb)
  +------------------------------+
  |  <nav> ... </nav>            |
  |                              |
  |  <main>                      |
  |    +----------------------+  |
  |    |   yield              |  |
  |    |  (your view goes in) |  |
  |    |                      |  |
  |    | articles/index.erb   |  |
  |    +----------------------+  |
  |  </main>                     |
  |                              |
  |  <footer> ... </footer>      |
  +------------------------------+
      |
      v
Complete HTML sent to Browser

Displaying Data Safely

Rails automatically escapes HTML characters when you use <%= %>. This protects against XSS (Cross-Site Scripting) attacks where a user might try to inject HTML or JavaScript into your pages.

User stored: <script>alert("hack")</script>

<%= user.name %>
Renders as: &lt;script&gt;alert("hack")&lt;/script&gt;
Browser shows it as text, NOT as a script.

If you intentionally want to output raw HTML (from trusted sources only), use raw or html_safe. Never do this with user-submitted content.

View Helpers

Rails provides built-in helper methods to generate common HTML elements cleanly.

Link:
<%= link_to "Read More", article_path(@article) %>
Renders: <a href="/articles/3">Read More</a>

Image:
<%= image_tag "logo.png", alt: "Site Logo" %>
Renders: <img src="/assets/logo.png" alt="Site Logo">

Truncate long text:
<%= truncate(article.body, length: 100) %>
Renders: First 100 characters followed by "..."

Format dates:
<%= article.created_at.strftime("%b %d, %Y") %>
Renders: Jan 10, 2024

Conditional Display

<% if current_user %>
  <p>Welcome, <%= current_user.name %></p>
  <%= link_to "Log Out", logout_path, method: :delete %>
<% else %>
  <%= link_to "Log In", login_path %>
<% end %>

Looping Through Collections

<ul>
  <% @products.each do |product| %>
    <li>
      <%= product.name %> — $<%= product.price %>
    </li>
  <% end %>
</ul>

Instance Variables vs Local Variables in Views

Variable TypeDefined InAvailable In View
@article (instance)ControllerYes
article (local)ControllerNo
article (local in loop)The view's each loopYes (within the loop only)

Custom View Helpers

Write your own helper methods in app/helpers/ to avoid repeating complex logic in views:

app/helpers/articles_helper.rb

module ArticlesHelper
  def reading_time(text)
    words = text.split.size
    minutes = (words / 200.0).ceil
    "#{minutes} min read"
  end
end

Use it in any view:

<p><%= reading_time(@article.body) %></p>

Views keep your users engaged and informed. Keep them simple — display data, use loops and conditionals, and delegate any complexity to models or helpers.

Leave a Comment

Your email address will not be published. Required fields are marked *