Beginning Ruby On Rails E-Commerce - Programmer Books

Transcription

Beginning Ruby on RailsE-CommerceFrom Novice to Professional Christian Hellsten and Jarkko Lainewww.allitebooks.com

Beginning Ruby on Rails E-Commerce: From Novice to ProfessionalCopyright 2006 by Christian Hellsten and Jarkko LaineAll 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 retrievalsystem, without the prior written permission of the copyright owner and the publisher.ISBN-13 (pbk): 978-1-59059-736-1ISBN-10 (pbk): 1-59059-736-2Printed and bound in the United States of America 9 8 7 6 5 4 3 2 1Trademarked names may appear in this book. Rather than use a trademark symbol with every occurrenceof a trademarked name, we use the names only in an editorial fashion and to the benefit of the trademarkowner, with no intention of infringement of the trademark.Lead Editor: Keir ThomasTechnical Reviewer: Peter MarklundEditorial Board: Steve Anglin, Ewan Buckingham, Gary Cornell, Jason Gilmore, Jonathan Gennick,Jonathan Hassell, James Huddleston, Chris Mills, Matthew Moodie, Dominic Shakeshaft, Jim Sumser,Keir Thomas, Matt WadeProject Manager: Beth ChristmasCopy Edit Manager: Nicole FloresCopy Editor: Marilyn SmithAssistant Production Director: Kari Brooks-CoponyProduction Editor: Kelly WinquistCompositor: Pat ChristensonProofreader: Dan ShawIndexer: Broccoli Information ManagementArtist: Kinetic Publishing Services, LLCCover Designer: Kurt KramesManufacturing Director: Tom DebolskiDistributed 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, orvisit http://www.springeronline.com.For information on translations, please contact Apress directly at 2560 Ninth Street, Suite 219, Berkeley, CA94710. Phone 510-549-5930, fax 510-549-5939, e-mail info@apress.com, or visit http://www.apress.com.The information in this book is distributed on an “as is” basis, without warranty. Although every precautionhas been taken in the preparation of this work, neither the author(s) nor Apress shall have any liability toany person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectlyby the information contained in this work.The source code for this book is available to readers at http://www.apress.com in the Source Code/Download section.www.allitebooks.com

Contents at a GlanceAbout the Authors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiiiAbout the Technical Reviewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvAcknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xviiIntroduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix CHAPTER 1Project Setup and Proof of Concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 CHAPTER 2Author Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 CHAPTER 3Book Inventory Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 CHAPTER 4Book Catalog Browsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 CHAPTER 5Shopping Cart Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 CHAPTER 6Forum Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 CHAPTER 7Tagging Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 CHAPTER 8Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 CHAPTER 9Checkout and Order Processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 CHAPTER 10Multiple Language Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 CHAPTER 11Acceptance Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 CHAPTER 12Application Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351 CHAPTER 13Performance Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381 INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403iiiwww.allitebooks.com

ContentsAbout the Authors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiiiAbout the Technical Reviewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvAcknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xviiIntroduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix CHAPTER 1Project Setup and Proof of Concept . . . . . . . . . . . . . . . . . . . . . . . .1Introducing the Emporium Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Installing the Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Installing Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4Installing RubyGems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5Installing Ruby on Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6Installing MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8Installing the MySQL Driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9Introducing Scrum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10Creating the Emporium Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12Creating the Skeleton Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12Creating the Emporium Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14Starting Emporium for the First Time . . . . . . . . . . . . . . . . . . . . . . . . . 18How Does Ruby on Rails Work? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20Implementing the About Emporium User Story . . . . . . . . . . . . . . . . . . . . . . 20Running the Generate Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21Modifying the Generated View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22Creating the Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23Modifying the Generated Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . 27Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28vwww.allitebooks.com

