
- •Introduction
- •Rails Is Agile
- •Finding Your Way Around
- •Acknowledgments
- •Getting Started
- •Models, Views, and Controllers
- •Installing Rails
- •Installing on Windows
- •Installing on Mac OS X
- •Installing on Unix/Linux
- •Rails and Databases
- •Keeping Up-to-Date
- •Rails and ISPs
- •Creating a New Application
- •Hello, Rails!
- •Linking Pages Together
- •What We Just Did
- •Building an Application
- •The Depot Application
- •Incremental Development
- •What Depot Does
- •Task A: Product Maintenance
- •Iteration A1: Get Something Running
- •Iteration A2: Add a Missing Column
- •Iteration A4: Prettier Listings
- •Task B: Catalog Display
- •Iteration B1: Create the Catalog Listing
- •Iteration B2: Add Page Decorations
- •Task C: Cart Creation
- •Sessions
- •More Tables, More Models
- •Iteration C1: Creating a Cart
- •Iteration C3: Finishing the Cart
- •Task D: Checkout!
- •Iteration D2: Show Cart Contents on Checkout
- •Task E: Shipping
- •Iteration E1: Basic Shipping
- •Task F: Administrivia
- •Iteration F1: Adding Users
- •Iteration F2: Logging In
- •Iteration F3: Limiting Access
- •Finishing Up
- •More Icing on the Cake
- •Task T: Testing
- •Tests Baked Right In
- •Testing Models
- •Testing Controllers
- •Using Mock Objects
- •Test-Driven Development
- •Running Tests with Rake
- •Performance Testing
- •The Rails Framework
- •Rails in Depth
- •Directory Structure
- •Naming Conventions
- •Active Support
- •Logging in Rails
- •Debugging Hints
- •Active Record Basics
- •Tables and Classes
- •Primary Keys and IDs
- •Connecting to the Database
- •Relationships between Tables
- •Transactions
- •More Active Record
- •Acts As
- •Aggregation
- •Single Table Inheritance
- •Validation
- •Callbacks
- •Advanced Attributes
- •Miscellany
- •Action Controller and Rails
- •Context and Dependencies
- •The Basics
- •Routing Requests
- •Action Methods
- •Caching, Part One
- •The Problem with GET Requests
- •Action View
- •Templates
- •Builder templates
- •RHTML Templates
- •Helpers
- •Formatting Helpers
- •Linking to Other Pages and Resources
- •Pagination
- •Form Helpers
- •Layouts and Components
- •Adding New Templating Systems
- •Introducing AJAX
- •The Rails Way
- •Advanced Techniques
- •Action Mailer
- •Sending E-mail
- •Receiving E-mail
- •Testing E-mail
- •Web Services on Rails
- •Dispatching Modes
- •Using Alternate Dispatching
- •Method Invocation Interception
- •Testing Web Services
- •Protocol Clients
- •Securing Your Rails Application
- •SQL Injection
- •Cross-Site Scripting (CSS/XSS)
- •Avoid Session Fixation Attacks
- •Creating Records Directly from Form Parameters
- •Knowing That It Works
- •Deployment and Scaling
- •Picking a Production Platform
- •A Trinity of Environments
- •Iterating in the Wild
- •Maintenance
- •Finding and Dealing with Bottlenecks
- •Case Studies: Rails Running Daily
- •Appendices
- •Introduction to Ruby
- •Ruby Names
- •Regular Expressions
- •Source Code
- •Cross-Reference of Code Samples
- •Resources
- •Index

Chapter 17
Action View
We’ve seen how the routing component determines which controller to use and how the controller chooses an action. We’ve also seen how the controller and action between them decide what to render back to the user. Normally that rendering takes place at the end of the action, and typically it involves a template. That’s what this chapter is all about. The ActionView module encapsulates all the functionality needed to render templates, most commonly generating HTML or XML back to the user. As its name suggests, ActionView is the view part of our MVC trilogy.
17.1 Templates
When you write a view, you’re writing a template: something that will get expanded to generate the final result. To understand how these templates work, we need to look at three things
•Where the templates go
•The environment they run in, and
•What goes inside them.
Where Templates Go
The render( ) method expects to find templates under the directory defined by the global template_root configuration option. By default, this is set to the directory app/views of the current application. Within this directory, the convention is to have a separate subdirectory for the views of each controller. Our Depot application, for instance, includes admin and store controllers. As a result, we have templates in app/views/admin and app/views/store. Each directory typically contains templates named after the actions in the corresponding controller.
Prepared exclusively for Rida Al Barazi

