# Contents

Foreword

My former company (CD Baby) was one of the first to loudly switch to Ruby on Rails, and then even more loudly switch back to PHP (Google me to read about the drama). This book by Michael Hartl came so highly recommended that I had to try it, and Ruby on Rails Tutorial is what I used to switch back to Rails again.

Though I’ve worked my way through many Rails books, this is the one that finally made me “get” it. Everything is done very much “the Rails way”—a way that felt very unnatural to me before, but now after doing this book finally feels natural. This is also the only Rails book that does test-driven development the entire time, an approach highly recommended by the experts but which has never been so clearly demonstrated before. Finally, by including Git, GitHub, and Heroku in the demo examples, the author really gives you a feel for what it’s like to do a real-world project. The tutorial’s code examples are not in isolation.

The linear narrative is such a great format. Personally, I powered through Rails Tutorial in three long days, doing all the examples and challenges at the end of each chapter. Do it from start to finish, without jumping around, and you’ll get the ultimate benefit.

Enjoy!

Derek Sivers (sivers.org)
Formerly: Founder, CD Baby
Currently: Founder, Thoughts Ltd.

Acknowledgments

Ruby on Rails Tutorial owes a lot to my previous Rails book, RailsSpace, and hence to my coauthor Aurelius Prochazka. I’d like to thank Aure both for the work he did on that book and for his support of this one. I’d also like to thank Debra Williams Cauley, my editor on both RailsSpace and Rails Tutorial; as long as she keeps taking me to baseball games, I’ll keep writing books for her.

I’d like to acknowledge a long list of Rubyists who have taught and inspired me over the years: David Heinemeier Hansson, Yehuda Katz, Carl Lerche, Jeremy Kemper, Xavier Noria, Ryan Bates, Geoffrey Grosenbach, Peter Cooper, Matt Aimonetti, Gregg Pollack, Wayne E. Seguin, Amy Hoy, Dave Chelimsky, Pat Maddox, Tom Preston-Werner, Chris Wanstrath, Chad Fowler, Josh Susser, Obie Fernandez, Ian McFarland, Steven Bristol, Wolfram Arnold, Alex Chaffee, Giles Bowkett, Evan Dorn, Long Nguyen, James Lindenbaum, Adam Wiggins, Tikhon Bernstam, Ron Evans, Wyatt Greene, Miles Forrest, the good people at Pivotal Labs, the Heroku gang, the thoughtbot guys, and the GitHub crew. Finally, many, many readers—far too many to list—have contributed a huge number of bug reports and suggestions during the writing of this book, and I gratefully acknowledge their help in making it as good as it can be.

Michael Hartl is a programmer, educator, and entrepreneur. Michael was coauthor of RailsSpace, a best-selling Rails tutorial book published in 2007, and was cofounder and lead developer of Insoshi, a popular social networking platform in Ruby on Rails. Previously, he taught theoretical and computational physics at the California Institute of Technology (Caltech), where he received the Lifetime Achievement Award for Excellence in Teaching. Michael is a graduate of Harvard College, has a Ph.D. in Physics from Caltech, and is an alumnus of the Y Combinator entrepreneur program.

Ruby on Rails Tutorial: Learn Rails by Example. Copyright © 2010 by Michael Hartl. All source code in Ruby on Rails Tutorial is available under the MIT License and the Beerware License.

   Copyright (c) 2010 Michael Hartl

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
/*
* ------------------------------------------------------------
* "THE BEERWARE LICENSE" (Revision 42):
* Michael Hartl wrote this code. As long as you retain this
* notice, you can do whatever you want with this stuff. If we
* meet someday, and you think this stuff is worth it, you can
* buy me a beer in return.
* ------------------------------------------------------------
*/

# Chapter 5 Filling in the layout

In the process of taking a brief tour of Ruby in Chapter 4, we added some basic cascading style sheets to our site layout (Section 4.1.2). In this chapter, we’ll add some custom styles of our own, as we fill in the layout with links to the pages (such as Home and About) that we’ve created so far. Along the way, we’ll learn about partials, Rails routes, and integration tests. We’ll end by taking a first important step toward letting users sign up to our site.

Rails Tutorial is a book on web development, not web design, but it would be depressing to work on an application that looks like complete crap, so in this section we’ll add some structure to the layout and give it some minimal styling with CSS. We’ll also give our code some styling, so to speak, using partials to tidy up the layout once it gets a little cluttered.

