Views, ERB & Partials

Reviewed & published by Brayan K

Views are the V in MVC — the templates Ruby on Rails turns into the HTML your users see. Rails writes them in ERB, which lets you embed Ruby right inside HTML.

Part of the free Ruby course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

By the end of this lesson you'll use the two ERB tags, pull data from controller instance variables, build pages with layouts, and reuse markup with partials and view helpers.

What You'll Learn in This Lesson

1️⃣ The Two ERB Tags

ERB has two main tags. <%= %> evaluates Ruby and outputs the result into the page; <% %> runs Ruby for logic (if/each) and prints nothing. The data comes from the controller's instance variables.

<%# app/views/posts/show.html.erb %>
<%# <%= %> OUTPUTS a value into the HTML: %>
<h1><%= @post.title %></h1>
<p><%= @post.body %></p>

<%# <% %> (no =) runs Ruby for LOGIC, printing nothing: %>
<% if @post.published? %>
  <span class="badge">Published</span>
<% else %>
  <span class="badge">Draft</span>
<% end %>

<%# A loop: <% %> for the each, <%= %> to print each value: %>
<ul>
  <% @post.tags.each do |tag| %>
    <li><%= tag %></li>
  <% end %>
</ul>

2️⃣ Layouts and Helpers

The layout wraps every page with shared HTML and uses <%= yield %> to insert each page's content. View helpers like link_to generate HTML for you.

<%# app/views/layouts/application.html.erb — wraps EVERY page %>
<!DOCTYPE html>
<html>
  <head>
    <title>My Blog</title>
  </head>
  <body>
    <nav>
      <%= link_to "Home", root_path %>      <%# a view helper builds the link %>
      <%= link_to "Posts", posts_path %>
    </nav>

    <%# yield drops the current page's view in HERE: %>
    <%= yield %>

    <footer>&copy; 2026 My Blog</footer>
  </body>
</html>

A partial is a reusable fragment whose filename starts with an underscore. Render it with render to keep markup DRY.

<%# A PARTIAL is a reusable fragment. File: _post.html.erb %>
<%# (the filename starts with an underscore) %>
<div class="post">
  <h2><%= post.title %></h2>      <%# uses a local 'post', not @post %>
  <p><%= post.body %></p>
</div>

<%# In index.html.erb, render the partial once per post: %>
<% @posts.each do |post| %>
  <%= render "post", post: post %>    <%# no underscore in the call %>
<% end %>

<%# Shortcut: render the collection in one line. %>
<%# <%= render @posts %>  uses _post.html.erb automatically %>

Your turn. Choose the correct ERB tag for outputting a value versus running logic.

<%# 🎯 YOUR TURN — fill in the right ERB tags. %>

<%# 1) OUTPUT the user's name into an h1: %>
<h1><__ @user.name __></h1>        <%# 👉 TODO: which tag outputs a value? %>

<%# 2) Only show the badge IF the user is an admin (logic, no output): %>
<__ if @user.admin? __>            <%# 👉 TODO: which tag runs logic? %>
  <span>Admin</span>
<__ end __>

<%# ✅ Expected tags:
       <%= @user.name %>
       <% if @user.admin? %> ... <% end %>  %>

Mini-Challenge: Output or Logic?

For each goal, decide which ERB tag you'd reach for.

# 🎯 MINI-CHALLENGE: which ERB tag?
# For each goal, say whether you'd use <%= %> or <% %>.
#
# 1. Print @article.title into the page          -> ______
# 2. Run an each loop over @comments              -> ______
# 3. Insert a link with link_to                   -> ______
# 4. Start an if/else block                        -> ______
#
# ✅ Example answers:
#    <%= %>
#    <% %>
#    <%= %>
#    <% %>

# your answers here

Common Errors (and the fix)

Pro Tips

📋 Quick Reference — Views & ERB

ConceptSyntax
Output a value<%= @post.title %>
Run logic<% if ... %> ... <% end %>
Insert page content<%= yield %>
A link<%= link_to "Home", root_path %>
Render a partial<%= render "post" %>
Render a collection<%= render @posts %>

🎉 Lesson Complete!

Practice quiz

What does the ERB tag <%= ... %> do?

  • Runs Ruby but prints nothing
  • Runs Ruby AND outputs the result into the HTML
  • Only writes a comment
  • Defines a route