TEMPLATES 328
You can also have templates that aren’t named after actions. These can be rendered from the controller using calls such as
render(:action => 'fake_action_name') render(:template => 'controller/name)
render(:file |
=> 'dir/template') |
The last of these allows you to store templates anywhere on your file system. This is useful if you want to share templates across applications.
The Template Environment
Templates contain a mixture of fixed text and code. The code is used to add dynamic content to the template. That code runs in an environment that gives it access to the information set up by the controller.
•All instance variables of the controller are also available in the template. This is how actions communicate data to the templates.
•The controller objects headers, params, request, response, and session are available as accessor methods in the view. In general, the view code probably shouldn’t be using these directly, as responsibility for handling them should rest with the controller. However, we do find this useful when debugging. For example, the following rhtml template uses the debug( ) method to display the contents of the request, the details of the parameters, and the current response.
<h4>Request</h4> <%= debug(request) %> <h4>Params</h4> <%= debug(params) %> <h4>Response</h4> <%= debug(response) %>
•The current controller object is accessible using the attribute named controller. This allows the template to call any public method in the controller (including the methods in ActionController).
•The path to the base directory of the templates is available in the attribute base_path.
What Goes in a Template
Out of the box, Rails support two types of template.
•rxml templates use the Builder library to construct XML responses.
•rhtml templates are a mixture of HTML and embedded Ruby, and are typically used to generate HTML pages.
We’ll talk briefly about Builder next, then look at rhtml. The rest of the chapter applies equally to both.
Prepared exclusively for Rida Al Barazi
Report erratum

BUILDER TEMPLATES 329
17.2 Builder templates
Builder is a freestanding library that lets you express structured text (such as XML) in code.1 A Builder template (in a file with an .rxml extension) contains Ruby code that uses the Builder library to generate XML.
Here’s a simple Builder template that outputs a list of product names and prices in XML.
xml.div(:class => "productlist") do
xml.timestamp(Time.now)
@products.each do |product| xml.product do
xml.productname(product.title) xml.price(product.price, :currency => "USD")
end end
end
With an appropriate collection of products (passed in from the controller), the template might produce something such as
<div class="productlist">
<timestamp>Tue Apr 19 15:54:26 CDT 2005</timestamp>
<product>
<productname>Pragmatic Programmer</productname>
<price currency="USD">39.96</price>
</product> <product>
<productname>Programming Ruby</productname>
<price currency="USD">44.95</price>
</product> </div>
Notice how Builder has taken the names of methods and converted them to XML tags; when we said xml.price, it created a tag called <price> whose contents were the first parameter and whose attributes were set from the subsequent hash. If the name of the tag you want to use conflicts with an existing method name, you’ll need to use the tag!( ) method to generate the tag.
xml.tag!("id", product.id)
Builder can generate just about any XML you need: it supports namespaces, entities, processing instructions, and even XML comments. Have a look at the Builder documentation for details.
1Builder is available on RubyForge (http://builder.rubyforge.org/) and via RubyGems. Rails comes packaged with its own copy of Builder, so you won’t have to download anything to get started.
Prepared exclusively for Rida Al Barazi
Report erratum

RHTML TEMPLATES 330
17.3 RHTML Templates
At its simplest, an rhtml template is just a regular HTML file. If a template contains no dynamic content, it is simply sent as-is to the user’s browser. The following is a perfectly valid rhtml template.
<h1>Hello, Dave!</h1>
<p>
How are you, today?
</p>
However, applications that just render static templates tend to be a bit boring to use. We can spice them up using dynamic content.
<h1>Hello, Dave!</h1>
<p>
It's <%= Time.now %>
</p>
If you’re a JSP programmer, you’ll recognize this as an inline expression: any code between <%= and %> is evaluated, the result is converted to a string using to_s( ), and that string is substituted into the resulting page. The expression inside the tags can be arbitrary code.
<h1>Hello, Dave!</h1>
<p>
It's <%= require 'date'
DAY_NAMES = %w{ Sunday Monday Tuesday Wednesday Thursday Friday Saturday }
today = Date.today DAY_NAMES[today.wday]
%>
</p>
Putting lots of business logic into a template is generally considered to be a Very Bad Thing, and you’ll risk incurring the wrath of the coding police should you get caught. We’ll look at a better way of handling this when we discuss helpers on page 332.
Sometimes you need code in a template that doesn’t directly generate any output. If you leave the equals sign off the opening tag, the contents are executed, but nothing is inserted into the template. We could have written the previous example as
<% require 'date'
DAY_NAMES = %w{ Sunday Monday Tuesday Wednesday Thursday Friday Saturday }
today = Date.today
%>
<h1>Hello, Dave!</h1>
<p>
It's <%= DAY_NAMES[today.wday] %>.
Tomorrow is <%= DAY_NAMES[(today + 1).wday] %>.
</p>
Prepared exclusively for Rida Al Barazi
Report erratum

RHTML TEMPLATES 331
In the JSP world, this is called a scriptlet. Again, many folks will chastise you if they discover you adding code to templates. Ignore them—they’re falling prey to dogma. There’s nothing wrong with putting code in a template. Just don’t put too much code in there (and especially don’t put business logic in a template). We’ll see later how we could have done the previous example better using a helper method.
You can think of the HTML text between code fragments as if each line was being written by a Ruby program. The <%...%> fragments are added to that same program. The HTML is interwoven with the explicit code that you write. As a result, code between <% and %> can affect the output of HTML in the rest of the template.
For example, consider the template
<% 3.times do %> Ho!<br/>
<% end %>
Internally, the templating code translates this into something like the following.
3.times do
puts "Ho!<br/>" end
The result? You’ll see the phrase Ho! written three times to your browser.
Finally, you might have noticed example code in this book where the ERb chunks ended with -%>. The minus sign tells ERb not to include the newline that follows in the resulting HTML file. In the following example, there will not be a gap between line one and line two in the output.
line one
<% @time = Time.now -%> line two
Escaping Substituted Values
There’s one critical thing you have to know about using rhtml templates. When you insert a value using <%=...%>, it goes directly into the output stream. Take the following case.
The value of name is <%= params[:name] %>
In the normal course of things, this will substitute in the value of the request parameter name. But what if our user entered the following URL?
http://x.y.com/myapp?name=Hello%20%3cb%3ethere%3c/b%3e
Prepared exclusively for Rida Al Barazi
Report erratum