You are on page 1of 15

An Introduction to ERB Templating

Overview
Writing Templates
o Using Text Transformation Methods
o Conventions for Template Files
o Using the ERB Library
o Running ERB in a Sandbox
o Suppressing Newlines
o A Longer Example
Running ERB from the Command-line

Overview
ERB (Embedded RuBy) is a feature of Ruby that enables you to conveniently generate any kind
of text, in any quantity, from templates. The templates themselves combine plain text with Ruby
code for variable substitution and flow control, which makes them easy to write and maintain.
Although ERB is most commonly seen generating Web pages, it is also used to produce XML
documents, RSS feeds, source code, and other forms of structured text file. It can be extremely
valuable when you need to create files which include many repetitions of a standard pattern, such
as unit test suites.
The main component of ERB is a library which you can call within your Ruby applications and
Rake tasks. This library accepts any string as a template, and imposes no limitations on the
source of the template. You may define a template entirely within your code, or store it in an
external location and load it as required. This means that you can keep templates in files, SQL
databases, or any other kind of storage that you want to use.
Ruby distributions also include a command-line utility that enables you to process templates that
are held in files without writing any additional code. Logically, this utility is called erb.
ERB is part of the Ruby standard library. You do not need to install any other software to use it.
Rails uses an improved version, called Erubis.
The supplied documentation for ERB provides a good introduction:
ri ERB

Writing Templates
ERB copies the text portions of the template directly to the generated document, and only
processes code that is identified by markers. Most ERB templates only use a combination of two
tag markers, each of which cause the enclosed code to be handled in a particular way.

A tag with an equals sign indicates that enclosed code is an expression, and that the renderer
should substitute the code element with the result of the code (as a string) when it renders the
template. Use an expression to embed a line of code into the template, or to display the contents
of a variable:
Hello, <%= @name %>.
Today is <%= Time.now.strftime('%A') %>.

Tags without the equals sign denote that the enclosed code is a scriptlet. Each scriptlet is caught
and executed, and the final result of the code is then injected in to the output at the point of the
scriptlet.
Scriptlets are most commonly used for embedding loops or conditional logic into templates:
<% for @item in @shopping_list %>
<%= @item %>
<% end %>

Notice that the scriptlets in this example enclose an expression. The scriptlets produce no text
themselves, but cause the enclosed expression to run multiple times, and the result of the
expression is written to the output each time.
Comment markers use a hash sign:
<%# This is just a comment %>

By default, a newline character is added to the page after the position of each tag. To suppress
this newline, use the optional parameter of ERB.new(), as explained below.
Rails extends ERB, so that you can suppress the newline simply by adding a trailing hyphen to
tags in Rails templates:
<% for @item in @items -%>
<%= @item %>
<% end -%>

Using Text Transformation Methods


ERB provides optional methods for transforming text:
This
This
This
This

will
will
will
will

be
be
be
be

HTML escaped: <%= h(this & that) %>


JSON encoded: <%= j(this & that) %>
converted to Textile markup: <%= t(this & that) %>
URL encoded: <%= u(this & that) %>

To use these features your code must include the module ERB::Util.
Conventions for Template Files
2

A file that contains an ERB template may have any name, but it is the convention that the name
of file should end with the .erb extension. Rails requires template files to have the extension of
the output type, followed by .erb, so that a name like layout.html.erb indicates a HTML
template. Some applications use the extension .rhtml for HTML templates.
If you store templates in files, it is good practice to keep each template in a separate file.
Using the ERB Library
This is a very simple example:
require 'erb'
weekday = Time.now.strftime('%A')
simple_template = "Today is <%= weekday %>."
renderer = ERB.new(simple_template)
puts output = renderer.result()

ERB only processes the template when result is called. This means that the output will show the
values of variables as they are at the moment when the result is rendered, not when the ERB
object was defined.
The code shown above will fail almost anywhere other than in a simple script. ERB gets
variables from a Binding, an object that provides access to the instance methods and variables
that are owned by another object. If you do not specify a Binding, the result() method gets a
Binding from the top-level object, which will probably own very little. Fortunately, every Ruby
class has a private binding() instance method to provide Bindings that points to itself, so we can
easily extend any object to provide ERB with a Binding.
If the ERB object is enclosed in a method, and we want it to use the variables of the host object,
we get a Binding for the host like this:
class ShoppingList
attr_accessor :items, :template
def render()
renderer.result(binding)
end
end

To enable ERB to use the variables from a separate object, we must first ensure that it has a
public method to provide a Binding. We can then get a Binding at any later point:
class ShoppingList
attr_accessor :items
def initialize(items)
@items = items
end

# Expose private binding() method.


def get_binding
binding()
end
end
list = ShoppingList.new(items)
renderer = ERB.new(template)
puts output = renderer.result(list.get_binding)

Running ERB in a Sandbox


You may protect your application from ERB by running it in a new thread. If you specify an
integer as a second parameter when you create the renderer, then the template will be processed
in a new thread which has a safe level equal to the given integer:
renderer = ERB.new(template, 3)

Safe level 4 provides maximum isolation. At this level, the specified binding must be marked as
trusted for ERB to use it.
If you need to set the third or fourth parameters, but do not want ERB to run in a new thread, use
0 as the second parameter.
Suppressing Newlines
The third parameter of new specifies optional modifiers, most of which alter when newline
characters will be automatically added to the output. For example, ERB will not print newlines
after tags if you give > as the third parameter:
renderer = ERB.new(template, 3, '>')

A Longer Example
require 'erb'
def get_items()
['bread', 'milk', 'eggs', 'spam']
end
def get_template()
%{
Shopping List for <%= @date.strftime('%A, %d %B %Y') %>
You need to buy:
<% for @item in @items %>
<%= h(@item) %>
<% end %>
}

end
class ShoppingList
include ERB::Util
attr_accessor :items, :template, :date
def initialize(items, template, date=Time.now)
@date = date
@items = items
@template = template
end
def render()
ERB.new(@template).result(binding)
end
def save(file)
File.open(file, "w+") do |f|
f.write(render)
end
end
end
list = ShoppingList.new(get_items, get_template)
list.save(File.join(ENV['HOME'], 'list.html'))

Running ERB from the Command-line


The erb utility processes a given template and sends the result to the standard output. This
enables you to generate files directly from templates, by redirecting the output:
erb my-template.txt.erb > new-file.txt

The template can automatically use built-in Ruby classes, such as String and File. To allow it to
access standard or third-party libraries, use the -r option. This option works in the same way as
the require keyword. This example processes a template that uses the Abbrev and IPAddr
libraries:
erb -r abbrev -r ipaddr my-template.txt.erb

> new-file.txt

Use the -S option to specify a safe level that isolates the template processing:
erb -S 4 my-template.txt.erb > new-file.txt

Understanding and Using Ruby Rake


Something that you will see a lot in Ruby projects is Rake. Rake is a build tool for automating
tasks.
This means you can define a set of tasks that should be carried out as part of a build process, or
perhaps a set of tasks that should be executed every time you run a specific command.
Rake allows you to create tasks that depend on one another or have prerequisites. This makes
creating automated processes very easy.
In todays tutorial we will be looking at Rake, how it works and what you will find yourself
using it for.

Installing Rake
Like all good things Ruby, Rake is available as a Gem that you can install on your computer:

gem install rake

If youve already got your Ruby environment set up, then theres really nothing else much to say
about installation!

Creating a Rake file


The first thing we need to do is to create a Rakefile (without an extension). This file is where
you list the tasks that you want to perform. Rakefiles are defined using Ruby, so if youre
familiar with the Ruby syntax, there should be nothing too crazy about this:

task default: %w[hello]

2
3
4
5

task :hello do
puts "Hello world!"
end

In this Rakefile we have two distinct things.

Firstly we have a task called default. All Rakefiles will have a default task. In this case, were
saying that when the default task is run, we should execute the hello task.
Secondly we have the hello task. When this task is run it will simply print Hello world! to the
screen.
If you save the Rakefile and run the following command from terminal, you should see the
correct output:

$ rake

Hello world!

Tasks can have prerequisites


So as you can see, it is very easy to define an automated task using Rake because it is just Ruby
code.
However, the real power of Rake is when you start using tasks with prerequisites. This makes it
possible to run a list of tasks in a given order.
For example, imagine if we wanted to automate deploying our website to our web server. We
might have the following tasks:

1
2
3

task :ssh_into_server do
puts "ssh into server"
end

4
5
6

task :move_to_directory do
puts "cd to the correct directory"
end

7
8
9
10

task :pull_code do
puts "pulling code from Github"
end

11

12
13
14

task :get_dependencies do
puts "getting the dependencies"
end

15
16

task :migrate_the_database do
puts "migrating the database"

17

end

18
19
20
21

task :set_file_permissions do
puts "setting the file permissions"
end

22
23
24
25

task :symlink_the_new_version do
puts "symlinking the new version"
end

26
27

We can state that these tasks should be performed in the correct order by creating a new task that
has prerequisites.

1
2

task :deploy => [:ssh_into_server, :move_to_directory, :pull_code,


:get_dependencies, :migrate_the_database, :set_file_permissions,
:symlink_the_new_version] do
puts deploying the website!

end

Now with one single command we can completely automate the deployment of the website to the
production server:

$ rake deploy

Namespacing
Namespacing is also an important topic in Rake as bigger projects could potentially have rake
tasks that have conflicting names.
To solve this problem we can use namespaces. For example we might namespace our
deployment process from above like this:

namespace :ship_it do

task :ssh_into_server do

puts "ssh into server"


end

4
5

# The rest of the tasks

6
7

end

Now to run the deploy task you would include the namespace as part of the command:

$ rake ship_it:deploy

Describing tasks
When you are first getting to grips with an existing project, it can be useful to check out the
existing rake tasks to see what has been defined.
To list out the Rake tasks you can run the following command from terminal:

1$ rake --tasks

However, if you do that now you wont see any output. To provide additional help to the user we
can write a short description about the task:

desc "SSH into the server."

task :ssh_into_server do

3
4

puts "ssh into server"


end

Now when you run the command again, you should see the following output:

$ rake tasks

rake ship_it:ssh_into_server

# SSH into the server

10

Creating a Ruby Gem


A Gem is an Open Source package that can be pulled into your Ruby project. You can find all of
the available Gems at Ruby Gems.
And to manage the dependencies of a project, we can use Bundler.
In todays tutorial we will be looking at how to build and distribute our own Ruby Gems so that
they can be used by other Ruby developers.

Install Bundler
The first thing we need to do is to install Bundler. Once again this should be pretty straight
forward if youve already got your Ruby environment set up:

$ gem install bundler

Create the new Gem


One of the important things about creating and releasing Gems is that all Gems should follow the
same standards. This makes it possible to use Gems as interchangeable packages within other
projects.
Instead of creating the required files and directories by hand, Bundler provides a command that
will do this job for you:

1$ bundle gem todo

If this is your first time creating a Gem you will be asked a couple of questions. The answers to
these questions dont really matter as we can change them later. We also wont be looking at
testing today, so you can just ignore the tests.
This will create the following files:

1 todo/Gemfile
2 todo/.gitignore
3 todo/lib/todo.rb
11

4 todo/lib/todo/version.rb
5 todo/todo.gemspec
6
7

todo/Rakefile
todo/README.md
todo/bin/console

8
9

todo/bin/setup
todo/LICENSE.txt

10

The Gemspec
The first file we will look at will be the todo.gemspec:

# coding: utf-8

lib = File.expand_path('../lib', __FILE__)

$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)

require todo/version

5
6
7
8
9

Gem::Specification.new do |spec|
spec.name

= "todo"

spec.version

= Todo::VERSION

spec.authors

= ["Philip Brown"]

spec.email

= ["phil@ipbrown.com"]

10
11
12
13
14
15
16

spec.summary
= %q{TODO: Write a short summary, because
Rubygems requires one.}
spec.description
this line.}

= %q{TODO: Write a longer description or delete

spec.homepage
URL here."

= "TODO: Put your gems website or public repo

spec.license

= "MIT"

17

12

18
19
20
21
22
23
24
25

# Prevent pushing this gem to RubyGems.org by setting


allowed_push_host, or
# delete this section to allow pushing this gem to any host.
if spec.respond_to?(:metadata)
spec.metadata[allowed_push_host] = "TODO: Set to
http://mygemserver.com'"
else
raise "RubyGems 2.0 or newer is required to protect against public
gem pushes."
end

26
27
28
29
30
31

spec.files
= `git ls-files -z`.split("\x0").reject { |f|
f.match(%r{^(test|spec|features)/}) }
spec.bindir
spec.executables
File.basename(f) }

= "exe"
= spec.files.grep(%r{^exe/}) { |f|

spec.require_paths = ["lib"]

32
spec.add_development_dependency "bundler", "~> 1.10"
spec.add_development_dependency "rake", "~> 10.0"
end

This file includes meta data about your Gem such as its name, description as well as details
about its author (you).
Next there are instructions for how the files should be read. You probably wont need to do
anything with these files unless you are doing something that requires extra files.
Finally we have the dependencies of the Gem. This Gem has no dependencies but if it did, they
would be listed here.
Dependencies can be either for development or for runtime. A development dependency would
be something like a testing framework. A runtime dependencies would be something that your
Gem needed to use into order work at runtime, for example an HTTP client.
These dependencies are also Gems made by other people and would be listed on Ruby Gems.

13

The Gems version


The actual code for your Gem lives under the lib directory.
You will see by default that you should have some files automatically created for you:

lib/todo/version.rb

lib/todo.rb

The version.rb file simply contains the version number of your Gem. Versioning is a very
important concept in the world of Open Source Software as it is the basis for including thirdparty code into your application.

1
2
3

module Todo
VERSION = "0.1.0"
end

The basic premise is that the version number should follow a consistent set of rules. So if your
Gem includes breaking changes, consumers of that Gem wont be affected until they choose to
be.

The Gems code


Next, the lib/todo.rb file is where your code lives:

require "todo/version"

2
3
4
5

module Todo
# Your code goes here
end

By default this file simply contains an empty module named after your Gem as well as the
version file we just looked at.
This is the file that kicks off the execution of your Gem as it is what will be included by default.
14

For small Gems you might want to put everything in this one file. For example, if your Gem just
included a couple of methods or a couple of simple classes.
However, for bigger Gems you will want to break your code into different files and then require
them in this file.

15

You might also like