ERB
The ERB module provides a templating system that lets you embed Ruby code within text documents. It’s widely used in Rails views, configuration templates, and any scenario where you need to generate dynamic text from static content mixed with Ruby logic.
Overview
ERB stands for “Embedded Ruby”. It allows you to insert Ruby expressions and statements into plain text files, which are then processed to produce final output with the Ruby code executed:
<%= ... %>— Evaluates the expression and outputs the result<% ... %>— Evaluates the expression without output<%# ... %>— Comments (not included in output)
Loading ERB
require 'erb'
Basic Usage
Simple Interpolation
require 'erb'
template = "Hello, <%= name %>!"
result = ERB.new(template).result(binding)
# Assuming name = "World" => "Hello, World!"
Using a Hash
require 'erb'
template = "Welcome to <%= place[:name] %>!"
binding_data = template, { place: { name: "RubyLand" } }
result = ERB.new(template).result_with_hash(place: { name: "RubyLand" })
# => "Welcome to RubyLand!"
Template Files
require 'erb'
# Read from file
template = File.read('page.html.erb')
renderer = ERB.new(template)
output = renderer.result(binding)
File.write('page.html', output)
ERB Tags
Output Tag <%= %>
The equals tag evaluates Ruby and inserts the result into the output:
template = <<~ERB
<h1><%= title %></h1>
<p>You have <%= items.count %> items</p>
ERB
ERB.new(template).result_with_hash(title: "My Page", items: [1,2,3])
# => <h1>My Page</h1>
# => <p>You have 3 items</p>
Expression Tag <% %>
Without the equals sign, code runs but nothing is output:
template = <<~ERB
<% items.each do |item| %>
<li><%= item %></li>
<% end %>
ERB
ERB.new(template).result_with_hash(items: ["apple", "banana"])
# => <li>apple</li>
# => <li>banana</li>
Comment Tag <%# %>
Comments are stripped from output:
template = "<%# This is ignored %><%= 1 + 1 %>"
ERB.new(template).result
# => "2"
Suppressing Newlines
Append - to close tags to trim surrounding whitespace:
template = <<~ERB
<% items.each do |item| -%>
<li><%= item %></li>
<% end -%>
ERB
This prevents extra blank lines in the output.
ERB Methods
ERB.new(template, safe_level = nil, trim_mode = nil)
Creates a new ERB template object.
| Parameter | Type | Default | Description |
|---|---|---|---|
template | String | Required | The ERB template string |
safe_level | Integer | nil | Security level (deprecated in Ruby 3.0+) |
trim_mode | String | nil | Trim mode configuration |
Trim Modes
# Default: no trimming
ERB.new(template, trim_mode: nil)
# Remove leading whitespace before %> (common)
ERB.new(template, trim_mode: '-')
# Remove whitespace around ERB tags
ERB.new(template, trim_mode: '<>')
# Combine: trim before and around tags
ERB.new(template, trim_mode: '-<>')
Common trim mode behaviors:
'-'— Strips whitespace before-%>and newline after'<>'— Strips whitespace between<%and%>tags'-<>'— Combination of both
result(binding = nil)
Renders the template with the given binding:
erb = ERB.new("Value: <%= x * 2 %>")
erb.result(binding) # Uses current binding
erb.result_with_hash(x: 5) # Uses hash as local variables
result_with_hash(hash)
Renders template with a hash as local variables:
erb = ERB.new("Hello <%= name %>!")
erb.result_with_hash(name: "Alice")
# => "Hello Alice!"
def method(result = nil)
Creates a method from the template:
erb = ERB.new("Hello <%= @name %>!")
erb.def_method(@template, :greeting)
template = ERBTemplate.new
template.@name = "Bob"
template.greeting # => "Hello Bob!"
Security Considerations
Safe Levels (Ruby 2.x and earlier)
Older Ruby versions had $SAFE taint checking. This is deprecated as of Ruby 2.7 and removed in Ruby 3.0.
HTML Escaping
By default, ERB does not escape HTML. Use CGI.escapeHTML or Rails’ html_escape:
# Manual escaping
template = "<%= CGI.escapeHTML(user_input) %>"
# In Rails (automatic)
template = "<%= user_input %>" # Automatically escaped in Rails
Code Injection
Never pass untrusted input as template code. Only allow data interpolation:
# DANGEROUS: User controls Ruby code
template = "<% #{user_input} %>" # NEVER DO THIS
# SAFE: User controls only data values
template = "<%= user_input %>" # User input is treated as text
Practical Examples
HTML Generation
require 'erb'
template = <<~ERB
<!DOCTYPE html>
<html>
<head><title><%= title %></title></head>
<body>
<h1><%= heading %></h1>
<ul>
<% items.each do |item| %>
<li><%= item %></li>
<% end %>
</ul>
</body>
</html>
ERB
output = ERB.new(template, trim_mode: '-').result_with_hash(
title: "My Page",
heading: "Welcome",
items: ["Feature 1", "Feature 2", "Feature 3"]
)
Configuration Files
require 'erb'
config_template = <<~CONF
database:
host: <%= db[:host] %>
port: <%= db[:port] %>
username: <%= db[:user] %>
password: <%= db[:pass] %>
CONF
config = {
db: {
host: "localhost",
port: 5432,
user: "admin",
pass: "secret"
}
}
File.write("config.yml", ERB.new(config_template).result_with_hash(config))
Email Templates
require 'erb'
email_template = <<~EMAIL
From: <%= from %>
To: <%= to %>
Subject: <%= subject %>
Hello <%= name %>,
<%= body %>
Best regards
EMAIL
email = ERB.new(email_template).result_with_hash(
from: "noreply@example.com",
to: "user@example.com",
subject: "Welcome!",
name: "User",
body: "Thank you for signing up."
)
Ruby Version History
- Ruby 1.8: Introduced ERB as part of standard library
- Ruby 1.9: Added encoding support for templates
- Ruby 2.7: Deprecated
$SAFEand taint checking - Ruby 3.0: Removed safe level functionality
- Ruby 3.2: Added
result_with_hashmethod