vi C O N T E N T S CHAPTER 2 CHAPTER 3Author Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29Using Test-Driven Development. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Testing in Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Unit Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Functional Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Integration Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Creating the ActiveRecord Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Using ActiveRecord Migrations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Running Unit Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Creating the Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the User Stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Adding an Author. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Listing Authors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Viewing an Author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Editing an Author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deleting an Author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Adjusting the Flash Notifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2930303131313236373939485052545557Book Inventory Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .59Getting the Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Using Scaffolding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the Publisher Administration Interface . . . . . . . . . . . . . . . .Updating the Schema with the Publishers Table . . . . . . . . . . . . . . . .Generating Publisher Code with the Scaffolding Script . . . . . . . . . .Completing the Add Publisher User Story . . . . . . . . . . . . . . . . . . . . .Completing the View Publisher User Story . . . . . . . . . . . . . . . . . . . .Completing the Edit Publisher User Story . . . . . . . . . . . . . . . . . . . . . .5960616162646668www.allitebooks.com

C O N T E N T SImplementing the Book Administration Interface . . . . . . . . . . . . . . . . . . . . 69Updating the Schema with the Books Table . . . . . . . . . . . . . . . . . . . . 69Creating the Book Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73ActiveRecord Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73Modifying the Generated Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77Cloning the Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80Unit Testing Validations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81Unit Testing the ActiveRecord Mappings . . . . . . . . . . . . . . . . . . . . . . 82Generating Book Administration Codewith the Scaffolding Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88Integration Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90Completing the Add Book User Story . . . . . . . . . . . . . . . . . . . . . . . . . . 91Completing the Upload Book Cover User Story . . . . . . . . . . . . . . . . 102Completing the List Books User Story . . . . . . . . . . . . . . . . . . . . . . . . 104Completing the View Book User Story . . . . . . . . . . . . . . . . . . . . . . . . 107Completing the Edit Book User Story . . . . . . . . . . . . . . . . . . . . . . . . . 110Testing the Delete Book User Story . . . . . . . . . . . . . . . . . . . . . . . . . . 112Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 CHAPTER 4Book Catalog Browsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .113Getting the Book Catalog Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the Book Catalog Interface . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the Browse Books User Story . . . . . . . . . . . . . . . . . .Implementing the View Book Details User Story . . . . . . . . . . . . . . .Implementing the Search Books User Story . . . . . . . . . . . . . . . . . . .Implementing the Get Latest Books User Story . . . . . . . . . . . . . . . .Creating an RSS Feed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .113114116120125133136139vii

viii C O N T E N T S CHAPTER 5 CHAPTER 6 CHAPTER 7Shopping Cart Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . .141Getting the Shopping Cart Requirements . . . . . . . . . . . . . . . . . . . . . . . . . .Setting Up the Shopping Cart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Creating the Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Adding a Functional Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Creating the Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Modifying the Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Creating the Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the User Stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the Add Items to the Cart User Story . . . . . . . . . . . .Implementing the Remove Items from the Cart User Story . . . . . .Implementing the Clear the Cart User Story . . . . . . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .141142142142143145147152152161166168Forum Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .169Getting the Forum Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Using the Threaded Forum Plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Setting Up the Forum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Updating the Database Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Modifying the Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Unit Testing the Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Generating the Controller and View . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the User Stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the Post to Forum User Story . . . . . . . . . . . . . . . . . . .Implementing the View Forum User Story . . . . . . . . . . . . . . . . . . . .Implementing the View Post User Story . . . . . . . . . . . . . . . . . . . . . .Implementing the Reply to Post User Story . . . . . . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .169170171171175176177179179185190192195Tagging Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .197Getting the Tagging Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Using the Tagging RubyGem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Setting Up for Tagging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Updating the Database Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Preparing the Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Unit Testing the Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Using the Console to Test the Model . . . . . . . . . . . . . . . . . . . . . . . . .197198201201203204205

