Trellis Tutorial #1 - The HiLo Web Application
Posted by Brian Sam-Bodden
Trellis HiLo Game
The Trellis Hilo Game is a simple application where the user guesses a number between one and ten. This example was ‘borrowed’ from the Apache Tapestry project and ported to Trellis.
The simple diagram shows the application’s page flow, which consists of three pages: Start, Guess and Game over.

Figure 1 - Hilo Application Page Flow
The Start page simply provides a link to start guessing. The guessing happens in the Guess page. The Guess page presents the user with ten links for the numbers from 1 to 10. When the user selects incorrectly the page responds with an appropriate message such as “Guess X is too low” or “Guess X is too high”. If the user selects the correct number the application navigates to the GameOver page, which reports how many guesses it took to find the correct answer.
The Application Structure
The HiLo web application structure consists of 1 Ruby file and possibly 3 XHTML templates:

Figure 2 - Trellis Hilo Directory Structure
It is not required that you organized your application as shown but if you want to avoid having to specify your view template locations, Trellis will assume the structure above when searching for a template.
Installing Trellis
gem install trellis
The Trellis Application Class
Let’s start at the beginning and create a Trellis application. Let’s call it HiLoGame and tuck it in a module named Hilo. At the top we’ll require the RubyGems and Trellis Gems and to simplify the code we’ll include the Trellis module:
require 'rubygems'
require 'trellis'
include Trellis
module HiLo
class HiLoGame < Application
home :start
end
end
The class HiLoGame extends Trellis::Application which represents a Web Application composed of one or more pages. Inside the class body the ‘home’ class method is used to declare the home page of the application. That is, the entry point and what the URI ‘/’ will be resolved to. In the case of the HiLoGame application the entry point is indicated by the symbol :start. The Trellis convention is that there will be a Trellis Page class named Start.
The Start Page
The Start page will provide a simple welcome message and a link for the users to start guessing numbers. Let’s start with the view and show the HTML markup:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Hi/Lo Game Start Page</title>
</head>
<body>
<h1>Hi/Lo Guess</h1>
<p>I'm thinking of a number between one and ten ... </p>
<p>
<trellis:action_link>Start guessing</trellis:action_link>
</p>
</body>
</html>
Everything in the markup above should be familiar except for the <trellis:action_link> tag. The tag represents one of Trellis’ core components, the ActionLink component. ActionLink is a simple stateless component that provides a hyperlink to trigger an action. The URI produced represents the creation of an event. Events in Trellis have names. The name of the event generated by the ActionLink component is called “select”. Now that we have a template, let’s create the Trellis page class that will serve that template. The Start page is a simple class that extends the Trellis Page class.
class Start < Page end
Launching the Application
Next, let’s add a bit of code so that we can launch the application. In order to run the application we need an instance of HiLoGame for which we will invoke the start() method, as follows:
web_app = HiLoGame.new web_app.start if __FILE__ == $PROGRAM_NAME
Note: The HiLoGame and all page classes are contained inside the HiLo module as well as the two lines above to instantiate and run the application.
With the skeleton page in place and its corresponding template we can now run the application like:
ruby hilo.rb
At the console you should see output similar to (Trellis uses Mongrel by default):
091005 19:51:51 INFO: Starting Trellis Application HiLo::HiLoGame on port 3000 091005 19:51:51 INFO: watching /Users/bsbodden/Documents/projects/trellis/examples/test/source/../html/ for template changes...
Launch your browser and point it to http://localhost:3000 and you should see the home page of our Hilo application as shown next:

Figure 3 - Trellis Hilo Start Page
On the console we can see the GET request for the root “/” URI:
090921 15:30:22 INFO: 127.0.0.1 - - [21/Sep/2009 15:30:22] "GET / HTTP/1.1" 200 558 0.0025
By now, you probably have already clicked on the “Start Guessing” link and the application has appropriately blown chunks and showed you an error page describing the problem such as:

Figure 4 - Trellis Error Page
Events
The error page indicates that the application could not find a method named on_select(). If you remember I mentioned that the ActionLink component generates an event called ‘select’. When a page gets an event with a name “bacon”, it looks for an event handler method named on_bacon().

Figure 5 - Start Guessing Link
The return value of an event handler method determines where the application will navigate to next. Inside of a page for example, returning ‘self’ will make the application navigate to the same page.
Let’s add a place holder on_select() event handler to the start page and for now let’s just make it navigate back to the start page.
def on_select
self
end
Go back to / or /start to refresh the page. If you hover over the link on the page you can see the URI generated by the ActionLink component. As you can see a page has an /events namespace in which we can ‘drop’ and event. In this case ‘select’. You can see the pattern now: /page/events/event
| Component | Event Produced | Event Handler |
| ActionLink | select | on_select() |
Clicking on the “Start Guessing” link again should now take you back to the start page.
By now you have probably noticed that it wasn’t necessary to restart the application after each change. Trellis will detect changes to your application’s code and templates and automatically reload them. We can now navigate to the same page but what we really want to do is navigate to the not-yet-existent Guess page.
Navigating To Other Pages
Trellis pages need to declare any other pages that they might redirect to. To declare the possible page transitions we use the class method ‘pages’. Since the Start page can only navigate to the Guess page, we declare that using the :guess symbol referring to a Guess page that we’ll develop next.
class Start < Page
pages :guess
def on_select
self
end
end
Injected pages such as :guess get their own instance variables (@guess) available to the page. We can change the on_select() event handler to return an instance of the Guess page and also perform some work along the way as shown below:
def on_select
@guess.initialize_target
end
Obviously we haven’t yet implemented the initialize_target() method, hell we don’t even have a Guess page yet!
Stand In Pages
Yet, if you refresh the start page and click the “Start Guessing” link you should see something like:

Figure 6 - Trellis Stand-In Page for Guess
In development mode (which is the default) Trellis will generate synthetic pages or “Stand-In” pages for any injected pages for which it cannot find an implementation. Invoking any method on a stand in page returns the page object itself. In the case of the on_select() method, the return value is the guess page itself, since calling the initialize_target() method will just return the guess page object.
Stand-In pages enable incremental development, you can think of them as virtual scaffolding that automatically fades away as you provide a page’s implementation.
Read more...
