Question

ERB Tags in Rails: Difference Between <% %>, <%= %>, <%# %>, and -%>

rubyruby-on-railstemplateserb

Question

In a Rails ERB template, what is the difference between these tags, and when should each one be used?

<% %>
<%= %>
<% -%>
<%# %>

I would like a clear explanation of what each form does, especially how they affect output in the rendered HTML.

Short Answer

By the end of this page, you will understand how ERB tags work in Rails templates, which tags produce output, which tags only run Ruby code, how ERB comments behave, and what -%> does when trimming whitespace or newlines.

Concept

ERB stands for Embedded Ruby. It lets you write Ruby inside a text template, usually HTML in a Rails view.

The main idea is simple:

  • some ERB tags run Ruby code without showing anything
  • some tags run Ruby code and insert the result into the page
  • some tags are comments
  • some closing forms affect whitespace and newlines

Here are the core forms:

  • <% ... %>: execute Ruby code, but do not print the result
  • <%= ... %>: execute Ruby code and output the result into the template
  • <%# ... %>: ERB comment, ignored by ERB
  • -%>: a variation of the closing tag used to trim a newline or surrounding whitespace depending on ERB configuration and usage

This matters because Rails views are not just static HTML. They often contain:

  • loops
  • conditionals
  • helper calls
  • partial rendering
  • dynamic content

Choosing the right tag controls whether your Ruby logic affects the final HTML output or only the template flow.

Mental Model

Think of an ERB template like a theater script:

  • <% ... %> is a stage direction: it tells the actors what to do, but the audience does not hear it.
  • <%= ... %> is a spoken line: it becomes part of what the audience sees or hears.
  • <%# ... %> is a note in the script: only for the writer, not used in the performance.
  • -%> is a cleanup instruction: it helps remove an extra blank line or unwanted spacing after the tag.

So the biggest question is always: Do I want this Ruby code to appear in the final HTML, or just control the template?

Take Quiz

Syntax and Examples

Core syntax

<% ruby_code %>
<%= ruby_expression %>
<%# comment %>
<% ruby_code -%>

1. <% %> — run Ruby without output

Use this for logic such as if, each, variable assignment, or setup.

<% items = ["Apple", "Banana", "Cherry"] %>
<% items.each do |item| %>
  <li><%= item %></li>
<% end %>

What happens?

  • items = [...] runs, but does not print anything
  • each do and end control the loop, but do not print anything
  • <%= item %> prints each item inside the <li>

Rendered output:

<li>Apple</li>
<li>Banana</li>
<li>Cherry</li>

2. <%= %> — run Ruby and output the result

Use this when you want the result to appear in the HTML.

<p>Hello, <%= @user.name %></p>
<p>Today is <%= Date.today %></p>

Rendered output might be:

<p>Hello, Alice</p>
<p>Today is 2026-06-10</p>

3. <%# %> — ERB comment

Use this to leave notes in the template that should not run and should not appear in the final HTML.

<%# This section may be replaced with a partial later %>

This comment is removed by ERB and does not appear in the browser.

4. -%> — trim newline or whitespace

This is used when you want to avoid extra blank lines in rendered output.

<% if true -%>
Hello
<% end -%>

In some ERB setups, the -%> helps remove the newline after the tag.

This is mostly about formatting output cleanly, especially in plain text templates, emails, XML, or carefully formatted HTML.

A practical combined example

<ul>
  <% @products.each do |product| %>
    <%# Only show active products %>
    <% if product.active? %>
      <li><%= product.name %></li>
    <% end %>
  <% end %>
</ul>

Why each tag is used

  • <% @products.each do |product| %>: loop logic only
  • <%# ... %>: comment for developers
  • <% if product.active? %>: condition logic only
  • <%= product.name %>: output visible content
  • <% end %>: close Ruby blocks without output

Step by Step Execution

Consider this ERB template:

<% name = "Sam" %>
<p><%= name %></p>
<%# This is hidden %>

Step-by-step

Line 1

<% name = "Sam" %>
  • Ruby assigns the string "Sam" to name
  • Nothing is printed into the HTML

Line 2

<p><%= name %></p>
  • ERB evaluates name
  • The value Sam is inserted into the template

So this becomes:

<p>Sam</p>

Line 3

<%# This is hidden %>
  • ERB treats this as a comment
  • It is ignored and does not appear in the output

Final rendered result

<p>Sam</p>

Another trace with control flow

<% logged_in = true %>
<% if logged_in %>
  <p>Welcome back!</p>
<% end %>

Execution

  • logged_in = true runs silently
  • if logged_in checks the condition silently
  • because the condition is true, the paragraph stays in the output
  • end closes the block silently

Rendered output:

<p>Welcome back!</p>

Real World Use Cases

ERB tags are used constantly in Rails views.

Common scenarios

Showing dynamic data

<h1><%= @post.title %></h1>
<p><%= @post.body %></p>

Use <%= %> because the values must appear in the page.

Running loops

<% @posts.each do |post| %>
  <h2><%= post.title %></h2>
<% end %>

Use <% %> for the loop itself, and <%= %> for what should be shown.

Conditional display

<% if current_user.admin? %>
  <a href="/admin">Admin Panel</a>
<% end %>

Use <% %> because the if controls whether content is included.

Developer notes in templates

<%# Replace this with a reusable partial later %>

Use <%# %> for notes that should not appear in HTML.

Avoiding extra blank lines in generated text

This is more common in text-based templates such as emails, config files, or XML:

<% @users.each do |user| -%>
<%= user.email %>
<% end -%>

Here -%> may help keep output compact.

Take Quiz

Real Codebase Usage

