ruby  web  

Feb 24, 2015 • Michael Chen

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.