Foundation Rails 2 Eldon Alameda Foundation Rails 2 Copyright©2008byEldonAlameda Allrightsreserved.Nopartofthisworkmaybereproducedortransmittedinanyformorbyanymeans,electronicormechanical, includingphotocopying,recording,orbyanyinformationstorageorretrievalsystem,withoutthepriorwrittenpermission ofthecopyrightownerandthepublisher. ISBN-13(pbk):978-1-4302-1039-9 ISBN-13(electronic):978-1-4302-1040-5 PrintedandboundintheUnitedStatesofAmerica987654321 Trademarkednamesmayappearinthisbook.Ratherthanuseatrademarksymbolwitheveryoccurrenceofatrademarkedname, weusethenamesonlyinaneditorialfashionandtothebenefitofthetrademarkowner,withnointentionofinfringement ofthetrademark. DistributedtothebooktradeworldwidebySpringer-VerlagNewYork,Inc.,233SpringStreet,6thFloor,NewYork,NY10013. Phone1-800-SPRINGER,fax201-348-4505,[email protected],orvisitwww.springeronline.com. Forinformationontranslations,pleasecontactApressdirectlyat2855TelegraphAvenue,Suite600,Berkeley,CA94705. Phone510-549-5930,fax510-549-5939,[email protected],orvisitwww.apress.com. ApressandfriendsofEDbooksmaybepurchasedinbulkforacademic,corporate,orpromotionaluse.eBookversionsandlicenses arealsoavailableformosttitles.Formoreinformation,referenceourSpecialBulkSales–eBookLicensingwebpageat http://www.apress.com/info/bulksales. Theinformationinthisbookisdistributedonan“asis”basis,withoutwarranty.Althougheveryprecautionhasbeentakeninthe preparationofthiswork,neithertheauthor(s)norApressshallhaveanyliabilitytoanypersonorentitywithrespecttoany lossordamagecausedorallegedtobecauseddirectlyorindirectlybytheinformationcontainedinthiswork. Thesourcecodeforthisbookisfreelyavailabletoreadersatwww.friendsofed.comintheDownloadssection. Credits LeadEditor ProductionEditor BenRenow-Clarke EllieFountain TechnicalReviewer Compositor SeanCribbs DinaQuan EditorialBoard Proofreader ClayAndres,SteveAnglin, PatrickVincent EwanBuckingham,TonyCampbell, GaryCornell,JonathanGennick, Indexer MatthewMoodie,JosephOttinger, RonStrauss JeffreyPepper,FrankPohlmann, BenRenow-Clarke,DominicShakeshaft, Artist MattWade,TomWelsh AprilMilne ProjectManager CoverImageDesigner KylieJohnston CornévanDooren CopyEditor InteriorandCoverDesigner HeatherLang KurtKrames AssociateProductionDirector ManufacturingDirector KariBrooks-Copony TomDebolski For my daughter Kaylee “As you wish . . .” CONTENTS AT A GLANCE AbouttheAuthor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii AbouttheTechnicalReviewer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix AbouttheCoverImageDesigner. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxiii Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxv Chapter 1 WhyRails? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Chapter 2 AShortIntroductiontoRuby . . . . . . . . . . . . . . . . . . . . . . . . 13 Chapter 3 TouringaRailsApplication . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Chapter 4 IntroducingActiveRecord. . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Chapter 5 AdvancedActiveRecord . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Chapter 6 PresentingtheViews. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Chapter 7 ExploringActionPack:UnderstandingtheController . . . . . 171 Chapter 8 ControllingOurRouting . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 Chapter 9 ScaffoldingandPlug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Chapter 10 IntroductiontoTestingwithRSpec . . . . . . . . . . . . . . . . . . 253 Chapter 11 BuildingaCompleteApplication. . . . . . . . . . . . . . . . . . . . 291 Chapter 12 EnhancingOurApplication . . . . . . . . . . . . . . . . . . . . . . . . 339 Chapter 13 SecurityandPerformanceEnhancements . . . . . . . . . . . . . 381 Chapter 14 DeployingYourRailsApplication. . . . . . . . . . . . . . . . . . . . 401 Appendix A WheretoGofromHere. . . . . . . . . . . . . . . . . . . . . . . . . . 415 Appendix B RailsInstallation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 Appendix C DatabaseDesign101 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437 v CONTENTS AbouttheAuthor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii AbouttheTechnicalReviewer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix AbouttheCoverImageDesigner. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxiii Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxv Chapter 1 WhyRails? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 WhatmakesRailssospecial? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Extractedfromarealapplication. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Usesconventionoverconfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 80/20rule. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Model-View-Controllerpattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 DRY(Don’tRepeatYourself) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Opinionatedsoftware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 UsesRubyfor(almost)everything . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Emphasisonbeauty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Developmenttools. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Richcommunityandplug-ins. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Supportfordifferentenvironments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Advancedwebservicessupport . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Commondirectorystructure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Fasttodevelopin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Fun. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 WhynotRails?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Notasilverbullet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Slowerbenchmarks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Deploymentdifficulties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Rapidlychanging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Notunderstandingthecode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 vii CONTENTS Chapter 2 AShortIntroductiontoRuby . . . . . . . . . . . . . . . . . . . . . . . . 13 WhatisRuby? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Rubyisobjectoriented. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Rubyisinterpreted. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Rubyisdynamicallytyped . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Rubyisreflective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 InteractingwithRuby. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Introducingirb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Literals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Thereisalwaysareturnedvalue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Everythingisanobject. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Variablesandconstants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Localvariables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Instancevariables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Classvariables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Globalvariables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Numbers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Fixnums . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Bignum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Floats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Nil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Comparisons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Conditionals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Hashes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Thewhileloop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Theforloop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Theeachcommand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Instancemethods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Accessormethods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Methodswithpunctuation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Classmethods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Classes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 TheAnarchyofRuby. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Chapter 3 TouringaRailsApplication . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Ourroadmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Creatingasampleapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Commondirectorystructure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 app/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 app/controllers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 viii CONTENTS app/models. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 app/views. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 app/helpers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 config . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 db . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 doc. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 log. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 public . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 test. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 tmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 vendor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Multipleenvironments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Standardconfigurationfiles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Databaseconfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Environmentconfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Routesconfiguration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Startingourapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 AtouroftheRailsframework. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 ComponentsofRails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 ActionMailer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 ActionPack. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 ActiveRecord . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 ActiveResource. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 ActiveSupport . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Railties. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 TeachingRailstosayhello . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Chapter 4 IntroducingActiveRecord. . . . . . . . . . . . . . . . . . . . . . . . . . . 67 WhatIsActiveRecord? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Thedemonstrationapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 Creatingyourfirstmodel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 CRUDinteractionusingourmodel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Tailingthelog. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Findingyourfirstcompany . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Creatinganewcompany. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 ActiveRecord’snewmethodinourapplication . . . . . . . . . . . . . . . . . . . . . . 76 Readingandfindingcompanyrecords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 find . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 find_by_*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Optionalparametersforfindmethods. . . . . . . . . . . . . . . . . . . . . . . . . . . 81 find_by_sql . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 ActiveRecord’sfindmethodinourapplication . . . . . . . . . . . . . . . . . . . . . . 83 Movingfindstoourmodel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Updatingacompanyrecord. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 ActiveRecord’supdatemethodinourapplication . . . . . . . . . . . . . . . . . . . . 85 ix CONTENTS Deletingacompany . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 ActiveRecord’sdeletemethodinourapplication. . . . . . . . . . . . . . . . . . . . . 87 CRUDrecap. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Validations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Ensuringvaluesareset. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Ensuringvaluesaretheproperlength . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 Ensuringvaluesarenumbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Ensuringthattherecanbeonlyone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Ensuringthatinputsareintheproperformat. . . . . . . . . . . . . . . . . . . . . . . . . 97 Ensuringthatinputsarethesame(confirmation). . . . . . . . . . . . . . . . . . . . . . . 99 Ensuringthattheuseracceptedsomething . . . . . . . . . . . . . . . . . . . . . . . . . 100 Othervalidationrules. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Definingyourownvalidations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Migrations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Sexymigrations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Magiccolumns. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 Legacyordifficultdatabases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Chapter 5 AdvancedActiveRecord . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 Buildingassociations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Theimportanceofprimaryandforeignkeys. . . . . . . . . . . . . . . . . . . . . . . . . 117 Typesofassociations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Singularassociations(one-to-one) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 belongs_to . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 has_one . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Collectionassociations(one-to-manyandmany-to-many) . . . . . . . . . . . . . . . . . 121 has_many . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 has_and_belongs_to_many. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 has_many:through. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 Customassociations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Recursiverelationships(self-referentialjoins). . . . . . . . . . . . . . . . . . . . . . . . . . . 130 Single-tableinheritance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 Namedscopes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Dirtyobjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 Chapter 6 PresentingtheViews. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Namingtemplates. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 MeettheERbtags. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 The<%= %>Tags. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 The<% %>Tags. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 The<%- -%>Tags. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 The<%# %>Tags. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Customlayoutcontentfromtheview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 x CONTENTS Helpermethods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Rails-providedhelpers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 stylesheet_link_tag. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 javascript_include_tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 image_tag. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Formattinghelpers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 Formhelpers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 Buildingyourownhelpers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 Partials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Callingapartialfromanothertemplate. . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Passingvariablesintoapartial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Renderacollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Chapter 7 ExploringActionPack:UnderstandingtheController . . . . . 171 Application.rbandcontrollerinheritance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Definingactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Communicationwiththecontroller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Disablingthesession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 Sessionoptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 Cookies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Adeeperlookatthecontroller’sresponse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Renderingtemplates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Directlyrendering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Redirect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Sendingdata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 send_data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 send_file. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 Propercontrollerdesign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 Skinnycontrollers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 CRUD. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 BuildingourCRUDcontroller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 Thenewaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 Thecreateaction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 Theeditaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 Theupdateaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Thedeleteaction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Updatingtheindextemplate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Chapter 8 ControllingOurRouting . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 Introducingrouting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 Whatroutingdoes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 Settingthehomedirectory. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 xi CONTENTS Regularroutes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 Prefixingourblogposts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 Routingbydate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 Namedroutes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 RESTfulrouting. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 Singularroutes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Nestedroutes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 CustomizingRESTfulroutes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Memberroutes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Collectionroutes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 rakeroutes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Chapter 9 ScaffoldingandPlug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Overviewofwhatwe’regoingtobuild . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Creatingourapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Yourfirstscaffold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Viewingthescaffold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Generatingtheplug-inscaffold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 Associatingourmodels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Cleaninguptheviews . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Addingaplug-intoourapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Modifyingourviews . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 Modifyingtheplug-inviews . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 Editingtheshowtemplate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 Addaratingscontroller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 Chapter 10 IntroductiontoTestingwithRSpec . . . . . . . . . . . . . . . . . . 253 Whatistesting? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 Whyshouldwetest?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 Isitenoughtoseethatyourapplicationisworkingcorrectly?. . . . . . . . . . . . . 254 Won’twritingtestsslowmedown?. . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Whendoweneedtowritetests? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 Introducingtesting. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 IntroducingRSpec. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 RSpecstories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 RSpecspecs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 Matchers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 InstallingRSpec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Addingmodelspecs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 AddingabeforeblocktoDRYupourspecs . . . . . . . . . . . . . . . . . . . . . . . . . 271 Removingredundancy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 Addingcontrollerspecs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 Mockingmodels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 Testingtheindexaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Testingthecreateaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 xii