Now that we know how to create a minimal Cuba application, we'll take a look at rendering templates. This first post is about basics of template rendering in Cuba. After reading it, you can check this post to learn how to structure your templates in a better way.
Cuba::Render and Tilt
Cuba includes a plugin called
that provides a couple of helper methods for rendering templates. This plugin uses
Tilt, which serves as an interface to a bunch
of different Ruby template engines (ERB, Haml, Sass, CoffeeScript, etc.), so you
can use the template engine of your choice.
Cuba doesn't ship with
Tilt. We need to install it:
$ gem install tilt
Remember our "Hello, Cuba!" example?
require 'cuba' Cuba.define do on root do res.write 'Hello, Cuba!' end end
Let's setup the
We need to include the
Cuba::Render plugin into the plugin system.
app.rb file and make the following changes:
require 'cuba' require 'erb' require 'cuba/render' Cuba.plugin Cuba::Render Cuba.define do on root do res.write 'Hello, Cuba!' end end
NOTE: In these examples, we will use the ERB template engine because is part of
the Ruby Standard Library and it doesn't need to be installed. If you want to
use another template engine (supported by Tilt), you will need to specify the
proper file extension for the templates and install the required library. You
can find a list of supported engines at Tilt Templates.
Defining our First Template
Why templates? Suppose you have to write a big chunk of HTML code or change a lot of pages at once, It will be hard to do it if we define them inside the routes or using only strings. Templates promote reusability and maintainability.
Create a template called
hello.erb with the following content:
<!DOCTYPE html> <html> <head> <title>Cuba example</title> </head> <body> <h1>Hello, Cuba!</h1> </body> </html>
After creating our first template, let's look how Cuba uses the
render method to show it in the screen.
To print our greeting message into the browser, we only
need to use the
render method and pick the desired
require 'cuba' require 'erb' require 'cuba/render' Cuba.plugin Cuba::Render Cuba.define do on root do res.write render('hello.erb') end end
Run the server with
rackup config.ru if it wasn't up
and open http://localhost:9292/ in your browser:
Passing local variables
A greeting message is minimally useful if we can only say "Hello, Cuba!", change the template to share <3<3<3 with everyone:
<!DOCTYPE html> <html> <head> <title>Cuba example</title> </head> <body> <h1>Hello, <%= name %>!</h1> </body> </html>
Now we can be friendly to everyone! You can pass a hash of local
variables as the second parameter on the
render method. This
adds a lot of flexibility to the templates. Let's add another
route to be able to say hello to anyone:
require 'cuba' require 'erb' require 'cuba/render' Cuba.plugin Cuba::Render Cuba.define do on root do res.write render('hello.erb', name: 'Cuba') end on :name do |name| res.write render('hello.erb', name: name) end end
NOTE: I like this approach more than sharing class/instance
variables into templates. In my opinion it's more flexible and makes some
things easier like View unit testing.
Run the web server, open a browser window and navigate to http://localhost:9292/. You should see the classic message:
That's great! We didn't break anything. Let's try it with the other route, http://localhost:9292/frodsan/ (You can try it with your own name):
So far we have seen how we can render templates with the
render method, but it
seems a bit low level or unsuited for common web applications. Usually we only
choose one template engine for the work, include layouts and partials to remove
duplication or set a location to put the templates.
Cuba::Render already has
included support for such work. We'll see it on the next entry.