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: <script>alert("hack")</script>
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 Type | Defined In | Available In View |
|---|---|---|
@article (instance) | Controller | Yes |
article (local) | Controller | No |
article (local in loop) | The view's each loop | Yes (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.