Answer: Runs Ruby AND outputs the result into the HTML. <%= %> evaluates the Ruby and inserts its result into the page.

What does the plain <% ... %> tag (no equals) do?

  • Runs Ruby for control flow but outputs nothing
  • Always prints the result
  • Comments out the line
  • Renders a partial

Answer: Runs Ruby for control flow but outputs nothing. <% %> runs Ruby (like if/each) without printing a value — used for logic.

How does a view get data from its controller?

  • By querying the database directly
  • Through global variables only
  • It cannot access controller data
  • Through instance variables (@posts) the controller set

Answer: Through instance variables (@posts) the controller set. Instance variables assigned in the action (e.g. @posts) are available in the matching view.

What is the file extension for an HTML ERB template?

  • .html.haml
  • .erb.html
  • .html.erb
  • .rb.html

Answer: .html.erb. ERB HTML templates use the .html.erb extension, like show.html.erb.

How do you render a partial named _form.html.erb?

  • partial "form"
  • render "form"
  • include "form"
  • yield "form"

Answer: render "form". render "form" renders the partial _form.html.erb (the leading underscore is dropped in the call).

Why do partial filenames start with an underscore?

  • To mark them as the layout
  • Because Ruby requires it for all views
  • By convention, to mark a reusable sub-template
  • To disable them

Answer: By convention, to mark a reusable sub-template. The leading underscore marks a file as a partial, a reusable view fragment.

What is the application layout (app/views/layouts/application.html.erb) for?

  • It defines the database schema
  • It lists the routes
  • It stores controller actions
  • It wraps every view with shared HTML and yields the page content

Answer: It wraps every view with shared HTML and yields the page content. The layout holds shared HTML (head, nav, footer) and uses yield to insert each page's content.

Which is a view helper that builds an HTML link?

  • link_to "Home", root_path
  • redirect_to root_path
  • render :home
  • params[:link]

Answer: link_to "Home", root_path. link_to "Home", root_path generates an anchor tag pointing at root_path.

To loop over @posts and print each title in ERB, you would use:

  • A plain <% @posts.each do |post| %> ... <% end %> with <%= post.title %> inside
  • <%= @posts.each %> with no block
  • render @posts.title
  • params.each

Answer: A plain <% @posts.each do |post| %> ... <% end %> with <%= post.title %> inside. Use <% ... %> for the each loop and <%= post.title %> to output each value.

What does <%= render @post %> typically do?

  • Deletes the post
  • Redirects to the post
  • Runs a migration
  • Renders the _post partial for that object

Answer: Renders the _post partial for that object. Passing an object to render uses the matching partial (_post.html.erb) by convention.

Continue this course

Frequently asked questions

What's the difference between <%= %> and <% %>?

Both run Ruby inside an ERB template, but only one prints. <%= %> (with the equals sign) evaluates the Ruby and inserts the result into the HTML — use it to output values like <%= @post.title %>. <% %> (no equals) runs Ruby but outputs nothing — use it for control flow like <% if ... %>, <% @posts.each do |p| %>, and their matching <% end %>. A common beginner bug is using <% %> where you meant <%= %>, which silently produces no text. There's also <%# %> for comments that aren't sent to the browser.

How do views get data from the controller?

Through instance variables. When an action assigns @posts = Post.all, that @posts is automatically available in the matching view (app/views/posts/index.html.erb). Only @-prefixed variables cross from the controller into the view; plain local variables in the action do not. So the controller's job is to load what the view needs into instance variables, and the view's job is to display them. This is the contract between the two layers: the controller prepares the data, the view presents it.

What are layouts and how does yield work?

A layout is the shared HTML wrapper around every page, by default app/views/layouts/application.html.erb. It holds the things every page needs — the <head>, navigation, footer — and calls <%= yield %> exactly where the current page's content should appear. When you render a view, Rails inserts that view's output into the layout at the yield. This means you write the boilerplate once and each individual view only contains the unique part of the page. You can also define multiple layouts or override which one an action uses.

What are partials and why use them?

A partial is a reusable view fragment stored in a file whose name starts with an underscore, like _post.html.erb. You render it with render "post" (note: no underscore in the call), and it's perfect for markup you repeat — a single post's card, a form, a navigation menu. Partials keep views DRY: change the markup in one place and every page using it updates. You can pass data in as locals (render "post", post: post) and even render a whole collection at once with <%= render @posts %>, which uses _post.html.erb for each element by convention.