When building web applications, it is often useful to get a high-level overview of the user interface as early as possible. Throughout the rest of this book, I will thus often include mockups (in a web context often called wireframes), which are rough sketches of what the eventual application will look like.1 In this chapter, we will principally be developing the static pages introduced in Section 3.1, including a site logo, a navigation header, and a site footer. A mockup for the most important of these pages, the Home page, appears in Figure 5.1. (You can see the final result in Figure 5.8. You’ll note that it differs in some details—for example, the footer has four links instead of three—but that’s fine, since a mockup need not be exact.)

As usual, if you’re using Git for version control, now would be a good time to make a new branch:

git checkout -b filling-in-layout  You might still have the example_user.rb file from Chapter 4 in your project directory; if so, you should probably just remove it. ### 5.1.1 Site navigation When we last saw the site layout file application.html.erb in Listing 4.3, we had just added Blueprint stylesheets using the Rails stylesheet_link_tag helper. It’s time to add a couple more stylesheets, one specifically for Internet Explorer browsers and one for our (soon-to-be-added) custom CSS. We’ll also add some additional divisions (divs), some ids and classes, and the start of our site navigation. The full file is in Listing 5.1; explanations for the various pieces follow immediately thereafter. If you’d rather not delay gratification, you can see the results in Figure 5.2. (Note: it’s not (yet) very gratifying.) Listing 5.1. The site layout with added structure. app/views/layouts/application.html.erb <!DOCTYPE html> <html> <head> <title><%= title %></title> <%= csrf_meta_tag %> <!--[if lt IE 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <%= stylesheet_link_tag 'blueprint/screen', :media => 'screen' %> <%= stylesheet_link_tag 'blueprint/print', :media => 'print' %> <!--[if lt IE 8]><%= stylesheet_link_tag 'blueprint/ie' %><![endif]--> <%= stylesheet_link_tag 'custom', :media => 'screen' %> </head> <body> <div class="container"> <header> <%= image_tag("logo.png", :alt => "Sample App", :class => "round") %> <nav class="round"> <ul> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Sign in", '#' %></li> </ul> </nav> </header> <section class="round"> <%= yield %> </section> </div> </body> </html>  Let’s look at the new elements from top to bottom. As noted briefly in Section 3.1, Rails 3 uses HTML5 by default (as indicated by the doctype <!DOCTYPE html>); since the HTML5 standard is new, some browsers (especially Internet Explorer) don’t yet fully support it, so we include some JavaScript code (known as an “HTML5 shiv”) to work around the issue: <!--[if lt IE 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]-->  The somewhat odd syntax <!--[if lt IE 9]>  includes the enclosed line only if the version of Microsoft Internet Explorer (IE) is less than 9 (if lt IE 9). The weird [if lt IE 9] syntax is not part of Rails; it’s actually a conditional comment supported by Internet Explorer browsers for just this sort of situation. It’s a good thing, too, because it means we can include the extra stylesheet only for IE browsers less than version 9, leaving other browsers such as Firefox, Chrome, and Safari unaffected. After the lines to include the Blueprint stylesheets (first introduced in Listing 4.4), there is another Internet Explorer–specific line, which this time is a stylesheet that only gets included if the browser is a version of Internet Explorer less than 8 (if lt IE 8): <!--[if lt IE 8]><%= stylesheet_link_tag 'blueprint/ie' %><![endif]-->  IE has a large number of idiosyncrasies (especially before version 8), and Blueprint comes with a special ie.css file that fixes a bunch of them. After the IE stylesheet comes a stylesheet link for a file that doesn’t exist yet, custom.css, where we’ll put our custom CSS: <%= stylesheet_link_tag 'custom', :media => 'screen' %>  CSS is very forgiving, and even though the file doesn’t exist our page will still work just fine. (We’ll create custom.css in Section 5.1.2.) The next section places a container div around our site navigation and content, which is a div tag with class container. This container div is needed by Blueprint (see the Blueprint tutorial for more information). Then there are header and section elements; the header contains the sample app logo (to be added below) and the site navigation (nav). Finally, there is section element containing the site’s main content: <div class="container"> <header> <%= image_tag("logo.png", :alt => "Sample App", :class => "round") %> <nav class="round"> <ul> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Sign in", '#' %></li> </ul> </nav> </header> <section class="round"> <%= yield %> </section> </div>  The div tag in HTML is a generic division; it doesn’t do anything apart from divide the document into distinct parts. In older style HTML, div tags are used for nearly all site divisions, but HTML5 adds the header, nav, and section elements for divisions common to many applications. All HTML elements, including divs and the new HTML5 elements, can be assigned classes2 and ids; these are merely labels, and are useful for styling with CSS (Section 5.1.2). The main difference between classes and ids is that classes can be used multiple times on a page, but ids can only be used once. Inside the header is a Rails helper called image_tag: <%= image_tag("logo.png", :alt => "Sample App", :class => "round") %>  Note that, as with stylesheet_link_tag (Section 4.3.4), we pass a hash of options, in this case setting the alt and class attributes of the image tag using symbols :alt and :class. To make this clearer, let’s look at the HTML this tag produces:3 <img alt="Sample App" class="round" src="/images/logo.png" />  The alt attribute is what will be displayed if there is no image,4 and the class will be used for styling in Section 5.1.2. (Rails helpers often take options hashes in this way, giving us the flexibility to add arbitrary HTML options without ever leaving Rails.) You can see the result in Figure 5.2; we’ll add the logo image at the end of this section. The second element inside the layout header is a list of navigation links, made using the unordered list tag ul, together with the list item tag li: <nav class="round"> <ul> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Sign in", '#' %></li> </ul> </nav>  This list uses the Rails helper link_to to create links (which we created directly with the anchor tag a in Section 3.3.2); the first argument is the link text, while the second is the URL. We’ll fill in the URLs with named routes in Section 5.2.3, but for now we use the stub URL ’#’ commonly used in web design. Once Rails has processed this layout and evaluated the Embedded Ruby, the list looks like this: <nav class="round"> <ul> <li><a href="#">Home</a></li> <li><a href="#">Help</a></li> <li><a href="#">Sign in</a></li> </ul> </nav>  Our layout is now complete, and we can look at the results by visiting, e.g., the Home page. In anticipation of adding users to our site in Chapter 8, let’s add a signup link to the home.html.erb view (Listing 5.2). Listing 5.2. The Home page with a link to the signup page. app/views/pages/home.html.erb <h1>Sample App</h1> <p> This is the home page for the <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a> sample application. </p> <%= link_to "Sign up now!", '#', :class => "signup_button round" %>  As with the previous uses of link_to, this just creates a stub link of the form <a href="#" class="signup_button round">Sign up now!</a>  Note again the recurring theme of options hashes, in this case used to add a couple CSS classes to the anchor tag. You might notice that the a tag here has two classes, separated by a space: <a href="#" class="signup_button round">  This is convenient for the common case of an element with two different kinds of styles. Now we’re finally ready to see the fruits of our labors (Figure 5.2).5 Pretty underwhelming, you say? Perhaps so. Happily, though, we’ve done a good job of giving our HTML elements sensible classes and ids, which puts us in a great position to add style to the site with CSS. Before we move on to CSS styling, let’s replace the logo alt text with a logo image; you can download the sample application logo at http://railstutorial.org/images/sample_app/logo.png Put the logo in public/images so that Rails can find it. The result appears in Figure 5.3. ### 5.1.2 Custom CSS In Section 5.1.1, you may have noticed that the CSS elements are semantic, that is, they have meaning in English beyond the structure of the page. For example, instead of writing that the navigation menu was “right-top” we used the element “nav”. This gives us considerable flexibility in constructing a layout based on CSS. Let’s get started by filling in the custom.css file with Listing 5.3. (There are quite a few rules in Listing 5.3. To get a sense of what a CSS rule does, it’s often helpful to comment it out using CSS comments, i.e., by putting it inside /* … */, and seeing what changes.) Listing 5.3. CSS for the container, body, and links. public/stylesheets/custom.css .container { width: 710px; } body { background: #cff; } header { padding-top: 20px; } header img { padding: 1em; background: #fff; } section { margin-top: 1em; font-size: 120%; padding: 20px; background: #fff; } section h1 { font-size: 200%; } /* Links */ a { color: #09c; text-decoration: none; } a:hover { color: #069; text-decoration: underline; } a:visited { color: #069; }  You can see the results of this CSS in Figure 5.4. There’s a lot of CSS here, but it has a consistent form. Each rule refers either to a class, an id, an HTML tag, or some combination thereof, followed by a list of styling commands. For example, body { background: #cff; }  changes the background color of the body tag to baby blue, while header img { padding: 1em; background: #fff; }  puts a padding layer of one em (roughly the width of the letter M) around the image (img) inside a header tag. This rule also makes the background color #fff, which is white.6 Similarly, .container { width: 710px; }  styles an element with class container, in this case giving it a width of 710 pixels (corresponding to 18 Blueprint columns).7 The dot . in .container indicates that the rule styles a class called “container”. (As we’ll see in Section 8.2.3, the pound sign # identifies a rule to style a CSS id in the same way that a dot indicates a CSS class.) Changing colors is nice, but the navigation links are still hanging down on the left side of the page. Let’s move them to a better location and give them a nicer appearance with the navigation rules in Listing 5.4. The results appear in Figure 5.5. (In some of the book’s code samples, including Listing 5.4, I use three vertical dots to indicate omitted code. When typing in the code, take care not to include the dots; alternatively, if you copy-and-paste the code, make sure to remove the dots by hand.) Listing 5.4. Navigation CSS. public/stylesheets/custom.css . . . /* Navigation */ nav { float: right; } nav { background-color: white; padding: 0 0.7em; white-space: nowrap; } nav ul { margin: 0; padding: 0; } nav ul li { list-style-type: none; display: inline-block; padding: 0.2em 0; } nav ul li a { padding: 0 5px; font-weight: bold; } nav ul li a:visited { color: #09c; } nav ul li a:hover { text-decoration: underline; }  Here nav ul styles a ul tag inside a nav tag, nav ul li styles an li tag inside a ul tag inside a nav tag, and so on. As the penultimate step, we’ll make the link to our site’s signup page a little more obvious. (Though for the sample app we don’t care, on any real site it’s naturally quite important to make the signup link very prominent.) Listing 5.5 shows CSS to make the signup link big, green, and clickable (so a click anywhere inside the box will follow the link). Listing 5.5. CSS to make the signup button big, green, and clickable. public/stylesheets/custom.css . . . /* Sign up button */ a.signup_button { margin-left: auto; margin-right: auto; display: block; text-align: center; width: 190px; color: #fff; background: #006400; font-size: 150%; font-weight: bold; padding: 20px; }  There are a bunch of rules here; as usual, comment a line out and reload the page if you want to see what each one does. The end result is a signup link that’s hard to miss (Figure 5.6). As a final touch, we’ll make use of the round class we’ve placed on many of our site elements. Although the current sharp-cornered boxes aren’t terrible, it’s a little friendlier to soften the corners so they won’t slice up our users. We can accomplish this using the CSS code in Listing 5.6, with the results shown in Figure 5.7. Listing 5.6. Stylesheet rules for round corners. public/stylesheets/custom.css . . . /* Round corners */ .round { -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; }  It’s worth noting that this trick works on Firefox, Safari, Opera, and many other browsers, but it doesn’t work on Internet Explorer. There are ways of getting round corners that work on all browsers, but there’s no other technique that’s even close to this easy, so we’ll just risk leaving our IE users with a few tiny cuts. ### 5.1.3 Partials Though the layout in Listing 5.1 serves its purpose, it’s getting a little cluttered: there are several lines of CSS includes and even more lines of header for what are logically only two ideas. We can tuck these sections away using a convenient Rails facility called partials. Let’s first take a look at what the layout looks like after the partials are defined (Listing 5.7). Listing 5.7. The site layout with partials for the stylesheets and header. app/views/layouts/application.html.erb <!DOCTYPE html> <html> <head> <title><%= title %></title> <%= csrf_meta_tag %> <%= render 'layouts/stylesheets' %> </head> <body> <div class="container"> <%= render 'layouts/header' %> <section class="round"> <%= yield %> </section> </div> </body> </html>  In Listing 5.7, we’ve replaced the stylesheet lines with a single call to a Rails helper called render: <%= render 'layouts/stylesheets' %>  The effect of this line is to look for a file called app/views/layouts/_stylesheets.html.erb, evaluate its contents, and insert the results into the view.8 (Recall that <%= ... %> is the Embedded Ruby syntax needed to evaluate a Ruby expression and then insert the results into the template.) Note the leading underscore on the filename _stylesheets.html.erb; this underscore is the universal convention for naming partials, and among other things makes it possible to identify all the partials in a directory at a glance. Of course, to get the partial to work, we have to fill it with some content; in the case of the stylesheet partial, this is just the four lines of stylesheet includes from Listing 5.1; the result appears in Listing 5.8. (Technically, the HTML5 shiv includes JavaScript, not CSS. On the other hand, its purpose is to allow Internet Explorer to understand CSS with HTML5, so logically it still belongs in the stylesheet partial.) Listing 5.8. A partial for stylesheet includes. app/views/layouts/_stylesheets.html.erb <!--[if lt IE 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <%= stylesheet_link_tag 'blueprint/screen', :media => 'screen' %> <%= stylesheet_link_tag 'blueprint/print', :media => 'print' %> <!--[if lt IE 8]><%= stylesheet_link_tag 'blueprint/ie' %><![endif]--> <%= stylesheet_link_tag 'custom', :media => 'screen' %>  Similarly, we can move the header material into the partial shown in Listing 5.9 and insert it into the layout with another call to render: <%= render 'layouts/header' %>  Listing 5.9. A partial for the site header. app/views/layouts/_header.html.erb <header> <%= image_tag("logo.png", :alt => "Sample App", :class => "round") %> <nav class="round"> <ul> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Sign in", '#' %></li> </ul> </nav> </header>  Now that we know how to make partials, let’s add a site footer to go along with the header. By now you can probably guess that we’ll call it _footer.html.erb and put it in the layouts directory (Listing 5.10). Listing 5.10. A partial for the site footer. app/views/layouts/_footer.html.erb <footer> <nav class="round"> <ul> <li><%= link_to "About", '#' %></li> <li><%= link_to "Contact", '#' %></li> <li><a href="http://news.railstutorial.org/">News</a></li> <li><a href="http://www.railstutorial.org/">Rails Tutorial</a></li> </ul> </nav> </footer>  As with the header, in the footer we’ve used link_to for the internal links to the About and Contact pages and stubbed out the URLs with ’#’ for now. (As with header, the footer tag is new in HTML5.) We can render the footer partial in the layout by following the same pattern as the stylesheets and header partials (Listing 5.11). Listing 5.11. The site layout with a footer partial. app/views/layouts/application.html.erb <!DOCTYPE html> <html> <head> <title><%= title %></title> <%= csrf_meta_tag %> <%= render 'layouts/stylesheets' %> </head> <body> <div class="container"> <%= render 'layouts/header' %> <section class="round"> <%= yield %> </section> <%= render 'layouts/footer' %> </div> </body> </html>  Of course, the footer will be ugly without some styling (Listing 5.12). The results appear in Figure 5.8. Listing 5.12. Adding the CSS for the site footer. public/stylesheets/custom.css . . . footer { text-align: center; margin-top: 10px; width: 710px; margin-left: auto; margin-right: auto; } footer nav { float: none; }  Note here the rule footer nav { float: none; }  that overrides the previous rule nav { float: right; }  so that the footer is centered in the bottom of the page rather than pushed off to the right like the navigation in the header. This convention of having a succession of rules, with subsequent rules possibly overriding previous ones, is what puts the cascading in cascading style sheets. ## 5.2 Layout links Now that we’ve finished a site layout with decent styling, it’s time to start filling in the links we’ve stubbed out with ’#’. Of course, we could hard-code links like <a href="/pages/about">About</a>  but that isn’t the Rails Way. For one, it would be nice if the URL for the about page were /about rather than /pages/about; moreover, Rails conventionally uses named routes, which involves code like <%= link_to "About", about_path %>  This way the code has a more transparent meaning, and it’s also more flexible since we can change the definition of about_path and have the URL change everywhere about_path is used. The full list of our planned links appears in Table 5.1, along with their mapping to URLs and routes. We’ll implement all but the last one by the end of this chapter. (We’ll make the last one in Chapter 9.) PageURLNamed route Home/root_path About/aboutabout_path Contact/contactcontact_path Help/helphelp_path Sign up/signupsignup_path Sign in/signinsignin_path Table 5.1: Route and URL mapping for site links. ### 5.2.1 Integration tests Before writing the routes for our application, we’ll continue with our test-driven development by writing some tests for them. There are several ways to test routes, and we’re going to take this opportunity to introduce integration tests, which give us a way to simulate a browser accessing our application and thereby test it from end to end. As we’ll see starting in Section 8.4, testing routes is just the beginning. We start by generating an integration test for the sample application’s layout links:  rails generate integration_test layout_links
invoke  rspec