In real Rails codebases, developers use ERB tags in a few repeatable patterns.

1. Guarded rendering

<% if @order.present? %>
  <p>Order total: <%= @order.total %></p>
<% end %>
  • logic uses <% %>
  • visible content uses <%= %>

2. Iteration with helpers

<% @users.each do |user| %>
  <li><%= link_to user.name, user_path(user) %></li>
<% end %>

Helpers like link_to are often placed inside <%= %> because they return HTML to render.

3. Partial rendering

<%= render "form", product: @product %>

render returns content, so it usually appears inside <%= %>.

4. Simple setup logic

<% css_class = @product.in_stock? ? "available" : "sold-out" %>
<div class="<%= css_class %>">
  <%= @product.name %>
</div>

Assignment uses <% %>; output uses <%= %>.

5. Keeping templates readable

Developers try to keep heavy business logic out of ERB views. Instead, views commonly use:

  • small conditionals
  • loops
  • helpers
  • partials
  • formatting helpers

If a view contains too much Ruby, developers often move logic into:

  • helpers
  • presenters
  • decorators
  • model methods

That keeps ERB focused on presentation.

Common Mistakes

1. Using <% %> when you meant to print something

Broken example:

<p><% @user.name %></p>

Problem:

  • the code runs, but nothing is output

Correct version:

<p><%= @user.name %></p>

2. Using <%= %> for control flow keywords

Broken example:

<%= if @user.admin? %>
  <p>Admin</p>
<%= end %>

Problem:

  • if and end are control-flow structure, not content to print
  • this is invalid or confusing

Correct version:

<% if @user.admin? %>
  <p>Admin</p>
<% end %>

3. Forgetting that comments differ

An HTML comment is still sent to the browser:

<!-- secret note -->

If you do not want it in the rendered HTML, use an ERB comment:

<%# secret note %>

4. Expecting -%> to change logic

-%> does not change what the Ruby code does. It only affects formatting of the rendered output.

5. Overusing Ruby logic inside views

Possible but messy:

<% if @user.orders.any? && @user.active? && !@user.suspended? %>
  <p>Eligible</p>
<% end %>

Better:

<% if @user.eligible_for_display? %>
  <p>Eligible</p>
<% end %>

This makes the template easier to read.

6. Confusing ERB comments with Ruby comments

Inside ERB, this works differently:

<%# hidden from output %>

This is not the same as:

<% # ruby comment %>

The second form is Ruby code containing a comment. It may still affect whitespace differently than a true ERB comment.

Comparisons

TagRuns Ruby?Outputs result?Appears in final HTML?Typical use
<% ... %>YesNoNoloops, if, variable assignment
<%= ... %>YesYesYesdisplay values, helpers, rendered partials
<%# ... %>No meaningful outputNoNotemplate comments
-%>Yes, as part of another tagDepends on tag typeDepends on tag typetrim newline/whitespace

ERB comment vs HTML comment

TypeVisible in browser source?Use when
<%# comment %>Nonote only for developers writing the template
<!-- comment -->Yescomment should remain in rendered HTML

<% %> vs <%= %>

  • Use <% %> for instructions
  • Use <%= %> for content

A good rule:

  • if you ask, "Should the user see this value?" → use <%= %>
  • if you ask, "Is this only controlling the template?" → use <% %>
Take Quiz

Cheat Sheet

<% ruby_code %>
  • Runs Ruby
  • Does not print anything
  • Use for if, each, variable assignment, end
<%= expression %>
  • Runs Ruby
  • Prints the result into the template
  • Use for variables, helper output, render, formatted values
<%# comment %>
  • ERB comment
  • Not rendered
  • Good for developer notes inside templates
<% code -%>
  • Same as normal ERB code, but trims newline/whitespace in supported contexts
  • Mainly useful for formatting clean output

Quick rule

  • logic only: <% %>
  • show result: <%= %>
  • leave note: <%# %>
  • control whitespace: -%>

Example

<% @items.each do |item| %>
  <li><%= item.name %></li>
<% end %>

Common mistake

Wrong:

<% @user.name %>

Right:

<%= @user.name %>

FAQ

What does <% %> do in Rails ERB?

It executes Ruby code without inserting the result into the rendered HTML.

What does <%= %> do in ERB?

It executes Ruby and outputs the result into the template.

What is <%# %> used for in ERB?

It creates an ERB comment that is ignored during rendering and does not appear in the final HTML.

What does -%> mean in ERB?

It is a trimming form of the closing tag, used to remove an extra newline or whitespace in some ERB contexts.

Why is nothing showing when I use <% @name %>?

Because <% %> runs code without output. Use <%= @name %> if you want the value displayed.

Should I use ERB comments or HTML comments?

Use ERB comments for developer-only notes. Use HTML comments only if the comment should remain in the rendered page source.

Can I use if with <%= %>?

Usually no. Use <% if condition %> for control flow, then use <%= %> inside the block for visible content.

Does Rails still use ERB often?

Yes. ERB remains a standard templating system in Rails for server-rendered HTML views.

Take Quiz

Mini Project

Description

Build a small Rails-style ERB template for a product list. This project helps you practice the difference between running Ruby logic, printing values, adding comments, and trimming whitespace where needed.

Goal

Create an ERB template that loops through products, shows only available ones, prints their names and prices, and includes a developer-only note.

Requirements

  • Create an array of product hashes or objects with name, price, and availability values.
  • Use <% %> for the loop and conditional logic.
  • Use <%= %> to display the product name and price.
  • Use <%# %> to add a comment that does not appear in the output.
  • Use -%> on at least one line to practice whitespace trimming.
Take Quiz

Keep learning

Related questions

View more