• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Rails Solutions
 

Rails Solutions

on

  • 742 views

 

Statistics

Views

Total Views
742
Views on SlideShare
742
Embed Views
0

Actions

Likes
0
Downloads
1
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Rails Solutions Rails Solutions Document Transcript

    • Rails Solutions Ruby on Rails Made Easy Justin Williams
    • Rails Solutions: Ruby on Rails Made Easy Copyright © 2007 by Justin Williams All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the copyright owner and the publisher. ISBN-13 (pbk): 978-1-59059-752-1 ISBN-10 (pbk): 1-59059-752-4 Printed and bound in the United States of America 9 8 7 6 5 4 3 2 1 Trademarked names may appear in this book. Rather than use a trademark symbol with every occurrence of a trademarked name, we use the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. Distributed to the book trade worldwide by Springer-Verlag New York, Inc., 233 Spring Street, 6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax 201-348-4505, e-mail orders-ny@springer-sbm.com, or visit www.springeronline.com. For information on translations, please contact Apress directly at 2560 Ninth Street, Suite 219, Berkeley, CA 94710. Phone 510-549-5930, fax 510-549-5939, e-mail info@apress.com, or visit www.apress.com. The information in this book is distributed on an “as is” basis, without warranty. Although every precaution has been taken in the preparation of this work, neither the author(s) nor Apress shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in this work. The source code for this book is freely available to readers at www.friendsofed.com in the Downloads section. Credits Lead Editor Copy Editor Chris Mills Nancy Sixsmith Technical Reviewers Assistant Production Director Ashish Bansal Kari Brooks-Copony Ryan J. Bonnell Production Editor Editorial Board Katie Stence Steve Anglin Ewan Buckingham Compositor Gary Cornell Molly Sharp Jason Gilmore Jonathan Gennick Jonathan Hassell Artist James Huddleston April Milne Chris Mills Matthew Moodie Proofreader Dominic Shakeshaft Linda Seifert Jim Sumser Keir Thomas Indexer Matt Wade Michael Brinkman Project Manager Interior and Cover Designer Beth Christmas Kurt Krames Copy Edit Manager Manufacturing Director Nicole Flores Tom Debolski
    • CONTENTS Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv Chapter 1: Introduction to Ruby on Rails . . . . . . . . . . . . . . . . . . . . 3 A history of Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Object-oriented programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Riding the Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Components of Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Model, View, Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Rails’ database support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Who uses Rails? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Is Rails safe? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Chapter 2: Installing Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Installing Rails on Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Installing Xcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Semiautomatic Rails install . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Manual install . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Setting the file path correctly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Setting up Ruby on Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Installing the Rails framework on Mac OSX...finally! . . . . . . . . . . . . . . . . . 24 Installing FastCGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Installing Lighttpd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Installing MySQL on Mac OSX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Locomotive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Extra tools for Mac OSX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
    • CONTENTS Installing Rails on Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Installing Ruby on Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Installing MySQL on Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 InstantRails—Rails for Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Extra tools for Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Ready? Let’s do it! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Chapter 3: Ruby for Rails Developers . . . . . . . . . . . . . . . . . . . . . . 39 Basic Ruby syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Ruby variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Classes and objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Calling objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Arrays and hashes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Decision structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Exception handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Chapter 4: Getting Started with Rails . . . . . . . . . . . . . . . . . . . . . . 53 Creating a Rails project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Configuring the web server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Viewing the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Creating the database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Using the command line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Telling Rails about the databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Creating the model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Rails migrations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Creating the controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Creating the views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Creating the first objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 Updating existing ads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Removing an ad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Adding some style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Chapter 5: More Advanced Rails . . . . . . . . . . . . . . . . . . . . . . . . . . 83 Validating data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Implementing validations in railslist . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Other common validations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Adding categories with migrations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 vi
    • CONTENTS Creating associations between models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Working with the new relationship . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Controlling the categories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Modifying URLs using routing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Defining your own routes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Defining route en masse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Named routes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Basic debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Rails console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Reading existing data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 breakpointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Debugging views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Chapter 6: Formatting Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 NumberHelper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Other helpers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 DateHelper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Defining date formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Using natural language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Chapter 7: Introduction to Ajax . . . . . . . . . . . . . . . . . . . . . . . . . 117 A history of web interaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 What is Ajax? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 Where is Ajax used? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 How does Rails do Ajax? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 When to use Ajax? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 What’s the catch? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 Chapter 8: Bringing Forms to Life with Ajax . . . . . . . . . . . . . . . 127 Ajaxing your application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Creating the categories controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Adding a touch of Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 Partials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 Adding dynamic JavaScript functionality using RJS . . . . . . . . . . . . . . . . . . . . . . 135 What about validation? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Deleting items with Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 Searching classifieds with Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Creating the search box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Sending e-mail with Action Mailer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Configuring Action Mailer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Let’s send some e-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 A bit of CSS style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 vii
    • CONTENTS Chapter 9: Uploading Files and Sending Attachments . . . . . . . . 149 Uploading images to your database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Reading files from the database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Securing your data field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Updating the remaining views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 Sending e-mail with attachments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 Adding some style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Chapter 10: User Authentication and Session Management . . . 161 Before you begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Windows XP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 Creating the user model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 Adding data model validations and associations . . . . . . . . . . . . . . . . . . . . . 165 Adding a new controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Creating a signup form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Securing the users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Creating a login form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 Adding the login code to the backend . . . . . . . . . . . . . . . . . . . . . . . . . . 172 How to store session data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Working with the sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 Locking railslist down . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 Securing the categories controller . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Assigning classifieds to users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 Removing the email field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Logging out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 Chapter 11: Customizing Rails Views . . . . . . . . . . . . . . . . . . . . . 183 Organizing listings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 Using helper methods in views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Adding Web 2.0 style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Creating a tag cloud from the categories . . . . . . . . . . . . . . . . . . . . . . . . . 189 Adding microformats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 Adding microformats to Railslist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 Chapter 12: Using Rails Plug-ins and Engines . . . . . . . . . . . . . . . 203 Building applications with scaffolding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 Creating a new application with scaffolding . . . . . . . . . . . . . . . . . . . . . . . 204 Testing the scaffolds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 Analyzing the code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 Scaffolded model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 Adding functionality with plug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 Using plug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 Using acts_as_taggable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 viii
    • CONTENTS Using engines in the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Migrating the database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Configuring login_engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 A note on components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Chapter 13: Deploying with Capistrano . . . . . . . . . . . . . . . . . . . 223 What is deployment? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Tool requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Installing Subversion for Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Installing Subversion for Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Before you begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 Creating the MySQL database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 Setting up the server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 Committing the project to Subversion . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Installing Capistrano . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 Connecting to the server on a Mac . . . . . . . . . . . . . . . . . . . . . . . . . . 235 Connecting to the server on Windows . . . . . . . . . . . . . . . . . . . . . . . . 236 Deploying the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Appendix A: Caching Your Content . . . . . . . . . . . . . . . . . . . . . . 239 Setting up the caching strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Implementing caching in the application . . . . . . . . . . . . . . . . . . . . . . . . . 242 Using fragment caching explicitly . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 Expiring caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 Appendix B: Testing Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 What is test-driven development? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 Test directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Fixtures folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Functional folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 Integration folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 Mock folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 Test folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 Unit folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 Creating a test database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 On Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 On Mac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 Preparing the test database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 Unit-testing the models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 Running the first test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 Other unit test assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Functional testing of the controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 Running all the tests at once . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 ix