Note that the generator automatically appends _spec.rb to the name of our test file, yielding spec/requests/layout_links_spec.rb. (In RSpec, integration tests are also called request specs; the origins of this terminology are obscure to me.)

Our integration test will use the same get function we used in Section 3.2 in the Pages controller spec, with code like this:

describe "GET 'home'" do
it "should be successful" do
get 'home'
response.should be_success
end
end


In this section, we want to test URLs like / and /about, but you can’t get these URLs inside a controller test—controller tests only know about URLs defined for that exact controller. In contrast, integration tests are bound by no such restriction, since they are designed as integrated tests for the whole application and hence can get any page they want.

Following the model of the Pages controller spec, we can write an integration spec for each of the pages in Table 5.1 that we’ve already created, namely, Home, About, Contact, and Help. To make sure the right page (i.e., view) is rendered in each case, we’ll check for the correct title using have_selector. The test definitions appear in Listing 5.13.

Listing 5.13. Integration test for routes.
spec/requests/layout_links_spec.rb
require 'spec_helper'

get '/'
response.should have_selector('title', :content => "Home")
end

it "should have a Contact page at '/contact'" do
get '/contact'
response.should have_selector('title', :content => "Contact")
end

end

it "should have a Help page at '/help'" do
get '/help'
response.should have_selector('title', :content => "Help")
end
end


