Ruby is a one of the most popular languages used on the web. We've started a new Session here on Nettuts+ that will introduce you to Ruby, as well as the great frameworks and tools that go along with Ruby development. In this episode, we’ll be looking at Tilt, an all-inclusive wrapper gem for Ruby template engines.
Video Tutorial
Rendering Templates
If you’ve used a Ruby web framework—like Rails and Sinatra—you’re probably familiar with at least one of the many template engines available: I’m about about options like ERB or Haml. When using them in the context of a framework, it’s pretty simple … but sometimes they seem very embedded; what if you want to use them in your own project? Is there an easy way to harness their usefulness?
Enter the Tilt gem. Billed as a “thin interface over a bunch of different Ruby template engines,” you’ll find it makes rendering templates a breeze.
Of course, we’ll install it first.
gem install tilt
If you’re not using RVM (which you should be), you might have to run that with root privileges (sudo
).
Of course, you’ll need to start with a template to render. We’ll keep it simple:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title><%= title %></title> </head> <body> <h2>A few of the Tuts+ Sites</h2> <ul> <% sites.each do |name, link| %> <li><a href="<%= link %>"> <%= name %></a></li> <% end %> </ul> </body> </html>
Save this to tutsplus.erb
. Notice that the title text will be inserted with Ruby, as well as the list of sites. Now, let’s render it. We’ll do it this way (save this in using_tilt.rb
):
require 'tilt' sites = { "Nettuts+" => "http://net.tutsplus.com", "Psdtuts+" => "http://psd.tutsplus.com", "Mobiletuts+" => "http://mobile.tutplus.com", "Audiotuts+" => "http://audio.tutsplus.com" } context = Object.new def context.title "Tuts+ Sites" end template = Tilt::ERBTemplate.new("tutsplus.erb") File.open "sites.html", "w" do |file| file.write template.render(context, sites: sites ) end
Of course, we start by requiring Tilt. Then, we create our data for the template: a simple hash, as well as a plain vanilla object. We give the object one property: title
. Then, we create our template object. Here, we’re creating an instance of the Tilt::ERBTemplate
class but the whole point of Tilt is that you can use whatever template engine you want: for example, you could use the Tilt::HamlTemplate
, Tilt::SassTempalte
(for CSS), Tilt::CoffeScriptTemplate
(for CoffeeScript), or whatever supported template engine you want However, it’s important to note that Tilt is just a wrapper: you need to require the appropriate library for the template engine you want to use. So, if you want to use a Tilt::HamlTemplate
instance, you need to require 'haml'
. You can see what libraries are required for each template engine in the Readme.
Finally, we open the file we want to write the output to. The HTML (or CSS, or JavaScript, depending on the template and engine you’re using) will be returned from the render
method of the template object. The render
method takes two parameters. The first is a context object: all the properties of this object will be available as variable within the template. So, our context.title
property will be available as just title
within the template. If there are any other values you want to pass into the template, pass them as part of the second parameter, which is a hash.
So, we can run this script on the command line:
ruby using_tilt.rb
Now, look in the directory that you’ve been saving these files in: you should see a sites.html
file. If you view it, you’ll find that the template has been rendered:
Yielding for More Power
You can do more complex things with Tilt if you pass a block to the render
method.
Tilt::ERBTemplate('other.erb').render(context, other_params) { "some text" }
Inside your template, you can yield
to the block; whatever is returned from the block will be inserted at that point in the template.
While you can, of course, just pass a string via the block, as above, there’s a more interesting use case. Recently, I’ve been using this functionality in Tilt to embed a page-specific template inside a site-wide shell. For example, we can split our above template into two files:
layout.erb
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title><%= title %></title> </head> <body> <%= yield %> </body> </html>
sites.erb
<h2>A few of the Tuts+ Sites</h2> <ul> <% sites.each do |name, link| %> <li><a href="<%= link %>"> <%= name %></a></li> <% end %> </ul>
Now, to render our page, we can do this:
template = Tilt::ERBTemplate.new("layout.erb") File.open "sites.html" do |file| file.write template.render(context) { Tilt::ERBTemplate.new("sites.erb").render(Object.new, sites: sites) } end
Notice that since we didn’t have any object we wanted to use as the context object, we just passed a plain vanilla blank Ruby object. The HTML that is returned from the rendering of sites.erb
will be inserted where the yield
keyword is. If you run the above code, you should see the same output as before.
Using Other Options
You’ll notice that, up until now, we’ve had to choose the template engine we want to use when creating the Tilt subclass object. However, Tilt will recognise the file extension of the template you pass it, so you don’t have to explicitly choose an engine: it will pick the right one, based on the file extension:
t = Tilt.new "tutsplus.erb" t.class # => Tilt::ERBTemplate
If, for some reason, your templates have a file extension that’s not what Tilt would expect, you can register that:
Tilt.register Tilt::ERBTemplate, "some_extension" t = Tilt.new "my_template.some_extension" t.class # => Tilt::ERBTemplate
Finding out More
There are a few more niche things that Tilt can do; if you’re interested in finding out more, I recommend you check out the documentation.
Comments