C O N T E N T SImplementing the User Stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the Assign Tags User Story . . . . . . . . . . . . . . . . . . . .Implementing the Edit Tags User Story . . . . . . . . . . . . . . . . . . . . . . .Implementing the List Tags and Show Tag User Stories . . . . . . . .Implementing the Recommend Books User Story . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CHAPTER 8 CHAPTER 9Security207207211215218221. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223Getting the Authentication Requirements . . . . . . . . . . . . . . . . . . . . . . . . . .Using the Authentication Plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the User Stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the Log In User Story . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the Fail Log In User Story . . . . . . . . . . . . . . . . . . . . . .Implementing the Reset Password User Story . . . . . . . . . . . . . . . . .Protecting Your Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Cross-Site Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .URL and Form Manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .SQL Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Cross-Site Request Forgery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .223224227227233238248248248249250250Checkout and Order Processing . . . . . . . . . . . . . . . . . . . . . . . . . .251Getting the Checkout and Order-Processing Requirements . . . . . . . . . .Implementing the Check Out User Story. . . . . . . . . . . . . . . . . . . . . . . . . . .Creating the Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Adding Validations to the Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Creating the Controller and Integration Test. . . . . . . . . . . . . . . . . . .Creating the View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Saving the Order Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Integrating with Payment Gateways . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Installing the Active Merchant Plugin . . . . . . . . . . . . . . . . . . . . . . . .Integrating with PayPal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Integrating with Authorize.Net . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Using the Payment Gem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the Administrator User Stories . . . . . . . . . . . . . . . . . . . . . .Implementing the View Orders User Story . . . . . . . . . . . . . . . . . . . .Implementing the View Order User Story . . . . . . . . . . . . . . . . . . . . .Implementing the Close Order User Story . . . . . . . . . . . . . . . . . . . . x

x C O N T E N T S CHAPTER 10 CHAPTER 11Calculating Shipping Costs and Taxes . . . . . . . . . . . . . . . . . . . . . . . . . . . .Using the Shipping Gem. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Calculating Taxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .294294296296Multiple Language Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .297Getting the Localization Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . .Using the Globalize Plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Localizing with Globalize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Setting Up Globalize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the User Stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Implementing the Change Locale User Story . . . . . . . . . . . . . . . . . .Implementing the Translation User Stories . . . . . . . . . . . . . . . . . . . .Translating the View and the Book Model . . . . . . . . . . . . . . . . . . . . . . . . .Translating the View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Translating the Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Localizing Dates, Numbers, and Currency . . . . . . . . . . . . . . . . . . . . . . . . .Localizing Dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Localizing Numbers and Currencies . . . . . . . . . . . . . . . . . . . . . . . . .Adding Unicode (UTF-8) Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Setting Character Encoding in HTML . . . . . . . . . . . . . . . . . . . . . . . . .Setting Character Encoding for the HTTP Response . . . . . . . . . . . .Changing the Database to Use UTF-8 . . . . . . . . . . . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24326Acceptance Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327Using Selenium . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Writing Selenium Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Selenium Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Selenium Test Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .The First Acceptance Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Recording Selenium Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Using the Selenium IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Recording the View Forum Acceptance Test . . . . . . . . . . . . . . . . . .Recording the Post to Forum Acceptance Test . . . . . . . . . . . . . . . .Recording the Show Post Acceptance Test . . . . . . . . . . . . . . . . . . .Recording the Reply to Post Acceptance Test . . . . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .327330330334335337337340345347348350

C O N T E N T S CHAPTER 12 CHAPTER 13Application Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .351Setting Up the Production Environment . . . . . . . . . . . . . . . . . . . . . . . . . . .Connecting to the Production Server: SSH . . . . . . . . . . . . . . . . . . . .Installing the Web Server: LightTPD. . . . . . . . . . . . . . . . . . . . . . . . . .Installing the Application Server: Ruby on Rails and FastCGI . . . .Installing the Database Server (MySQL) . . . . . . . . . . . . . . . . . . . . . .Configuring LightTPD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Creating the Production Database . . . . . . . . . . . . . . . . . . . . . . . . . . .Deploying the Application Manually . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Copying the Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Creating Users and Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Starting LightTPD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Starting FastCGI Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Automating Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Installing Capistrano . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Creating the Capistrano Deployment Recipe . . . . . . . . . . . . . . . . . .Running the Setup Task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Deploying to Production . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Starting LightTPD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76379380Performance Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .381Performance and Scaling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Measuring Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Checking the Log File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Using Rails Analyzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Page Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Action Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Fragment Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Fragment Stores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Caching ActiveRecord Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Common Performance Problems in Rails . . . . . . . . . . . . . . . . . . . . . . . . . .Rendering Speed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Database Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .381382382383388388390390392395397397399401 INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403xi