Of course, at this point they should fail (Red); we’ll get them to Green in Section 5.2.2.

By the way, if you don’t have a Help page at this point, now would be a good time to add one. (If you solved the Chapter 3 exercises in Section 3.5, you already have one.) First, add the help action to the Pages controller (Listing 5.14). Then, create the corresponding view (Listing 5.15).

Listing 5.14. Adding the help action to the Pages controller.
app/controllers/pages_controller.rb
class PagesController < ApplicationController
.
.
.
def help
@title = "Help"
end
end

Listing 5.15. Adding a view for the Help page.
app/views/pages/help.html.erb
<h1>Help</h1>
<p>
Get help on Ruby on Rails Tutorial at the
<a href="http://railstutorial.org/help">Rails Tutorial help page</a>.
To get help on this sample app, see the
<a href="http://railstutorial.org/book">Rails Tutorial book</a>.
</p>


There’s one final detail to deal with before moving on: if you’re running Autotest, you might notice that it doesn’t run the integration test. This is by design, since integration tests can be slow and hence can disrupt the red-green-refactor cycle, but I still find it preferable to have Autotest run the integration tests. To arrange for this to happen, you just have to tell Autotest to run tests in the spec/requests directory (Listing 5.16 or Listing 5.17).

Listing 5.16. Additions to .autotest needed to run integration tests with Autotest on OS X.
Autotest.add_hook :initialize do |autotest|
autotest.add_mapping(/^spec\/requests\/.*_spec\.rb$/) do autotest.files_matching(/^spec\/requests\/.*_spec\.rb$/)
end
end

