This is part 9 of Ramaze by Example, a tutorial on web development. In Part 8: Deleting Tasks, we added the ability to delete tasks.
If you look at our two views, you might notice that there is some common code in both. Being good coders, we know that such unnecessary duplication is bad for maintenance and debugging, and also hinders our flexibility for future changes we might want to make.
Fortunately, Ramaze has some facilities that let you consolidate shared view code. One of these facilities is the ability to use layouts.
A layout template
In the 9-layout git branch, I add a layout.xhtml view file:
<html> <head> <title>#{@title}</title> </head> <body> <h1>#{@title}</h1> #{@content} </body> </html>
I’ve copied roughly the top and bottom parts of both existing views. The differences are that I’m interpolating the title, and that the middle portion of each view is not present. Instead, there is another interpolation: #{@content}. I’ll hold off explaining this…
Adjusting the controller
We now have a layout view, but to make use of it, we need to make some changes to our controller. Looking at the source code diff, you can see that in MainController I’m using a Ramaze::Controller class method, layout:
layout '/layout' => [ :index, :new ]
The layout method takes a Hash argument. The hash key is the path to the layout. This path is specified from the root of the site (a common newbie mistake is to specify the filesystem path). The hash value is an array of symbols corresponding to the paths that we want laid out by the layout. If we omitted the array, the layout would apply to all paths, but most applications would not want this behaviour. For example, remember that our application has controller methods that handle creation and deletion of tasks. In general, it’s better to be explicit about what pages you want laid out.
I further adjust the controller by specifying each page’s @title, to be picked up by the layout.
Modifying the views
Since we are trying to move duplicate code into a single, shared location, we should remove that code from their original places in the views. To see exactly what I’ve removed, view git diff 8-delete-task 9-layout.
Now the only thing left in the views are the inner portions that distinguish them from one another. For example, here’s what’s left of view/new.xhtml:
<a href="/">Back to task list</a> <form method="POST" action="create"> Description: <input type="text" name="description" /><br /> <input type="submit" /> </form>
See the layout in action
So, check out the 9-layout branch, and take a look at the result of the changes.
git checkout 9-layout ruby start
Use View Source in your browser to see for yourself that a full webpage is rendered, even though neither the layout alone, nor the view alone has a complete page of HTML. Observe also that the @title we set in different controller methods passes along to the layout as well.
We’ll pretty up the face of our application a bit in Part 10: Cosmetics.
Related posts:
I actually had an error in an earlier version of this post. The actual syntax for the
layoutcommand is:and NOT
[...] Ramaze by Example – Part 9: LayoutRamaze by Example – Part 8: Deleting TasksRamaze by Example – Part 7: Checking off TasksRamaze by Example – Part 6: Adding TasksRamaze by Example – Part 5: Controller [...]
[...] by Example – Part 11: Validation and Error HandlingRamaze by Example – Part 10: CosmeticsRamaze by Example – Part 9: LayoutRamaze by Example – Part 7: Checking off [...]