About the Authors CHRISTIAN HELLSTEN is the founder of Aktagon Ltd., a provider ofconsulting services and custom Internet software development,and CTO of Sanda Interactive Ltd. He has worked on large-scalee-business projects as a consultant for PricewaterhouseCoopersConsulting and IBM Business Consulting Services. Christian’sbackground is in J2EE, but he fell in love with Ruby on Rails at firstsight, and has been using it professionally ever since to build webapplications. When he is not changing the diapers of his two young daughters at his homein Finland, Christian enjoys researching new and better ways of building software. JARKKO LAINE is the owner and CEO of O’Design, a Rails-based webdesign shop. He has been using Ruby on Rails since its publiclaunch in 2004. He has contributed patches to the core developerteam, and has also contributed to several Rails plugins. Jarkko hasprovided Rails consultancy for a number of organizations, fromnonprofits to Fortune 500 companies. He has also taught Rails atthe university level and delivers lectures about Rails around theworld. Currently, he works on dotherightthing.com, a project that will bring people awhole new way to rate, follow, and discuss the social responsibility of companies. Jarkko isa sports junkie, so if he isn’t sitting in front of his computer, he is probably running aroundforests or kicking a ball on the nearest field. He lives in Tampere, Finland, with his fiancéeMaria and a growing list of pending household chores.xiii

About the Technical Reviewer PETER MARKLUND has extensive experience with and expertise inobject orientation, web development, relational databases, andtesting, and has been doing web development with Java and Tclsince 2000. He was one of the core developers of the OpenACSopen source web framework. In late 2004, he was introduced toRuby on Rails and has since helped develop an online communityand a CRM system with Rails. Peter is currently working as a Rubyon Rails freelancer and is also helping organize events for the Ruby on Rails developercommunity in Stockholm. Peter has a personal blog at http://marklunds.com, where heshares Rails tips with other developers.xv

AcknowledgmentsFirst of all, I would like to thank my family for allowing me to take on such a timeconsuming project as this in my spare time. Secondly, I would like to thank everyoneinvolved in this project, including Keir Thomas, Jarkko Laine, Peter Marklund, BethChristmas, Marilyn Smith, and Kelly Winquist. Last, but not least, I would like to thank myparents, for buying me a Commodore VIC-20, back in the early 1980s.Christian HellstenI am eternally grateful to the following people: Yukihiro “Matz” Matsumoto and DavidHeinemeier Hansson for bringing passion and joy back to programming; my ex-girlfriend—now fiancée—Maria, for putting up with the innumerable nights spent married to the computer; my parents, for telling me to believe in and pursue my dreams, even if it was just“fooling around with computers”; the whole team at Apress, for towing me back on track inthe moments of despair; and finally, Philip and Alex, for igniting the spark.Jarkko Lainexvii

IntroductionBeginning Ruby on Rails E-Commerce is for people who want to learn how to build realworld professional web applications using Rails best practices. We put a specific emphasison e-commerce by showing you how to build an online bookstore, including a shoppingcart, catalog, forum, and other functionality. On the front-end, we guide you throughimportant technologies like Ajax, syndication, tagging

JARKKO LAINE is the owner and CEO of O'Design, a Rails-based web design shop. He has been using Ruby on Rails since its public launch in 2004. He has contributed patches to the core developer team, and has also contributed to several Rails plugins. Jarkko has provided Rails consultancy for a number of organizations, from