Listing 5.17. Additions to .autotest needed to run integration tests with Autotest on Ubuntu Linux.
Autotest.add_hook :initialize do |autotest|
$git commit -am "Removed default Rails page"  You may recall from Section 1.3.5 that we used the Git command git commit -a -m "Message", with flags for “all changes” (-a) and a message (-m). As shown above, Git also lets us roll the two flags into one using git commit -am "Message". With that, all of the routes for static pages are working, and the tests should pass. Now we just have to fill in the links in the layout. ### 5.2.3 Named routes Let’s put the named routes created in Section 5.2.2 to work in our layout. This will entail filling in the second arguments of the link_to functions with the proper named routes. For example, we’ll convert <%= link_to "About", '#' %>  to <%= link_to "About", about_path %>  and so on. We’ll start in the header partial, _header.html.erb (Listing 5.21), which has links to the Home and Help pages. While we’re at it, we’ll follow a common web convention and link the logo image to the Home page as well. Listing 5.21. Header partial with links. app/views/layouts/_header.html.erb <header> <% logo = image_tag("logo.png", :alt => "Sample App", :class => "round") %> <%= link_to logo, root_path %> <nav class="round"> <ul> <li><%= link_to "Home", root_path %></li> <li><%= link_to "Help", help_path %></li> <li><%= link_to "Sign in", '#' %></li> </ul> </nav> </header>  We won’t have a named route for the “Sign in” link until Chapter 9, so we’ve left it as ’#’ for now. Note that this code defines the local variable logo for the logo image tag, and then links to it in the next line:  <% logo = image_tag("logo.png", :alt => "Sample App", :class => "round") %> <%= link_to logo, root_path %>  This is a little cleaner than stuffing it all into one line. It’s especially important to notice that the ERb for the variable assignment doesn’t have an equals sign; it’s just <% ... %>, because we don’t want that line inserted into the template. (Using a local variable in this manner is only one way to do it. An even cleaner way might be to define a logo helper; see Section 5.5.) The other place with links is the footer partial, _footer.html.erb, which has links for the About and Contact pages (Listing 5.22). Listing 5.22. Footer partial with links. app/views/layouts/_footer.html.erb <footer> <nav class="round"> <ul> <li><%= link_to "About", about_path %></li> <li><%= link_to "Contact", contact_path %></li> <li><a href="http://news.railstutorial.org/">News</a></li> <li><a href="http://www.railstutorial.org/">Rails Tutorial</a></li> </ul> </nav> </footer>  With that, our layout has links to all the static pages created in Chapter 3, so that, for example, /about goes to the About page (Figure 5.9). By the way, it’s worth noting that, although we haven’t actually tested for the presence of the links on the layout, our tests will fail if the routes aren’t defined. You can check this by commenting out the routes in Listing 5.18 and running your test suite. For a testing method that actually makes sure the links go to the right places, see Section 5.5. ## 5.3 User signup: A first step As a capstone to our work on the layout and routing, in this section we’ll make a route for the signup page, which will mean creating a second controller along the way. This is a first important step toward allowing users to register for our site; we’ll take the next step, modeling users, in Chapter 6, and we’ll finish the job in Chapter 8. ### 5.3.1 Users controller It’s been a while since we created our first controller, the Pages controller, way back in Section 3.1.2. It’s time to create a second one, the Users controller. As before, we’ll use generate to make the simplest controller that meets our present needs, namely, one with a stub signup page for new users. Following the conventional REST architecture favored by Rails, we’ll call the action for new users new and pass it as an argument to generate controller to create it automatically (Listing 5.23). Listing 5.23. Generating a Users controller (with a new action). $ rails generate controller Users new
create  app/controllers/users_controller.rb
route  get "users/new"
invoke  erb
create    app/views/users
create    app/views/users/new.html.erb
invoke  rspec
create    spec/controllers/users_controller_spec.rb
create    spec/views/users
create    spec/views/users/new.html.erb_spec.rb
invoke  helper
create    app/helpers/users_helper.rb
invoke    rspec
create    spec/helpers/users_helper_spec.rb


