Skip to content

Ror Views

DodaTech 4 min read

title: Ruby on Rails Views — Complete Guide to ERB Templates description: 'Learn Ruby on Rails views: ERB syntax, layouts, partials, helpers, form builders, content_for, and rendering collections for clean, DRY templates.' date: 2026-06-28 lastmod: 2026-06-28 weight: 16 tags: [backend, ror]


Ruby on Rails views use ERB (Embedded Ruby) templates to generate HTML, with layouts for shared structure, partials for reusable components, and helpers for presentation logic.

## What You'll Learn

By the end of this tutorial, you'll write ERB templates, use layouts and partials, create forms with form builders, use view helpers, render collections, and keep views clean.

## Real-World Use

A blog uses application.html.erb layout for header/footer, _post.html.erb partial for each post card, and form_with for creating posts. Helpers format dates and truncate text.

## Views Learning Path

```mermaid
flowchart LR
  A[Controllers] --> B[Views]
  B --> C[Models]
  C --> D[Active Record]
  D --> E[Migrations]
  B --> F{You Are Here}
  style F fill:#f90,color:#fff

ERB Syntax

<!-- Code execution (no output) -->
<% if user_signed_in? %>
  <!-- Expression output -->
  <h1>Welcome, <%= current_user.name %>!</h1>
<% else %>
  <%= link_to "Sign In", new_user_session_path %>
<% end %>

<!-- Comment -->
<%# This is a comment %>

<!-- Truncate and format -->
<p><%= truncate(@post.body, length: 200) %></p>
<p><%= time_ago_in_words(@post.created_at) %> ago</p>

Layouts

<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
<head>
  <title><%= content_for?(:title) ? yield(:title) : "MyApp" %></title>
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>
  <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
  <%= javascript_importmap_tags %>
</head>
<body>
  <header>
    <%= render "shared/navbar" %>
  </header>
  <main class="container">
    <% flash.each do |type, msg| %>
      <div class="alert alert-<%= type %>"><%= msg %></div>
    <% end %>
    <%= yield %>
  </main>
  <footer>
    <%= render "shared/footer" %>
  </footer>
</body>
</html>

Partials

<!-- app/views/posts/_post.html.erb -->
<article class="post">
  <h2><%= link_to post.title, post %></h2>
  <p><%= truncate(post.body, length: 200) %></p>
  <div class="meta">
    By <%= post.user.name %> | <%= time_ago_in_words(post.created_at) %> ago
    <%= pluralize(post.comments.count, "comment") %>
  </div>
</article>

<!-- Rendering a collection -->
<%= render @posts %>  <!-- Renders _post.html.erb for each post -->

<!-- Rendering with locals -->
<%= render partial: "post", locals: { post: @featured_post } %>

Forms

<!-- New/Edit form -->
<%= form_with model: @post do |form| %>
  <% if @post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post:</h2>
      <ul>
        <% @post.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>
  <div class="field">
    <%= form.label :title %>
    <%= form.text_field :title %>
  </div>
  <div class="field">
    <%= form.label :body %>
    <%= form.text_area :body, rows: 10 %>
  </div>
  <div class="field">
    <%= form.label :published %>
    <%= form.check_box :published %>
  </div>
  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

View Helpers

# app/helpers/posts_helper.rb
module PostsHelper
  def post_status(post)
    if post.published?
      content_tag(:span, "Published", class: "badge bg-success")
    else
      content_tag(:span, "Draft", class: "badge bg-warning")
    end
  end

  def post_meta(post)
    "#{time_ago_in_words(post.created_at)} ago by #{post.user.name}"
  end
end

Common Mistakes

1. Complex Ruby Logic in Views

Views should only have simple conditionals and loops. Complex logic belongs in helpers or models.

2. Not Using Partials

Repeating the same HTML structure multiple times violates DRY. Extract into partials.

3. Hardcoding URLs

Use path helpers (posts_path, @post) instead of hardcoded /posts/1 URLs.

4. Ignoring the Flash

flash[:notice] and flash[:alert] provide user feedback. Display them in the layout.

5. Missing CSRF Token

form_with and form_tag include CSRF tokens automatically. For AJAX, include <%= csrf_meta_tags %>.

Practice Questions

1. What is the difference between <% %> and <%= %>?

<% %> executes Ruby code without output. <%= %> executes and outputs the result.

2. What is a layout in Rails?

A shared template wrapper. yield inserts the current view's content. Common for header, footer, and navigation.

3. How do partials work?

Partial files start with underscore (_post.html.erb). render @posts renders _post partial for each item.

4. What is the purpose of form_with?

form_with creates HTML forms bound to a model. It generates proper form fields, CSRF token, and handles errors.

5. Challenge: Create a view that lists posts using partials, with a layout and flash messages.

<!-- app/views/posts/index.html.erb -->
<h1>Posts</h1>
<%= render @posts %>
<%= link_to "New Post", new_post_path %>

FAQ

What template engines can Rails use besides ERB?

Slim and Haml are popular alternatives. They use indentation-based syntax that's cleaner for complex views.

What is Turbolinks (now Turbo)?

Turbo speeds up page navigation by intercepting links and replacing page content without full reloads.

How do I add CSS classes to form fields?

form.text_field :title, class: 'form-control', placeholder: 'Enter title'.

What is content_for?

content_for(:sidebar) captures content and yields it in the layout at the specified yield location.

How do I render JSON in a view?

Use render json: @posts in the controller, or create a Jbuilder view.

Mini Project: Post Index View

Create a complete index view with layout, partials, and flash messages.

<h1>Blog Posts</h1>
<%= render @posts %>
<%= link_to "New Post", new_post_path, class: "btn btn-primary" %>

What's Next

Ruby on Rails Models Ruby on Rails Active Record

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro