Erb tips for Sinatra Users
Sinatra provides different perspective and workflow to Web development with a tiny and elegent domain specific language for HTTP(s) actions. Although no strict MVC pattern enforced, Sinatra supports many template languages for its dynamic views. Among these template languages, Haml and Slim are popular choices because their succinct Ruby-like syntaxes. However, I prefer ERB over other newer template languages like Haml or Slim because the syntax of ERB follows original HTML tags, meaning better recognition by editor and web designer.
Erb Syntax
Erb uses Ruby itself as the template language, meaning that there is no need to re-learn another template language. In Erb, <%# %>
stands for comments, <%= %>
for text substitutions, and <% %>
for non-text Ruby code. For example, if we want to loop over an array in out template, just use for
loop or each
method to iterate over array elements.
<%# for loop %>
<% for element in array %>
<p><%= element %></p>
<% end %>
<%# iterate over array elements %>
<ul>
<% array.each do |element| %>
<li><%= element %></li>
<% end %>
</ul>
Here we use if
clause to optionally include meta tag.
<head>
<% if defined? description %>
<meta name="description" content="<%= description %>">
<% end %>
</head>
Use Erb in Sinatra
If you want to use Erb in Sinatra, use erb
method in Sinatra file.
require 'sinatra'
get '/' do
title = 'My Next Awesome Website'
erb :index, :locals => { :title => title }, :layout => :main_layout
end
In the above example, we use index.erb
as template, pass title
as variable in template, and use main_layout.erb
as layout. You may also pass class variable to template directly without setting :locals
.
require 'sinatra'
get '/' do
@title = 'My Next Awesome Website'
erb :index
end
In this example, we still use index.erb
as template. @title
will pass to template, you don’t need to explictly setting local variables.
Layout
Although Erb doesn’t support template inheritance, you can use layout to mimic the effect and reduce repeated code. Layout is simply template with <%= yield =>
block. After finishing layout template, you just need to fill content in your main template. By default, layout template will be named as layout.erb
.
<%# layout.erb %>
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<%= yield %>
</body>
</html>
<%# index.erb %>
<h1><%= title %></h1>
<p><%= content %></p>
You may also use different layouts in different pages. Nevertheless, these layouts may have repeated region among them. You need partial to further reduce these parts.
Partial
Partial is supported in Sinatra. To utilitize partial, use erb
method in template.
<%# layout.erb %>
<html>
<%= erb :head %>
<body>
<%= erb :header %>
<%= yield %>
<%= erb :footer %>
</body>
</html>
Then, design your head.erb.
<%# head.erb %>
<head>
<meta name="author" content="<%= author %>">
<meta name="description" content="<%= description %>">
<meta name="keywords" content="<%= keywords %>">
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
</head>
You may also design your own header.erb and footer.erb in the same manner.
content_for
<%= yield %>
should be sufficient for most conditions. However, if you need fine control over template blocks, you may consider content_for
. content_for
is not a built-in part of Sinatra, but you can easily get it from sinatra-contrib gem. The main point of content_for
is that you can use several blocks in template instead of only one yield
.
If you want to use content_for
, require it in main Sinatra file:
require 'sinatra'
require 'sinatra/content_for'
<%# layout.erb %>
<!DOCTYPE html>
<html>
<%= erb :head %>
<body>
<%= erb :header %>
<h1><%= yield_content :title %></h1>
<p><%= yield_content :content %></p>
<%= erb :footer %>
</body>
</html>
Then, in your main template:
<%# index.erb %>
<% content_for :title do %>
My Site Title
<% end %>
<% content_for :content do %>
My website goes from here...
<% end %>
Conclusion
Erb keeps original HTML tags, making a easier life for web designers. By combining layout, partial, and content_for, you can reduce repeated tags and maintain good templates.