As with the Pages controller, this generates view and helper specs that we won’t need, so remove them:

$rm -rf spec/views$ rm -rf spec/helpers


The controller generator makes both the Users controller and a useful default test, which verifies that the new action responds properly to a GET request (Box 3.1); the code appears in Listing 5.24. This code should look familiar; it follows the exact same form as the Pages controller spec last seen in Section 3.3.1 (Listing 3.20).

Listing 5.24. Testing the signup page.
spec/controllers/users_controller_spec.rb
require 'spec_helper'

describe UsersController do

describe "GET 'new'" do
it "should be successful" do
get 'new'
response.should be_success
end
end
end


By construction, the Users controller already has the proper new action and new.html.erb template to get this test to pass (Listing 5.25). (To view the page at /users/new, you might have to restart the server.)

Listing 5.25. Action for the new user (signup) page.
app/controllers/users_controller.rb
class UsersController < ApplicationController

def new
end

end


To get back in the spirit of test-driven development, let’s add a second (failing) test of our own by testing for a title that contains the string "Sign up" (Listing 5.26). Be sure to add render_views as we did in the Pages controller spec (Listing 3.20); otherwise, the test won’t pass even after we add the proper title.

Listing 5.26. A test for the signup page title.
spec/controllers/users_controller_spec.rb
require 'spec_helper'

describe UsersController do
render_views

describe "GET 'new'" do
it "should be successful" do
get 'new'
response.should be_success
end

it "should have the right title" do
get 'new'
end
end
end


This test uses the have_selector method we’ve seen before (Section 3.3.1); note that, as in Section 3.3.1, have_selector needs the render_views line since it tests the view along with the action.

Of course, by design this test currently fails (Red). To get a custom title, we need to make an @title instance variable as in Section 3.3.3. We can thus get to Green with the code in Listing 5.27.

Listing 5.27. Setting the custom title for the new user page.
app/controllers/users_controller.rb
class UsersController < ApplicationController

def new
end
end


### 5.3.2 Signup URL

With the code from Section 5.3.1, we already have a working page for new users at /users/new, but recall from Table 5.1 that we want the URL to be /signup instead. As in Section 5.2, we’ll first write a test (Listing 5.28).

Listing 5.28. Simple integration test for user signup link.
spec/requests/layout_links_spec.rb
require 'spec_helper'

.
.
.
it "should have a signup page at '/signup'" do
get '/signup'
end
end


Note that this is the same file as the one used for the other layout links, even though the Signup page is in a different controller. Being able to hit pages in multiple controllers is one of the advantages of using integration tests.

The last step is to make a named route for signups. We’ll follow the examples from Listing 5.18 and add a match ’/signup’ rule for the signup URL (Listing 5.29).

Listing 5.29. A route for the signup page.
config/routes.rb
SampleApp::Application.routes.draw do
get "users/new"

match '/signup',  :to => 'users#new'

match '/contact', :to => 'pages#contact'
match '/help',    :to => 'pages#help'

root :to => 'pages#home'
.
.
.
end


Note that we have kept the rule get "users/new", which was generated automatically by the Users controller generation in Listing 5.23. Currently, this rule is necessary to route /users/new correctly, but it doesn’t follow the proper REST conventions (Table 2.2), and we will eliminate it in Section 6.3.3.

At this point, the signup test in Listing 5.28 should pass. All that’s left is to add the proper link to the button on the Home page. As with the other routes, match ’/signup’ gives us the named route signup_path, which we put to use in Listing 5.30.

Listing 5.30. Linking the button to the Signup page.
app/views/pages/home.html.erb
<h1>Sample App</h1>

<p>
<a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
sample application.
</p>



With that, we’re done with the links and named routes, at least until we add a route for signing in (Chapter 9). The resulting new user page (at the URL /signup) appears in Figure 5.10.

## 5.4 Conclusion

In this chapter, we’ve hammered our application layout into shape and polished up the routes. The rest of the book is dedicated to fleshing out the sample application: first, by adding users who can sign up, sign in, and sign out; next, by adding user microposts; and, finally, by adding user relationships.

If you’re following along with Git, be sure to commit and merge (and, just to be paranoid, run your tests first):

$bundle exec rspec spec/$ git add .
$git commit -m "Finished layout and routes"$ git checkout master
$git merge filling-in-layout  You might also want to push up to GitHub, or deploy to Heroku: $ git push
\$ git push heroku


## 5.5 Exercises

1. Replace the local variable logo in Listing 5.21 with a helper method of the same name, so that the new partial looks like Listing 5.31. Use the code in Listing 5.32 to help you get started.
2. You may have noticed that our tests for the layout links test the routing but don’t actually check that the links on the layout go to the right pages. One way to implement these tests is to use visit and click_link inside the RSpec integration test. Fill in the code in Listing 5.33 to verify that all the layout links are properly defined.
Listing 5.31. Header partial with the logo helper from Listing 5.32.
app/views/layouts/_header.html.erb
<header>
<nav class="round">
<ul>
</ul>
</nav>

Listing 5.32. A template for the logo helper.
app/helpers/application_helper.rb
module ApplicationHelper

def logo
# Fill in.
end

# Return a title on a per-page basis.
def title
.
.
.
end
end

Listing 5.33. A test for the links on the layout.
spec/requests/layout_links_spec.rb
require 'spec_helper'

.
.
.
it "should have the right links on the layout" do
visit root_path
response.should # fill in
response.should # fill in
response.should # fill in
response.should # fill in
end
end

1. The mockups in Ruby on Rails Tutorial are made with an excellent online mockup application called Mockingbird
2. These are completely unrelated to Ruby classes.
3. You might notice that the img tag, rather than looking like <img>...</img>, instead looks like <img ... />. Tags that follow this form are known as self-closing tags.
4. The alt text is also what will be displayed by screen readers for the visually impaired. Though people are sometimes sloppy about including the alt attribute for images, it is in fact required by the HTML standard. Luckily, Rails includes a default alt attribute; if you don’t specify the attribute in the call to image_tag, Rails just uses the image filename (minus extension). In this case, though, Sample App is more descriptive than logo, so I’ve elected to set the alt text explicitly.
5. Note that Safari and Chrome users will see an indicator of a broken image in place of the “Sample App” alt text.
6. HTML colors can be coded with three base-16 (hexadecimal) numbers, one each for the primary colors red, green, and blue. #fff maxes out all three colors, yielding pure white. See this HTML colors site for more information.
7. Blueprint CSS uses a grid of columns 40 pixels across, 30 pixels for the column itself and 10 pixels of padding. The rightmost column doesn’t need padding, so 18 columns is 710 pixels: 18 * 40 – 10 = 710.
8. Many Rails developers use a shared directory for partials shared across different views. I prefer to use the shared folder for utility partials that are useful on multiple views, while putting partials that are literally on every page (as part of the site layout) in the layouts directory. (We’ll create the shared directory starting in Chapter 8.) That seems to me a logical division, but putting them all in the shared folder certainly works fine, too.
9. In the line SampleApp::Application.routes.draw do you might recognize that the draw method takes a block, a construction we last saw in Section 4.3.2
Michael Hartl is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to Amazon.com.