Download Ruby On Rails Tutorial-Preview...
2
Ruby on Rails Tutorial Learn Web Development with Rails Michael Hartl
ii
Contents 1
From ze From zero ro to de depl ploy oy 1.1 In Intro trodu duct ctio ion n . . . . . . . . . . . . . . . 1.1.1 1.1. 1 Pr Prer ereq equi uisi sites tes . . . . . . . . . . 1.1 1.1.2 .2 Con Conve ventio ntions ns use used d in thi thiss boo book k .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1 5 6 10
1.2 1.2
Up an and d ru runn nnin ing g . . . . . . . . . . . . . 1.2.1 De 1.2.1 Devel velopm opment ent en enviro vironme nment nt . . . 1.2.2 1.2. 2 In Inst stall allin ing g Ra Rails ils . . . . . . . . . Thee fir Th first st ap appl plica icatio tion n . . . . . . . . . . . 1.3 .3.1 .1 Bun undl dler er . . . . . . . . . . . . . rails ls server server . . . . . . . . 1.3.2 rai 1.3.3 Mod 1.3.3 Model-V el-Vie iew-C w-Cont ontrol roller ler (MVC (MVC)) 1.3.4 1.3. 4 He Hell llo, o, wo worl rld! d! . . . . . . . . . . Vers ersion ion con control trol with Git Git . . . . . . . . . 1.4.1 1.4. 1 In Inst stall allat ation ion an and d se setu tup p . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
12 12 17 17 20 27 33 35 38 41
1.4. 2 Wh What at go good od do does es Git do yo you? u? . . 1.4.2 1.4. 1.4.3 3 Bi Bitb tbuc uck ket . . . . . . . . . . . . 1.4.4 Bra 1.4.4 Branch nch,, edi edit, t, com commit, mit, mer merge ge . . Depl De ploy oyin ing g . . . . . . . . . . . . . . . . 1.5.1 1.5. 1 He Hero roku ku se setu tup p . . . . . . . . . . 1.5.2 Heroku oku dep deploy loymen ment, t, step one . 1.5.2 Her 1.5 1.5.3 .3 Her Heroku oku dep deploy loymen ment, t, step two . 1. 1.5. 5.4 4 He Hero roku ku co comm mman ands ds . . . . . . . Conc Co nclu lusi sion on . . . . . . . . . . . . . . . 1.6.1 Whatt we lea learne rned d in this cha chapte pterr 1.6.1 Wha
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
43 44 50 56 56 59 59 61 62 63
1.3
1.4
1.5 1.5
1.6 1.6
iii
iv 2
A toy app 2.1 Pla Plannin nning g the app applica licatio tion n . . . . . . . . . . . . . . . . . . . . 2.1.1 2.1. 1 A to toy y mo mode dell fo forr us users ers . . . . . . . . . . . . . . . . . .
65 66 69
2.3
2.1.2 2.1. 2 A to toy y mo mode dell fo forr mic micro ropo post stss . . . . The Use The Users rs re reso sourc urcee . . . . . . . . . . . . . .2.1 .1 A us user er to tour ur . . . . . . . . . . . . . 2.2 2.2.2 2.2. 2 MV MVC C in ac acti tion on . . . . . . . . . . . 2.2.3 eaknes nesses ses of thi thiss Use Users rs res resour ource ce . 2.2.3 Weak The Micr Micropo oposts sts reso resourc urcee . . . . . . . . . . 2.3. 1 A mic micro ropo post st mi micro crotou tourr . . . . . . . 2.3.1 2.3.2 2.3. 2 Pu Putt ttin ing g th thee micro in microposts . . 2.3 .3..3 A user has_many microposts . . . 2.3.4 Inheri eritan tance ce hie hierar rarchi chies es . . . . . . . 2.3.4 Inh
2.4 4 2.
2. 2.3. 3.5 5 lusi Depl De toy app 10 08 6 Co Conc nclu sion onploy oyin . ing . g. the . . to . y. ap . .p . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 1 2.4.1 .1 Wha Whatt we lea learne rned d in this cha chapte pterr . . . . . . . . . . . . 109 2.4
2.2
3
CONTENTS
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
Mostly Most ly st stat atic ic pa page gess 3.1 Sa Samp mple le ap app p se setu tup p . . . . . . . . . . . . . . . . . 3.2 Stat atic ic pa page gess . . . . . . . . . . . . . . . . . . . . 3.2 St 3.2.1 3.2. 1 Ge Gene nera rate ted d st stat atic ic pa page gess . . . . . . . . . . 3.2. 2 Cu Custo stom m sta stati ticc pa page gess . . . . . . . . . . . 3.2.2 3.3 Gett Getting ing sta started rted with tes testing ting . . . . . . . . . . . . 3.3. 1 Ou Ourr fir first st te test st . . . . . . . . . . . . . . . 3.3.1 3.3.2 Red . . . . . . . . . . . . . . . . . . . . 3.3 .3..3 Green . . . . . . . . . . . . . . . . . . . 3. 3.3. 3.4 4 Re Refa fact ctor or . . . . . . . . . . . . . . . . . . 3.4 Slig Slightl htly y dyn dynamic amic pag pages es . . . . . . . . . . . . . . 3.4.1 esting ing titl titles es (Re (Red) d) . . . . . . . . . . . . 3.4.1 Test 3.4.2 Add 3.4.2 Adding ing pag pagee titl titles es (Gre (Green) en) . . . . . . . . 3.4.3 Layout outss and emb embedd edded ed Rub Ruby y (Re (Refac factor) tor) . 3.4.3 Lay 3. 3.4. 4.4 4 Se Setti tting ng th thee ro root ot ro rout utee . . . . . . . . . . . 3.5 5 Co Conc nclu lusi sion on . . . . . . . . . . . . . . . . . . . . 3. 3.5 3.5.1 .1 Wha Whatt we lea learne rned d in this cha chapte pterr . . . . .
. . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . . . . . . .
. 70 . 71 . 74 . 82 . 89 . 90 . 90 . 96 . 98 . 103
. . . . . . . . . . . . . . . .
111 112 117 118 127 128 133 134 136 139 140 140 143 147 154 157 159
CONTENTS
3.6
4
5
v
Advanced Advanc ed tes testing ting setu setup p . . . . . . . . . . . . . . . . . . . . . 159 3.6.1 3.6. 1 mi minit nites estt re repo port rter erss . . . . . . . . . . . . . . . . . . . . 160 3.6.2 .2 Aut Automa omated ted tes tests ts with Gua Guard rd . . . . . . . . . . . . . . 160 3.6
Rails-fla Railsflavo vore red d Rub Ruby y 4.1 Mo 4.1 Moti tiv vat atio ion n . . . . . . . . . . . . . . . . . 4.1. 1 Bu Built ilt-in -in he help lper erss . . . . . . . . . . 4.1.1 4. 4.1. 1.2 2 Cu Custo stom m he help lper erss . . . . . . . . . . Strin ings gs an and d met metho hods ds . . . . . . . . . . . . 4.2 Str 4.2.1 4.2. 1 Co Comm mmen ents ts . . . . . . . . . . . . 4.2 .2.2 .2 Str trin ings gs . . . . . . . . . . . . . . 4.2.3 .3 Obj Objects ects and mess message age pas passin sing g . . . 4.2 4.2.4 4.2. 4 Me Meth thod od de defin finiti ition onss . . . . . . . . 4.2.5 4.2. 5 Ba Back ck to th thee ti title tle he helpe lperr . . . . . . Other er da data ta str struc uctu ture ress . . . . . . . . . . . 4.3 Oth 4.3.1 4.3. 1 Ar Arra rays ys an and d ra rang nges es . . . . . . . . 4.3 .3.2 .2 Blo lock ckss . . . . . . . . . . . . . . 4. 4.3. 3.3 3 Ha Hash shes es an and d sy symb mbol olss . . . . . . . 4.3.4 4.3. 4 CS CSS S re revi visit sited ed . . . . . . . . . . . 4.4 4 Ru Ruby by cl clas asse sess . . . . . . . . . . . . . . . . 4. 4.4.1 4.4. 1 Co Cons nstru truct ctor orss . . . . . . . . . . . 4.4. 4.2 2 Cl Clas asss in inhe herit ritan ance ce . . . . . . . . . 4. 4.4 4.4.3 .3 Mod Modifyi ifying ng bu builtilt-in in cla classes sses . . . . 4.4.4 4.4. 4 A co contr ntrol olle lerr cl clas asss . . . . . . . . . 4. 4.4. 4.5 5 A us user er cl clas asss . . . . . . . . . . . . 4.5 Conc nclu lusi sion on . . . . . . . . . . . . . . . . 4.5 Co 4.5 4.5.1 .1 Wha Whatt we lea learne rned d in this cha chapte pterr . Fillin Fill ing g in th thee la lay you outt Adding ing so some me st stru ruct cture ure . . . . . . . 5.1 Add 5.1.1 5.1. 1 Si Site te na navig vigat ation ion . . . . . . . 5. 5.1. 1.2 2 Bo Boot otstr strap ap an and d cu custo stom m CS CSS S . 5.1. 1.3 3 Par arti tial alss . . . . . . . . . . . 5. 5.2 Sas Sasss and the asse assett pipe pipeline line . . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
171 171 172 173 176 178 178 182 186 188 189 190 194 198 203 205 205 207 211 213 216 219 220
. . . . .
223 224 224 233 245 251
vi
5.3 3 5.
5.4
5. 5.5 5
6
5.2.1 5.2. 1 Th Thee as asse sett pip pipel elin inee . . . . . . . . . . . . . . . . . . . . 251 5.2.2 Syntac tactica tically lly awe awesom somee styl stylesh esheet eetss . . . . . . . . . . . 255 5.2.2 Syn Layo La yout ut li link nkss . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 5.3. 1 Co Cont ntac actt pa page ge . . . . . . . . . . 5.3.1 5. 5.3. 3.2 2 Ra Rail ilss ro rout utes es . . . . . . . . . . . 5.3.3 5.3. 3 Us Usin ing g na named med ro rout utes es . . . . . . . 5.3. 3.4 4 La Layo yout ut li link nk te test stss . . . . . . . . 5. Userr sig Use signu nup: p: A fir first st ste step p . . . . . . . . 5. 5.4. 4.1 1 Us User erss co cont ntro rolle llerr . . . . . . . . . 5.4. 2 Si Sign gnup up UR URL L . . . . . . . . . . 5.4.2 Conc Co nclu lusi sion on . . . . . . . . . . . . . . . 5.5 5.5.1 .1 Wha Whatt we lea learne rned d in this cha chapte pterr
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
263 265 269 272 276 276 278 282 282
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
285 286 288 295 296 300 302 304 305 307
6.2. 3 Le Leng ngth th val alida idatio tion n . . . . . . . . . . 6.2.3 6.2. 2.4 4 Fo Form rmat at vali alida datio tion n . . . . . . . . . . 6. 6.2.5 Uni 6.2.5 Unique quenes nesss va valid lidatio ation n . . . . . . . Adding Add ing a sec secure ure pas passwo sword rd . . . . . . . . . 6. 6.3. 3.1 1 A ha hash shed ed pa passw sswor ord d . . . . . . . . . 6.3 6.3.2 .2 Use Userr has sec secure ure pas passwo sword rd . . . . . 6.3.3 .3 Min Minimu imum m pas passwo sword rd sta standa ndards rds . . . 6.3 6.3.4 Cre 6.3.4 Creatin ating g and auth authenti enticat cating ing a use userr . Conc Co nclu lusi sion on . . . . . . . . . . . . . . . . . 6.4.1 .1 Wha Whatt we lea learne rned d in this cha chapte pterr . . 6.4
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
311 313 320 329 329 332 335 337 340 341
Mode Mo deli ling ng us user erss 6.1 1 Us User er mo mod del . . . . . . . . . . 6. 6.1.1 6.1. 1 Da Data taba base se mi migr grati ation onss . 6.1.2 6.1. 2 Th Thee mo mode dell fil filee . . . . 6.1. 1.3 3 Cr Crea eatin ting g us user er ob obje ject ctss . 6. 6. 6.1. 1.4 4 Fi Find ndin ing g us user er ob objec jects ts . 6. 6.1. 1.5 5 Up Upda dati ting ng us user er ob obje jects cts . 6.2 Use Userr va vali lida datio tions ns . . . . . . . . 6.2. 2.1 1 A va valid lidity ity tes testt . . . . . 6. 6.2.2 Valid 6.2.2 alidatin ating g pre presen sence ce . .
6.3
6.4 6.4
CONTENTS
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
CONTENTS
7
vii
Sign up 343 7.1 Sh Sho owin wing g us user erss . . . . . . . . . . . . . . . . . . . . . . . . . . 344 7.1.1 Deb 7.1.1 Debug ug and Rai Rails ls en enviro vironme nments nts . . . . . . . . . . . . . 344
7.2 7.2
7.3
7.4
7.5
7.6 7.6
8
7.1. 2 A Use Users rs re reso sour urce ce . . . . . . . . 7.1.2 7.1.3 7.1. 3 De Deb bug ugge gerr . . . . . . . . . . . . 7.1.4 Grava vatar tar imag imagee and a side sidebar bar 7.1.4 A Gra Sign Si gnup up fo form rm . . . . . . . . . . . . . . . 7.2 .2..1 Usin ing g form_for . . . . . . . 7.2. 2.2 2 Si Sign gnup up fo form rm HT HTML ML . . . . . . 7. Unsucce Unsu ccessfu ssfull sign signups ups . . . . . . . . . . 7.3. 3.1 1 A wo work rkin ing g fo form rm . . . . . . . . . 7. 7.3.2 7.3. 2 St Stro rong ng pa para rame meter terss . . . . . . . 7.3. 3.3 3 Si Sign gnup up er erro rorr me mess ssag ages es . . . . . 7.
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
352 357 360 368 368 374 379 379 383 387
7.3cces 7.3.4 .4essf Aultest for inva submis Su Succ sful sign si gnup upssin valid . lid . .sub . .mission . .sion . . .. .. 7. 7.4. 4.1 1 Th Thee fin finish ished ed si sign gnup up fo form rm . . . . .4.2 .2 The flas ash h . . . . . . . . . . . . 7.4 7.4.3 7.4. 3 Th Thee fir first st sig signu nup p . . . . . . . . . 7.4.4 .4 A test for va valid lid sub submis mission sion . . . 7.4 Profes Pro fession sionalal-gra grade de dep deploy loymen mentt . . . . . 7. 7.5. 5.1 1 SS SSL L in pr prod oduc ucti tion on . . . . . . . 7.5 7.5.2 .2 Pro Produc duction tion web webserv server er . . . . . . 7.5.3 .3 Pro Produc duction tion dep deploy loymen mentt . . . . . 7.5 Conc Co nclu lusi sion on . . . . . . . . . . . . . . . 7.6 7.6.1 .1 Wha Whatt we lea learne rned d in this cha chapte pterr
.. . . . . . . . . . .
.. . . . . . . . . . .
.. . . . . . . . . . .
.. . . . . . . . . . .
.. . . . . . . . . . .
.. . . . . . . . . . .
.. . . . . . . . . . .
.. . . . . . . . . . .
.. . . . . . . . . . .
.. . . . . . . . . . .
.. . . . . . . . . . .
.. . . . . . . . . . .
39 98 1 3 398 402 405 409 412 413 414 415 417 418
. . . . . . .
419 420 421 424 429 433 434 439
Basicc lo Basi logi gin n 8. 8.1 1 Se Sess ssio ion ns . . . . . . . . . . . . . . . . . . 8.1. 1.1 1 Se Sessi ssion onss co cont ntro rolle llerr . . . . . . . . 8. 8.1. 2 Lo Logi gin n fo form rm . . . . . . . . . . . . 8.1.2 8.1.3 Fin 8.1.3 Findin ding g and aut authen hentica ticatin ting g a use userr 8.1.4 Render dering ing with a flas flash h mess message age . 8.1.4 Ren 8.1 .1.5 .5 A fla flash sh te test st . . . . . . . . . . . . 8.2 2 Lo Logg ggin ing g in in . . . . . . . . . . . . . . . . . 8.
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
viii
8.2.1 8.2.2 8.2. 2 8.2.3 8.2.3
8.3 8.3 8.4 8.4
9
CONTENTS
The log_in method method . . . . . . . . . . . . . . . . . . 440 Curr Cu rren entt us user er . . . . . . . . . . . . . . . . . . . . . . . 442 Changi Cha nging ng the lay layout out lin links ks . . . . . . . . . . . . . . . 448
8.2.4 .4 Test esting ing lay layout out cha change ngess . . . . . 8.2 8.2.5 8.2. 5 Lo Logi gin n up upon on si sign gnup up . . . . . . . Logg Lo ggin ing g ou outt . . . . . . . . . . . . . . . Conc Co nclu lusi sion on . . . . . . . . . . . . . . . 8.4 8.4.1 .1 Wha Whatt we lea learne rned d in this cha chapte pterr
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
454 459 462 465 466
Advanc Adva nced ed lo logi gin n 467 9. 9.1 1 Re Reme memb mber er me me . . . . . . . . . . . . . . . . . . . . . . . . . . 467 9.1.1 Rememb ember er tok token en and dige digest st . . . . . . . . . . . . . . 468 9.1.1 Rem 9.1.2 9.1. 2 Lo Logi gin n wi with th re reme membe mberin ring g . . . . . . . . . . . . . . . . 475
9.2 9.3
9.4 4 9.
9.1. 3 Forg rget ettin ting geus user ers s . .. .. .. .. .. .. .. .. .. 9.1.3 9.1. 1.4 4 Fo Two subtl su btle bugs bu gs 9. “Remem “Re member ber me” che checkb ckbox ox . . . . . . . . Reme Re memb mber er te tests sts . . . . . . . . . . . . . . 9.3.1 Test 9.3.1 esting ing the “re “remem member ber me” box . 9.3 9.3.2 .2 Test esting ing the rem rememb ember er bra branch nch . . . Conc Co nclu lusi sion on . . . . . . . . . . . . . . . . 9.4 9.4.1 .1 Wha Whatt we lea learne rned d in this cha chapte pterr .
10 Updating, Updating, showing showing,, and deleting deleting users 10.1 Updatin Updating g users . . . . . . . . . . . . 10. 10.1.1 1.1 Edi Editt form . . . . . . . . . . . 10.1.2 Unsucc Unsuccessful essful edits . . . . . . unsuccessful essful edits . . 10.1.3 Testing unsucc 10.1.4 Succe Successful ssful edits (with TDD) . 10.2 Authori Authorization zation . . . . . . . . . . . . . Requiring ring logged logged-in -in users . . 10.2.1 Requi 10.2.2 Requi Requiring ring the right user . . . 10.2.3 Friend Friendly ly forwar forwarding ding . . . . . Showing wing all users . . . . . . . . . . . 10.3 Sho 10. 10.3.1 3.1 Use Users rs ind index ex . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
.. . . . . . .
. . . . . . . . . . .
.. . . . . . .
. . . . . . . . . . .
.. . . . . . .
.. . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
.. . . . . . .
. . . . . . . . . . .
.. . . . . . .
. . . . . . . . . . .
.. . . . . . .
. . . . . . . . . . .
.. . . . . . .
. . . . . . . . . . .
.. . . . . . .
. . . . . . . . . . .
.. . . . . . .
. . . . . . . . . . .
.. . . . . . .
48 87 5 4 493 500 500 507 511 511
. . . . . . . . . . .
513 513 514 522 525 526 530 532 538 544 548 549
CONTENTS
ix
10. 10.3.2 3.2 Sample Sample use users rs . . . . . . . . . . . . . . . . . . . . . . 554 10.3.3 Pa 10.3.3 Pagin ginatio ation n . . . . . . . . . . . . . . . . . . . . . . . 559 10.3.4 3.4 Use Users rs ind index ex test test . . . . . . . . . . . . . . . . . . . . . 564 10. 10.3.5 Parti Partial al refac refactoring toring . . . . . . . . 10.4 Dele 10.4 Deleting ting use users rs . . . . . . . . . . . . . . Administrati trative ve users . . . . . . 10.4.1 Adminis 10.4.2 10.4. 2 Th Thee destroy action action . . . . . . 10.4.3 Use 10.4.3 Userr destr destroy oy test testss . . . . . . . . 10.5 Conclu Conclusion sion . . . . . . . . . . . . . . . 10.5.1 What we learned learned in this this chapter chapter
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
566 568 568 574 577 581 583
11 Account Account activa activation tion 585 11.1 Accoun Accountt activati activations ons resource resource . . . . . . . . . . . . . . . . . . 586
11.2
11.3
11.4 11.5
Account activations activ ations controller ller .. .. .. .. .. .. .. .. .. 11.1.1 11.1.2 Accoun Accounttt activati Accoun acti vation on data dcontro ata model model Accountt activati Accoun activation on emails emails . . . . . . . . . . . . . . . . 11.2.1 2.1 Mai Mailer ler temp template latess . . . . . . . . . . . . . . . . 11. 11.2.2 Email pre preview viewss . . . . . . . . . . . . . . . . . 11.2.3 Ema 11.2.3 Email il tes tests ts . . . . . . . . . . . . . . . . . . . 11.2.4 Updati ating ng the the User Userss create action . . . . . . 11.2.4 Upd Activating Activ ating the account account . . . . . . . . . . . . . . . . . 11.3.1 3.1 Gen Genera eralizi lizing ng the authenticated? method 11. 11.3.2 Act 11.3.2 Activ ivatio ation n edit action . . . . . . . . . . . . 11.3.3 Acti Activati vation on test test and and refacto refactoring ring . . . . . . . . . Email in product production ion . . . . . . . . . . . . . . . . . . . Conclusion Conclu sion . . . . . . . . . . . . . . . . . . . . . . . 11.5.1 What we learned learned in this this chapter chapter . . . . . . . .
12 Password Password rese resett 12.1 Passw Password ord resets resets resourc resourcee . . . . . . . . 12.1.1 Pass Password word resets contro controller ller . . . 12.1.2 New passwo password rd resets . . . . . . 12.1.3 1.3 Pa Passw ssword ord res reset et create action action . 12. 12.2 Passw Password ord reset emails emails . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
.. . . . . . . . . . . . .
. . . . .
.. . . . . . . . . . . . .
. . . . .
.. . . . . . . . . . . . .
. . . . .
.. . . . . . . . . . . . .
5 58 87 9 596 596 602 606 608 613 613 619 622 630 634 634
. . . . .
635 639 640 643 646 651
x
CONTENTS
12.2.1 Pass Password word reset mailer and templates templates . . . . . . . . . . 651 12.2.2 2.2 Ema Email il tes tests ts . . . . . . . . . . . . . . . . . . . . . . . 658 12. 12.3 Resetti Resetting ng the the password password . . . . . . . . . . . . . . . . . . . . . 659 12 12.3. .3.1 1 Re Rese sett edit action . . . . . . . 12.3.2 3.2 Upd Updati ating ng the the rese resett . . . . . . . 12. Password word reset test . . . . . . . 12.3.3 Pass 12.4 Email in produc production tion (take (take two) two) . . . . . Conclusion sion . . . . . . . . . . . . . . . 12.5 Conclu 12.5.1 What we learned learned in this this chapter chapter 12.6 Proof of expir expiration ation comparis comparison on . . . . . micropost opostss 13 User micr 13. 13.1 1 A Microp Micropost ost mode modell . . . . . . . . . . . 13.1.1 basic ic mod model el . . . . . . . . 13.1.1 The bas 13.1.2 Microp Micropost ost val validation idationss . . . . . . User/Micropos cropostt associ associations ations . . 13.1.3 User/Mi 13.1.4 Microp Micropost ost refine refinements ments . . . . . 13.2 Sho Showing wing micropo microposts sts . . . . . . . . . . . 13.2.1 Rende Rendering ring microp microposts osts . . . . . 13.2.2 Sample micropo microposts sts . . . . . . . 13.2.3 Profile micropo micropost st tests . . . . . 13.3 Manipu Manipulating lating microp microposts osts . . . . . . . . 13.3.1 Microp Micropost ost access contro controll . . . . 13.3.2 Creati Creating ng micropo microposts sts . . . . . . 13.3.3 proto-f to-feed eed . . . . . . . . . . 13.3.3 A pro 13.3.4 Destro Destroying ying microp microposts osts . . . . . 13.3.5 Mic 13.3.5 Microp ropost ost tes tests ts . . . . . . . . . Micropost st images . . . . . . . . . . . . 13.4 Micropo 13.4.1 Basic ic imag imagee uploa upload d . . . . . . . 13.4.1 Bas 13.4.2 Image vali validation dation . . . . . . . . 13.4.3 4.3 Ima Image ge resi resizin zing g . . . . . . . . . 13. 13.4.4 Image upload in produc production tion . . Conclusion sion . . . . . . . . . . . . . . . 13.5 Conclu 13.5.1 What we learned learned in this this chapter chapter
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
659 663 670 675 679 679 680
. . . . . . . . . . . . . . . . . . . . . .
683 683 684 687 690 695 700 700 707 714 718 719 722 732 739 744 748 748 756 759 763 768 770
CONTENTS
xi
Following ing users 771 14 Follow 14.1 The Relatio Relationship nship model model . . . . . . . . . . . . . . . . . . . . . 772 14.1.1 A problem problem with the data data model model (and a solution) solution) . . . . 772
14.1.2 User/re User/relations lationship hip associa associations tions . . . . . . . 14.1.3 Relati Relationship onship val validation idationss . . . . . . . . . . 14.1.4 Follo Followed wed users . . . . . . . . . . . . . . . 14.1.5 Fo 14.1.5 Follo llower werss . . . . . . . . . . . . . . . . . . interface for for following following users users . . . . . . . . 14.2 A web interface following wing data . . . . . . . . . . . 14.2.1 Sample follo 14.2.2 Stats ts and and a follo follow w form form . . . . . . . . . . . 14.2.2 Sta 14.2.3 Follo Following wing and follo followers wers pages pages . . . . . . . 14.2.4 A working working follow follow butto button n the standar standard d way way . 14.2.5 A working working follo follow w button button with with Ajax Ajax . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
782 785 786 790 793 794 795 807 818 823
14.2.6 Following Follo wing 14.3 status stat us feed feed . tests . . . .. .. .. .. .. .. .. .. .. 14.3 The 14.3.1 Moti Motivat vation ion and strate strategy gy . . . . . implementation ntation . . 14.3.2 A first feed impleme 14.3.3 Subsele selects cts . . . . . . . . . . . . 14.3.3 Sub 14.4 Conclu Conclusion sion . . . . . . . . . . . . . . . resources ces . . . 14.4.1 Guide to further resour 14.4.2 What we learned learned in this this chapter chapter
.. . . . . . .
.. . . . . . .
.. . . . . . .
.. . . . . . .
.. . . . . . .
.. . . . . . .
83 20 8 8 832 834 838 843 844 845
.. . . . . . .
.. . . . . . .
.. . . . . . .
.. . . . . . .
.. . . . . . .
.. . . . . . .
xii
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). drama). This book by Michael Hartl came so highly recommended recommended that I had to try it, and the 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 fina lly made me “ge “get” t” it. Ev Every erythin thing g is done very much “the Rails way”—a 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 approa approach ch highly recommend recommended ed 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 it’s lik likee to do a real-w real-worl orld d pro projec ject. t. The tutorial tutorial’’s code code exa example mpless are not in isolation. The linear narrative narrative is such a great format. Person Personally ally,, I powered through through 1
the Rails Tutorial in three long days, doing all the examples examples and challenges at the end of each chapte chapterr. Do it from start to finish, without jumping around, and you’lll get the ultimat you’l ultimatee benefi benefit. t. Enjoy! Derek Sivers Sivers ( (sivers.org sivers.org)) Founder, CD Baby
1
This is not typical! Getting through the entire book usually takes much longer than three days.
xiii
xiv
CONTENTS
Acknowledgments The Ruby on Rails Tutorial owes a lot to my previous Rails book, RailsSpace, and hence to my coauthor Aurelius Prochazka. Prochazka. I’d I’d like like to thank thank Aure Aure both for the work he did on that book and for his support support of this this one. I’d I’d also like to thank Debra Williams Cauley, my editor on both RailsSpace and the Ruby on 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 spi red me ov over er the years: years: Da David vid Heine Heinemeie meierr Hansso Hansson, n, Yehuda ehuda Kat Katz, z, Car Carll Lerche, Jeremy Kemper, Xavier Noria, Ryan Bates, Geoffrey Grosenbach, Peter Cooper, Matt Aimonetti, Mark Bates, 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, Pratik Naik, Sarah Mei, Sarah Allen, Wolfram Arnold, Alex Chaffee, Giles Bowke Bo wkett, tt, Ev Evan an Dorn, Dorn, Long Long Ngu Nguyen yen,, James James Linden Lindenbau baum, m, Ada Adam m Wigg iggins, ins, Tikhon Bernstam, Ron Evans, Wyatt Greene, Miles Forrest, Sandi Metz, Ryan Davis, Aaron Patterson, the good people at Pivotal Labs, the Heroku gang, the thoughtbot guys, and the GitHub crew. I’d like to thank technical reviewer Andrew Thai for his careful reading of the man manusc uscript ript and for his helpf helpful ul sugge suggestio stions. ns. I’d I’d als also o like like to thank my cofounders at Learn at Learn Enough to Be Dangerous Dangerous,, Nick Merwin and Lee Donahoe, for all their help in preparing this tutorial. Finally,, many Finally many,, many reader readers—far s—far too man many y to list—ha list—have ve contrib contributed uted 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.
xv
xvi
CONTENTS
About the author Hartl is the author of the Ruby on Rails Tutorial, one of the leading Michael Hartl is introductions to web development, and is a founder of the educational website Learn site Learn Enough to Be Dangerous Dangerous (learnenough.com). learnenough.com). His prior experience includes writing and developing RailsSpace, an extremely obsolete Rails tutorial book, and developing Insoshi, a once-popular and now-obsolete social networking platform in Ruby on Rails. In 2011, Michael received a Ruby a Ruby Hero Award for Award for his contributions to the Ruby community. He is a graduate of Har Harvard College, College, has a Ph.D. a Ph.D. in Physics Physics from from Caltech Caltech,, and is an alumnus of the Y Combinator entrepreneur Combinator entrepreneur program.
xvii
xviii
CONTENTS
Copyright and license Copyright right © 2016 Ruby on Rails Tutorial Tutorial:: Learn W Web eb Development with Rails. Copy by Michael Hartl. Last updated 2017/02/07 16:11 PT. All source code in the Ruby on Rails Tutorial is available jointly under the License and the Beerware MIT License and the Beerware License License.. The The MIT MIT Lic Licen ense se Copyrig Cop yright ht (c) 201 2016 6 Mic Michael hael Hartl Permi Permiss ssion ion is hereb hereby y gra grant nted, ed, fre free e of charg charge, e, to any perso person n obt obtain ainin ing g a copy copy of this softwar software e and asso associat ciated ed doc documen umentati tation on fil files es (th (the e "Sof "Softwa tware") re"), , to deal in the Soft Software ware with without out res restric triction tion, , inc includi luding ng wit without hout limi limitati tation on the rig rights hts to use, copy copy, , mod modify, ify, merg merge, e, publ publish ish, , dis distrib tribute, ute, subl sublicen icense, se, and/ and/or or sell copie copies s of the the Softw Softwar are, e, and and to per permi mit t perso persons ns to who whom m the Soft Softwa ware re is furni furnish shed ed to do so, subje subject ct to the fol follo lowin wing g con condi ditio tions ns: : The The abov above e copyr copyrig ight ht notic notice e and thi this s per permi missi ssion on notic notice e sha shall ll be inc inclu luded ded in all cop copies ies or sub substan stantial tial portio portions ns of the Sof Softwar tware. e. THE THE SOFT SOFTWAR WARE E IS PRO PROVI VIDED DED "AS "AS IS", IS", WITHO WITHOUT UT WARR WARRANT ANTY Y OF ANY KIND, KIND, EXP EXPRE RESS SS OR IMP IMPLIED LIED, INC INCLUDI LUDING BUT NOT LIMI LIMITED TED THE WAR WARRANT RANTIES IES MER MERCHAN CHANTABI LITY, , FITNE FITNESS SS,FOR A PARTI PANG RTICU CULAR LAR PURP PURPOS OSE E AND ANTO D NONI NO NINFR NFRING INGEM EMENT ENT. .OFIN NO EVENT EVTABILITY ENT SHAL SHALL L THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI LIABILI LITY, TY, WHETH WHETHER ER IN AN ACTIO ACTION N OF CON CONTR TRACT ACT, , TOR TORT T OR OTHER OTHERWIS WISE, E, ARI ARISI SING NG FROM, FROM, OU OUT T OF OR IN CO CONN NNEC ECTI TION ON WI WITH TH TH THE E SO SOFT FTWA WARE RE OR TH THE E US USE E OR OTHE OTHER R DE DEAL ALIN INGS GS IN THE SOFTWAR SOFTWARE. E.
THE BEE BEERWAR RWARE E LICE LICENSE NSE (Rev (Revisio ision n 42) Michael Hartl wrote this code. As long as you retain this notice you can do whate whateve ver r you you wan want t with with this this stuff stuff. . If we mee meet t some some day, day, and and you you thi think nk this this st stuf uff f is wo wort rth h it it, , yo you u ca can n buy buy me a be beer er in re retu turn rn. .
xix
xx
CONTENTS
Chapter 1
From zero to deploy Welcome to Ruby on Rails Tutorial: Learn Web Development with Rails . The purpose of this tothe teach you how to on develop custom web applications, and our tool of book choiceis is popular popular Ruby Rails Ruby Rails web web framework. In addition to focusing on general principles of web development (rather than on Rails Ruby on Rails Tutorial Tutorial teaches teaches the broader skill of technical technical specifically) specifi cally),, the the Ruby 1 1.1), which is a principal theme developed by the Learn sophistication (Box 1.1), Enough to Be Dangerous tutorials. Dangerous tutorials.2 In particular, the Learn Enough introductory sequence consists of a series of tutorials that are suitable as prerequisites to the Ruby the Ruby on Rails Tutorial, Tutorial, starting with Learn Enough Command Line to Be Dangerous Danger ous,3 which (unlike the present tutorial) is aimed at complete beginners.
Box 1.1. Technical sophistication
the Learn Enough to Be Dangerous famDangerous famThe Ruby on Rails Tutorial is The Ruby Tutorial is part of the Learn ily of tutorials, which develop the theme of technical technical sophistication: the combination of hard and soft skills that make it seem like you can magically solve any technical techni cal problem (Figure 1.1). 1.1). Web development, and computer programming in 1
Copyright © Randall Munroe and used unaltered under the terms of the Creative Commons AttributionNonCommercial 2.5 Generic license.. Generic license.. 2 learnenough.com/story 3 learnenough.com/command-line
1
2
CHAP CHAPTER TER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
general, are essential components of technical sophistication, but there’s more to it than that—you also have to know how to click around menu items to learn the capabilities of a particular application, how to clarify a confusing error message Googling it it,, or when to give up and just reboot the darn thing. by Googling by Because web applications have so many moving parts, they offer ample opportunities portun ities to devel develop op your technical sophis sophisticatio tication. n. In the context of Rails web development, some specific examples of technical sophistication include making bundle le inst install all or sure you’re using the right Ruby gem versions, running bund bundle bund le upda update te, and restarting the local webserver if something doesn’t work. (Don’t worry if all this sounds like gibberish; we’ll cover everything mentioned here in the course of completing this tutorial.) As you proceed through this tutorial, in all likelihood you will occasionally be tripped tripped up by thin things gs not imme immedia diately tely working working as ex expec pected ted.. Althoug Although h some some particularly tricky steps are explicitly highlighted in the text, it is impossible to anticip ant icipate ate all the thing thingss tha thatt can go wrong. wrong. I rec recomme ommend nd you embrac embracee the these se inevitable stumbling blocks as opportunities to work on improving your technical sophistication. Or, as we say in geek in geek speak : It’s not a bug, it’s a feature!
The Ruby on Rails Tutorial is designed to give you a thorough introduction to web application development, including a basic grounding in Ruby, Rails, HTML & CSS, databases, version control, testing, and deployment—sufficient to launch you on a career career as a web dev develo eloper per or tec techno hnolog logy y entrep entrepren reneur eur.. If you already know web development, this book will quickly teach you the essentials of the Rails framework, including MVC and REST, generators, migrations, tio ns, routin routing, g, and embe embedde dded d Ruby Ruby.. In any case, case, whe when n you finis finish h the Ruby on Rails Tutorial you will be in a position to benefit from the many more advanced books, blogs, and screencasts that are part of the thriving programming educational ecosystem.4 The Ruby on Rails Tutorial takes an integrated approach to web develop4
The mos mostt up-toup-to-dat datee versi version on of the Ruby on Rai Rails ls Tuto utoria riall can be fo foun und d on the the bo book ok’’s webs websit itee at http://www.railstutorial.org/ http://www.railstutorial.org/ .. If you are reading reading this this book offline, offline, be sur suree to check check the the online online version of the Rails Tutorial book at at http://www.railstutorial.org/book for for the latest updates.
3
Figure 1.1: “Tech “Tech Support Cheat Sheet Sheet”” (via xkcd (via xkcd). ).
4
CHAP CHAPTER TER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
ment by building three example applications of increasing sophistication, start1.3), ), a slightly more capable toy app ing with a minimal hello app (Section (Section 1.3 (Chapter 3 through 3 through Chapter Chapter 14). 14). As imim(Chapter 2), 2), and a real sample app (Chapter plied by their generic names, the applications developed in the Ruby on Rails Tutorial are not specific specific to any part particu icular lar kind of website website.. The final sample sample application bears more than a passing resemblance to Twitter to Twitter (which, (which, coincidentally dental ly,, was also origin originally ally written in Rails) Rails),, but the emphasis emphasis throughout throughout the tutorial is on general principles, so you will have a solid foundation no matter what kinds of web applications you want to build. In this first chapter, we’ll get started with Ruby on Rails by installing all the necessary software and by setting up our development environment (Sec( Section 1.2). 1.2). We’ll then create our first Rails application, application, called hello_app. The Rails Tutorial emphasizes good software development practices, so immediately afterGit creating our fresh newbelieve Rails we’ll putchapter it under version 1.4). ). And, belie ve project it or not, in this chapte r we’ll evenconput trol with (Section (Section 1.4 1.5). ). our first app on the wider web by deploying it to production (Section (Section 1.5 In Chapter In Chapter 2 2,, we’ll make a second project, whose purpose is to demonstrate the basic workings of a Rails application. To get up and running quickly, we’ll (Box 1.2) 1.2) to generate build this toy app (called toy_app) using scaffolding (Box code; because this code is both ugly and complex, Chapter 2 will focus on interacting with the toy app through its URIs (often called URLs)5 using a web browser. The rest of the tutorial focuses on developing a single large real sample writing all the cod codee from scra scratch tch.. We’ll e’ll application (called sample_app), writing mockups, test-driven developdevelop the sample app using a combination of mockups (TDD), and integration tests. We’l e’lll get starte started d in Chapter in Chapter 3 by 3 by creating ment (TDD), static sta tic pages and then add a litt little le dynamic dynamic con conten tent. t. We’ll e’ll take take a qui quick ck detour in Chapter in Chapter 4 4 to to learn a little about the Ruby language underlying Rails. Then, Chapter 12, 12, we’ll comple complete te the founda foundation tion for the sample in Chapter in Chapter 5 through 5 through Chapter application by making a site layout, a user data model, and a full registration and authen authentication tication system (includ (including ing accou account nt activati activation on and password password resets). resets). Finally, in Chapter in Chapter 13 and 13 and Chapter Chapter 14 we’ll 14 we’ll add microblogging and social fea5
URI stands stands for Uniform Resource Identifier, Identifier, while the slightly less general URL stands for Uniform Resource
Locator. In practice, the URL is usually equivalent to “the thing you see in the address bar of your browser”.
1.1. INTRODUC INTRODUCTION TION
5
tures to make a working example site.
Box 1.2. Scaffolding: Quicker, easier, more seductive
From the beginning, Rails has benefited from a palpable sense of excitement, starting with the famous 15-minute famous 15-minute weblog video video by by Rails creator David Heinemeier mei er Hanss Hansson. on. Tha Thatt video and its succe successo ssors rs are a gre great at way to get a taste of Rails’ power, and I recommend watching them. But be warned: they accomplish their amazing fifteen-minute feat using a feature called scaffolding, which relies generate te scaff scaffold old heavily on generated code, magically created by the Rails genera command. When writing a Ruby on Rails tutorial, it is tempting to rely on the scaffolding approach—it’s approach—it’s quicker, quicker, easier, seductive seductive. . whel Butelmi the complexity and amou am ount nt of co code de in th the e scaf scaffo fold ldin ing g can camore n be utte ut terl rly y over overwh ming ng to a begi beginn nnin ing g sheer Rail Railss developer; you may be able to use it, but you probably won’t understand it. Following the scaffolding approach risks turning you into a virtuoso script generator with little (and brittle brittle)) actual know knowledge ledge of Rails. In the Ruby on Rails Tutorial, we’ll take the (nearly) polar opposite approach: although Chapter although Chapter 2 2 will will develop a small toy app using scaffolding, the core of the in Chapter 3. 3. At each Rails Tutorial is the sample app, which we’ll start writing in Chapter stage of developing the sample application, we will write small, bite-sized pieces pieces of code—simple enough to understand, yet novel enough to be challenging. The cumulative effect will be a deeper, more flexible knowledge of Rails, giving you a good background background for writing nearly any type of web applicatio application. n.
1.1 1. 1
Intr Introd oduc ucti tion on
Ruby on Rails (or just “Rails” for short) is a web development framework written in the Ruby programming language. Since its debut in 2004, Ruby on Rails has rapidly become one of the most powerful and popular tools for building dynamic web applications. applications. Rails is used by companies as varied as as Airbnb Airbnb,, Base-
6
CHAP CHAPTER TER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
camp camp,, Disney, Disney, GitHub GitHub,, Hulu, Hulu, Kickstarter Kickstarter,, Shopify, Shopify, Twitter, Twitter, and the Yellow Pages.. There Pages There are als also o many many web dev develop elopment ment shop shopss that that special specialize ize in Rails, Rails, thoughtbot, Pivotal Labs, Labs, Hashrocket, Hashrocket, and HappyFunCorp and HappyFunCorp,, plus such as ENTP as ENTP,, thoughtbot, innumerable independent consultants, trainers, and contractors. What Wh at mak makes es Rails Rails so grea great? t? Firs Firstt of all, Ruby Ruby on Rail Railss is 100% openopensource, available under the generous MIT generous MIT License, License, and as a result it also costs nothing to download or use. Rails also owes much of its success to its elegant lanand compact design; by exploiting the malleability of the underlying Ruby underlying Ruby lanlanguage for for writing web apguage, Rails effectively creates a domain-specific a domain-specific language plications. As a result, many common web programming tasks—such as generating HTML, making data models, and routing URLs—are easy with Rails, and the resultin resulting g applic application ation code is concis concisee and readable. readable. Rails also adapts rapidly to new developments in web technology and framework frame work design. Forthe exampl example, Rails was one of the framework frameworks to fully digest and implement RESTe,architectural style for first structuring websapplications (which we’ll be learning about throughout this tutorial). And when other frameworks develop successful new techniques, Rails creator David Heinemeier Hansson and Hansson and the Rails the Rails core team team don’t don’t hesitate to incorporate their ideas. Perhaps the most dramatic example is the merger of Rails and Merb, a rival Ruby web framework, so that Rails now benefits from Merb’s modular design, stable API stable API,, and improved performance. Finally,, Rails benefits from an unusually Finally unusually enthusiastic enthusiastic and suppo supportiv rtivee community mun ity.. The result resultss inc include lude thousand thousandss of ope open-s n-sour ource ce contributors contributors,, fun and conferences,, a huge number of gems (self-contained gems (self-contained solutions to informative conferences informative specific problems such as pagination and image upload), a rich variety of informative mati ve blogs, and a cornuc cornucopia opia of discussio discussion n forums and IRC channels. The large number of Rails programmers also makes it easier to handle the inevitable applica app lication tion errors errors:: the “Go “Googl oglee the err error or mes messag sage” e” alg algori orithm thm nearly nearly always always produces a relevant blog post or discussion-forum thread.
1.1.1 1.1 .1
Prer Prerequ equisi isites tes
There are no formal prerequisites to this book, and the Ruby on Rails Tutorial contains integrated tutorials not only for Rails, but also for the underlying Ruby
1.1. INTRODUC INTRODUCTION TION
7
language, the default Rails testing framework (minitest), the Unix command line, HTML line, HTML,, CSS, CSS , a small amount of JavaScript, JavaScript, and even a little SQL little SQL.. That’s a lot of material to absorb, though, and I generally recommend having some HTML and progra HTML programmin mming g bac backgr kgroun ound d bef before ore startin starting g this tutorial. tutorial. If you you’’re new to software development, I recommend starting with the tutorials at Learn at Learn 6 Enough to Be Dangerous instead: Dangerous instead: 1. Developer Fundamentals (a) Learn Enough Command Line to Be Dangerous (b) Learn Enough Text Editor to Be Dangerous (c) Learn Enough Git to Be Dangerous 2. Web Basics (a) Learn Enough HTML to Be Dangerous (b) Learn Enough CSS & Layout to Be Dangerous (c) Learn Enough JavaScript to Be Dangerous 3. Intro Ruby Web Development (a) Learn Enough Ruby to Be Dangerous (b) Learn Enough Sinatra to Be Dangerous (c) Learn Enough Ruby on Rails to Be Dangerous 4. Professional Ruby Web Development • The Ruby on Rails Tutorial One common question when learning Rails is whether to learn Ruby first. The answer depends on your personal learning style and how much programming experience experience you already hav have. e. If you prefer to learn everythin everything g systematically from the ground up, or if you have never programmed before, then 6
As of this writing, the command line, text editor, and Git tutorials are complete, and the other tutorials are in development.
8
CHAP CHAPTER TER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
learning Ruby first might work well for you, and in this case I recommend follo fol lowin wing g the full Lea Learn rn Enough sequ sequenc encee list listed ed above. above. On the other hand, many beginning Rails developers are excited about making web applications, and would rather not wait to finish a whole book on Ruby before ever writing a single web page. In this case, I recommend giving this tutorial a go and switching switchi ng to the Learn Enough sequence if it proves too challenging. challenging. At the end of this tutorial, no matter where you started, you should be ready for the many more intermediate-to-adv intermediate-to-advanced anced Rails resour resources ces out there. Here are some I particu particularly larly recommend recommend:: Society:: Premium subscription service that includes • The Learn Enough Society a special enhanced version of the Ruby on Rails Tutorial book and 15+ hours of streaming screencast lessons filled the kind of with tips, tricks, and demos thatother Learn you can’t getEnough tutor from reading a book. Also includes text and live videos for the other Enough Learn tutorials. ials. Scholarship Schol arship discounts discou nts are available. School:: Good interactive online programming courses • Code School • The The Turing Turing School of Software & Design Design:: A full-time, 27-week training program in Denver, Colorado online ine bootca bootcamp mp with a stru structu ctured red curriculu curriculum, m, per person sonaliz alized ed • Bloc: Bloc: An onl mentorship, mentor ship, and a focus on learning throu through gh concrete proje projects. cts. Use the coupon code BLOCLOVESHARTL to get $500 off the enrollment fee. School:: A good online Rails development development bootc bootcamp amp (includes (includes • Launch School advanced material) • Firehose Project Project:: A mentor-driven, online coding bootcamp focused on real-world programming skills like test-driven development, algorithms, and building an advanced web application as part of an agile team. Twoweek free intro course course.. • Thinkful: Thinkful: An online class that pairs you with a professional engineer as you work through a project-based curriculum
1.1. INTRODUC INTRODUCTION TION
9
• Pragmatic Studio: Studio: Online Ruby and Rails cou courses rses from Mike and Nicole Clark. Cla rk. Alon Along g with Pr author hor Dave Dave Tho Thomas mas,, Mike Mike tau taught ght Progra ogrammin mming g Ruby aut the first Rails course I took, way back in 2006. RailsApps:: A large variety of detailed topic-specific Rails projects and • RailsApps tutorials • Rails Guides Guides:: Topical and up-to-date Rails references Exercises
The Ruby on Rails Tutorial contains The Ruby Tutorial contains a large number of exercises. Solving them as you procee proceed d through the tutoria tutoriall is strongly recommended. recommended. In order to keep the main discussion independent of the exercises, the solution lut ionss are not gen genera erally lly incorpor incorporate ated d into subs subsequ equent ent code listing listings. s. (In the rare circumstance that an exercise solution is used subsequently, it is explicitly solve sol ved d in the mai main n tex text.) t.) This This mea means ns that over time your code may div diver erge ge from the code shown in the tutorial due to differences introduced in the exercises. ercise s. Learn Learning ing how to resolve such discrepa discrepancies ncies is a valu valuable able exercise exercise in technical sophistication (Box (Box 1.1). 1.1). To record your answers and see solutions, you can join the Learn the Learn Enough Society,, a subscription service from Learn Enough to Be Dangerous Society Dangerous that that includes a specia speciall enhan enhanced ced version of the Ruby the Ruby on Rails Tutorial. Tutorial. Many of the exercises are challenging, but we’ll start out with some easy ones just to get warmed up: 1. Whi Which ch webs website ite hos hosts ts the Ruby gem for Ruby on Rails? Hint : When in doubt, Google doubt, it. Google it. 2. What is the ccurrent urrent v version ersion n number umber of Ra Rails? ils? 3. As of this moment, ho how w many total times has Rub Ruby y on Rails been downdownloaded?
10
1.1.2 1.1 .2
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Conve Conventi ntions ons used used in this this book book
The convention conventionss used in this book are mostly self-e self-explana xplanatory tory.. In this section, section, we’ll go over some that may not use be. command-line commands. For simplicity, Many examples in this book all command line examples use a Unix-style command line prompt (a dollar sign), as follows: "hello, world" $ echo "hello, hello, hel lo, worl world d
Rails comes with many comm Rails command andss tha thatt can be run at the command command line. For For example, in Section in Section 1.3.2 we’ll 1.3.2 we’ll run a local development webserver with the rai rails ls ser server ver command: $ rails serv server er
As with the command-line prompt, the Rails Tutorial uses the Unix convention for directory separators (i.e., a forward slash / ). For example, the sample application production.rb configuration file appears as follows: config/environments/production.rb
This file path should be understood as being relative to the application’s root directory, which will vary by system; on the cloud IDE (Section ( Section 1.2.1), 1.2.1), it looks like this: /home/ubuntu/workspace/sample_app/
Thus, the full path to production.rb is
1.1. INTRODUC INTRODUCTION TION
11
/home/ubuntu/workspace/sample_app/config/environments/production.rb
I will typically omit the application path and write just config/environ ments/production.rb for short. The Rails Tutorial often often shows outp output ut from from va vario rious us programs. programs. Bec Becaus ausee of the innumerable small differences between different computer systems, the output you see may not always agree exactly with what is shown in the text, but this is not cause for concern. In addition, some commands may produce errors depending on your system; rather than attempt the Sisyphean Sisyphean task of documenting all such errors in this tutorial, I will delegate to the “Google the error message” algorithm, which among other things is good practice for real-life software development (Box (Box 1.1 1.1). ). If you run into any problems while following following the tutorial, I suggest consulting the resources listed in the Rails the Rails Tutorial help page. page .7 Because the Rails Tutorial covers testing of Rails applications, it is often helpful to know if a particular piece of code causes the test suite to fail (indicated by the color red) or pass (indicated by the color green). For convenience, code resulting in a failing test is thus indicated with RE D, while code resulting in a passing test is indicated with GREEN. Finally, for convenience the Ruby on Rails Tutorial adopts two conventions design des igned ed to mak makee the many cod codee samp samples les easi easier er to und unders erstan tand. d. First, First, some some code listings include one or more highlighted highlighted lines, as seen belo below: w: class User < ApplicationRecord validates :name :name, , presence presence: : true validates :email :email, , presence: presence: true end
Such highlighted lines typically indicate the most important new code in the given sample, and often (though not always) represent the difference between the the prese present nt co code de listi listing ng an and d pre previo vious us lis listin tings gs.. Seco Second nd,, for br brev evity ity and and si simp mplic licity ity many of the book’s code listings include vertical dots, as follows: 7
railstutorial.org/help
12
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
class User < ApplicationRecord . . . has_secure_password end
These dots represent omitted code and should not be copied literally.
1.2
Up and run runni ning ng
Even for experienced Rails developers, installing Ruby, Rails, and all the associated sociat ed supporting softw software are can be an exercis exercisee in frustration. frustration. Compounding Compounding the problem is thepreferences multiplicityinoftext enviro environments nments: different different development operating operating systems, version numbers, editor and :integrated envi Ruby on Rails Tutorial Tutorial offers offers two recommended soluronmentt (IDE), etc. The ronmen The Ruby tions to this problem. One possibility is to follow the full Learn Enough intro Enough intro sequence mentioned in Section in Section 1.1.1, 1.1.1, which will automatically lead to a system configured config ured for this tutorial. The other possibility, recommended for newer users, is to sidestep such installation and configuration issues by using a cloud integrated development environment , or cloud IDE. The cloud IDE used in this tutorial runs inside an ordinary web browser, and hence works the same across different platforms, which is especially useful for operating systems (such as Windows) on which Rails development has historically been difficult. It also maintains the current state of your work, so you can take a break from the tutorial and come back to the system just as you left it.
1.2.1 1.2. 1
Develop Development ment envir environme onment nt
Considering various idiosyncratic customizations, there are probably as many development environments as there are Rails programmers. To avoid this complexity, the Ruby on Rails Tutorial standardizes on the excellent cloud development environment Cloud9 environment Cloud9.. In particular, I am pleased to be partnering with
1.2. UP AND AND RUNNI RUNNING NG
13
Cloud9 to offer a free development environment specifically tailored to the needs of this tutorial. The resulting Rails Rails Tutorial Tutorial Cloud9 workspace workspace comes pre-configured with most of the software needed for professional-grade Rails develop deve lopmen ment, t, inc includ luding ing Ruby Ruby,, Rub RubyGem yGems, s, Git. (Indeed (Indeed,, the only big piece piece of software we’ll install separately is Rails itself, and this is intentional (Sec(Section 1.2.2).) 1.2.2).) Although you are welcome to develop your application locally, setting up a Rails development environment can be challenging, so I recommend the cloud IDE for most readers readers.. Fo Forr tho those se who want to go the local rout route, e, try the step stepss at InstallRails.com at InstallRails.com,, and be prepared for a challenging exercise in technical sophistication (Box (Box 1.1). 1.1). The cloud IDE includes the three essential components needed to develop web applicatio applications: ns: a tex textt editor editor,, a file filesys system tem na navig vigato atorr, and a com comman mand-li d-line ne terminal (Figure 1.2 1.2). ). Among otherthat features, the cloud IDE text editor supports the “Find(Figure in Files” global search I consider essential to navigating any 8 large Ruby or Rails project. Finally, even if you decide not to use the cloud IDE exclusively in real life (and I certainly recommend learning other tools as well), it provides an excellent introduction to the general capabilities of text editors and other development tools. Here are the steps for getting started with the cloud development environment: Cloud9..9 In order to prevent abuse, Cloud9 1. Sign up for a free account at Cloud9 requires a valid credit card for signup, but the Rails Tutorial workspace is 100% free, and your card will not be charged. 2. Click o on n “Go to y your our Dash Dashboard” board”.. 3. Select “Cr “Create eate New W Workspa orkspace”. ce”. 4. As sh sho own in in Figure Figure 1.3 1.3,, create a workspace called “rails-tutorial” (not “rails_tutorial”), set it to “Private to the people I invite”, and select the icon for the Rails Tutorial (not the the icon for Ruby on Rails). 8 9
For example, to find the definition of a function called foo , you can do a global search for “def foo”. c9.io/signup
14
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Figure 1.2: The anatomy of the cloud IDE.
1.2. UP AND AND RUNNI RUNNING NG
15
Figure 1.3: Creatin Creating g a new workspace workspace at Cloud9 Cloud9.. 5. Click ““Create Create worksp workspace”. ace”. 6. Aft After er Clo Cloud9 ud9 has fini finishe shed d pro provisi visioni oning ng the worksp workspace ace,, it should should start start automatically. Because using two spaces for indentation is a near-universal convention in Ruby, I also recommend changing the editor to use two spaces instead of the defaul def aultt four. four. As sho shown wn in in Figure 1.4, 1.4, you can do this by clicking the gear icon in the upper right and then selecting “Code Editor (Ace)” to edit the “Soft Tabs” setting. (Note that this takes effe effect ct immediately; you don’t need to click a “Save” button.)
16
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Figure 1.4: Setting Cloud Cloud9 9 to use two spaces for indentation. indentation.
1.3. THE FIRST APPLICA APPLICATION
1.2. 1. 2.2 2
17
Inst Instal allin ling g Rail Railss
The development environment from Section from Section 1.2.1 1.2.1 includes includes all the software we need to get sta need started rted except except for Rails Rails itself. To ins install tall Rails, Rails, we’ll we’ll use the gem command provided by the RubyGems package manager, which involves typing into your comman command-line d-line term terminal. inal. (If dethe command shown in Listing in Listing 1.1 1.1 into veloping on your local system, this means using a regular terminal window; if using the cloud IDE, this means using the command-line area shown in Figin Figure 1.2.) 1.2.) Listing 1.1: Installing Rails with a specific version number. $ gem insta install ll rails rails -v 5.0. 5.0.1 1
Here the -v flag ensures that the specified version of Rails gets installed, which is important for getting results consistent consistent with this tutorial.
1.3 1. 3
The The first first appl applic icat atio ion n
tradition in in computer programming, our goal for the first apFollowing a long a long tradition plicati pli cation on is to write a “he “hello llo,, world” world” prog program ram.. In partic particula ularr, we will create create a simple application that displays the string “hello, world!” on a web page, both on our development environment (Section (Section 1.3.4 1.3.4)) and on the live web (Sec(Section 1.5). 1.5). Virtually all Rails applications start the same way, by running the rails command. This handy comm command and creates a skeleto skeleton n Rails applicatio application n in new command. a directory directory of your choic choice. e. To get star started ted,, use users rs not using the Cloud9 IDE recommended recomm ended in Section in Section 1.2.1 should 1.2.1 should make a workspace directory for your Rails projects if it doesn’t already exist (Listing (Listing 1.2) 1.2) and then change into the 1.2 uses uses the Unix commands cd and mkdir; see Box see Box 1.3 1.3 if if directory. (Listing (Listing 1.2 you are not already familiar with these command commands.) s.)
18
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Listing 1.2: Making a workspace directory for Rails projects (unnecessa (unnecessary ry in the cloud). $ cd $ mkdir workspac workspace e $ cd cd workspace/
# Chang Change e to th the e ho home me di direc recto tory. ry. # Make Make a wor works kspac pace e dire directo ctory ry. . # Cha Change nge into the workspac workspace e dire director ctory. y.
Box 1.3. A crash course on the Unix command line
For readers coming from Windows or (to a lesser but still significant extent) macOS, mac OS, the Unix comman command d line may be unfam unfamilia iliarr. Luckily Luckily,, if you are using using the recommended cloud environment, you automatically have access to a Unix (Linux) standard shell command-line interface interface known known as Bash. Bash. command line running a standard shell The basic basic ide ideaa of the com comman mand d line is sim simple: ple: by issuing issuing short commands commands,, user userss can can pe perf rfor orm m a larg largee numb number er of op oper erat atio ions ns,, su such ch as cr crea eatin ting g di dire rect ctor ories ies (mkdir), moving and copying files (mv and cp), and navigating the filesystem by changing directories (cd). Although the command line may seem primitive to users mainly familiar with graphical user interfaces (GUIs), appearances are deceivin cei ving: g: the comma command nd line is one of the most powerf powerful ul tools tools in the develo developer per’’s toolbox. Indeed, you will rarely see the desktop of an experienced developer without several open terminal windows running command-line shells. The general subject is deep, but for the purposes of this tutorial we will need only a few of the most common Unix command-line commands, as summarized in Tabl ablee 1.1 1.1.. For For a mo more re thor thorou ough gh in intr trod oduc ucti tion on to th thee Unix Unix comm comman and d li line ne,, see see th thee first first of the Learn the Learn Enough tutorials, Enough tutorials, Learn Enough Command Line to Be Dangerous.10
The next step on both local systems and the cloud IDE is to create the first application using the command in Listing in Listing 1.3 1.3.. Note that Listing that Listing 1.3 1.3 explicitly explicitly includes includ es the Rails version number as part of the command. command. This ensures that 1.1 is is used to create the first the same version of Rails we installed in Listing in Listing 1.1 application’s file structure. (If the command in Listing in Listing 1.3 returns 1.3 returns an error like
1.3. THE FIRST APPLICA APPLICATION
Description list contents make directory change directory
cd directory up cd one to home directory cd to path incl. home dir move file (rename) copy file remove file remove empty directory remove nonempty directory concatenate & display file contents
Command
Example
ls mkdir cd
$ ls -l $ mkdi mkdir r wor workspa kspace ce $ cd wo works rkspa pace/ ce/
$ $ $ mv $ cp $ $ rm rmdir $ rm -rf $ cat $
19
cd .. cd ~ or just $ cd cd ~/wo ~/works rkspace pace/ / mv foo foo bar bar cp foo foo bar bar rm foo rmdir rmdi r wor workspa kspace/ ce/ rm -r -rf f tm tmp/ p/ cat ~/.s ~/.ssh/i sh/id_r d_rsa.p sa.pub ub
Table 1.1: Some common Unix commands.
d no not t fi find nd ’r ’rai ailt ltie ies’ s’”, it means you don’t have the right version Could “Coul of Ra Rails ils insta installe lled, d, and and you you shou should ld do doub uble le-c -che heck ck tha thatt you you follo followe wed d th thee comm comman and d 1.1 exactly exactly as written.) in Listing in Listing 1.1 rail ils s ne new w (with a specific version number). Listing 1.3: Running ra $ cd cd ~/workspace $ rails rails _5.0 _5.0.1_ .1_ new hell hello_a o_app pp create creat cr eate e RE READ ADME. ME.md md creat cr eate e Ra Rake kefil file e creat cr eate e co conf nfig. ig.ru ru create crea te .gi .gitign tignore ore cr creat eate e crea cr eate te create create create create create create create . . . create crea te create create create
Ge Gemf mfile app ap p ile app/assets/conf app/ass ets/config/mani ig/manifest.js fest.js app/assets/java app/ass ets/javascripts scripts/applica /application.js tion.js app/assets/java app/ass ets/javascripts scripts/cable.j /cable.js s app/assets/styl app/ass ets/stylesheets esheets/applica /application.css tion.css app/channels/ap app/cha nnels/applicati plication_cable on_cable/channel /channel.rb .rb app/channels/ap app/cha nnels/applicati plication_cable on_cable/connect /connection.rb ion.rb app/controllers app/con trollers/applic /application_co ation_controller ntroller.rb .rb
tmp/cache/a tmp/cac he/asset ssets s vendor/assets/j vendor/ assets/javascri avascripts pts vendor/assets/j vendor/ assets/javascri avascripts/.kee pts/.keep p vendor/assets/s vendor/ assets/styleshe tylesheets ets
20
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
vendor/assets/s assets/styleshe tylesheets/.kee ets/.keep p create vendor/ remove config/ config/initiali initializers/co zers/cors.rb rs.rb run ru n bu bund ndle le inst instal all l Fetching Fetchin g gem metadata from https:// https://rubygems rubygems.org/.. .org/.......... ........ Fetching additio Fetching additional nal metadat metadata a from https:/ https://rubygem /rubygems.org/.. s.org/.. Resolving Resolvi ng depende dependencies... ncies... Install Ins talling ing rake 11.1 11.1.2 .2 Using concurr concurrent-ruby ent-ruby 1.0.2 . . . Your You r bun bundle dle is comp complet lete! e! Use Us e `b `bun undle dle sho show w [ge [gemn mname ame]` ]` to see whe where re a bu bundl ndled ed ge gem m is ins insta talle lled. d. run ru n bu bund ndle le exec sprin spring g bi binst nstub ub --all --all bin/rake: spri spring ng ins inserte erted d * bin/rake: bin/rails: spring inserte inserted d * bin/rails:
As seen at the end of Listing Listing 1.3 1.3,, running ra rail ils s ne new w automatically runs the bundle install command after the file creation is done. We’ll discuss what
1.3.1.. this means in more detail starting in Section in Section 1.3.1 command cr creates. eates. This Notice how many files and directories the rails command 1.5)) is one of the many advantages standard directory and file structure (Figure (Figure 1.5 of Rails: Rails: it immedi immediate ately ly gets you from zero to a fun functi ctiona onall (if minimal) minimal) application. Moreover, since the structure is common to all Rails apps, you can immediately get your bearings when looking at someone else’s code. A summary of the default Rails files appears in Table in Table 1.2 1.2.. We’ll learn about most of these files and directories throughout the rest of this book. In particular, starting in Section in Section 5.2.1 we’ll 5.2.1 we’ll discuss the app/assets directory, part of the asset pipel pipeline ine th that at ma make kess it easy easy to orga organi nize ze an and d depl deploy oy asse assets ts su such ch as casc cascad adin ing g style sheets and JavaScript files.
1.3. 1. 3.1 1
Bund Bundle lerr
After creating a new Rails application, the next step is to use Bundler to to install and include the gems needed by the app. As noted briefly in Section in Section 1.3 1.3,, le ins instal tall l) by the rails command, Bundler is run automatically (via bund bundle but in this section we’ll make some changes to the default application gems and run Bundler again. This involves opening the Gemfile with a text editor. (With the cloud IDE, this involves clicking the arrow in the file navigator to
1.3. THE FIRST APPLICA APPLICATION
Figure 1.5: The director directory y structure for a newl newly y created Rails app.
21
22
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Fi File le/D /Dir irec ecto tory ry app/
Pu Purp rpos osee Core application (app) code, including models, views, controllers, and helpers app/assets Applications assets such as cascading style sheets (CSS), JavaScript JavaScript files, and iimages mages bin/ Binary executable executable files config/ Application configuration db/ Database files doc/ Documentation for the application lib/ Library modules lib/assets Library assets such as cascading style sheets (CSS), JavaScript JavaScript files, and iimages mages log/ Application log files public/ Data accessible to the public (e.g., via web browsers), such as error pages bin/rails A program for generating code, opening console sessions, or starting a local server test/ Application tests tmp/ Temporary files vendor/ Third-party code such as plugins and gems vendor/assets Third-party ass assets ets such as cascadin cascading g style sheets (CSS), JavaScript JavaScript files, files, and images README.md A brief description of the application Rakefile Utility tasks availa available ble via the rake command Gemfile Gem requirements for this app Gemfile.lock A list of gems gems used to ensure ensure that all all copies of the app use tthe he same gem versions config.ru A configuration file for for Rack Rack middlewar middlewaree .gitignore Patterns for files that should be ignored by Git
Table 1.2: A summary of the default default Rails directory directory structure.
1.3. THE FIRST APPLICA APPLICATION
23
Figure 1.6: The default Gemfile open in a text editor. open the sample app directory and double-clicking the Gemfile ic icon on.) .) Although the exact version numbers and details may differ slightly, the results should look something like Figure like Figure 1.6 1.6 and and Listing Listing 1.4 1.4.. (The code in this file is 4 will will cover Ruby Ruby, but don’t worry at this point about the syntax; Chapter syntax; Chapter 4 in more depth.) If the files and directo directories ries don’t appea appearr as sho shown wn in Figure in Figure 1.6, 1.6, click cli ck on the file navi navigat gator’ or’ss gear gear icon icon and select select “Re “Refre fresh sh File Tree”. Tree”. (As a general rule, you should refresh the file tree any time files or directories don’t appear as expected.)11 Listing 1.4: The default Gemfile in the hello_app directory. source 'https://rubygems.org'
11
This is a typical example of technical sophistication (Box ( Box 1.1). 1.1).
24
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Bundle le edg edge e Rai Rails ls inst instead ead: : gem 'ra 'rails' ils', , git github: hub: 'rails/rai 'rails/rails' ls' # Bund gem 'rails', gem 'rails', '~> 5.0. 5.0.1' 1' # Use sqlite sqlite3 3 as the databa database se for Active Active Rec Record ord gem 'sqlite3' gem # Us Use e Pu Puma ma as th the e ap app p se serv rver er gem 'puma', gem 'puma', '~> 3. 3.0' 0' # Use SC SCSS SS fo for r st style ylesh sheet eets s gem 'sass-rails', gem 'sass-rails', '~> 5.0 5.0' ' # Use Ug Uglif lifie ier r as co comp mpres resso sor r fo for r Ja JavaS vaScr cript ipt ass asset ets s gem 'uglifier', gem 'uglifier', '>= 1.3. 1.3.0' 0' # Use Co Coffe ffeeS eScri cript pt fo for r .c .cof offee fee ass asset ets s an and d vi views ews gem 'coffee-rails', gem 'coffee-rails', '~> 4. 4.2' 2' # See http https:/ s://git /github. hub.com/ com/rail rails/ex s/execj ecjs#re s#readme adme for more supp supporte orted d runt runtimes imes # gem 'the 'therub rubyrac yracer', er', plat platform forms: s: :ru :ruby by # Use jq jquer uery y as the Ja JavaS vaScr cript ipt lib libra rary ry gem 'jquery-rails' gem # Turb Turbolin olinks ks make makes s nav navigat igating ing your web appl applicat ication ion fas faster. ter. # Read more: https:// https://github.c github.com/turb om/turbolinks/t olinks/turbolink urbolinks s gem 'turbolinks', gem 'turbolinks', '~> 5.x 5.x' ' # Buil Build d JSON APIs wit with h eas ease. e. Read more more: : http https:// s://gith github. ub.com/ com/rail rails/jb s/jbuild uilder er gem 'jbuilder', gem 'jbuilder', '~> 2. 2.0' 0' # Use Re Redis dis ada adapt pter er to ru run n Act Action ion Ca Cable ble in pr produ oduct ction ion # gem 'redis 'redis', ', '~ '~> > 3. 3.0' 0' # Use ActiveM ActiveModel odel has_sec has_secure_pass ure_password word # gem 'b 'bcry crypt pt', ', '~> 3. 3.1.7 1.7' ' # Use Capi Capistr strano ano for depl deployme oyment nt # gem 'capist 'capistrano rano-rai -rails', ls', grou group: p: :de :develo velopmen pment t group :development, :development, :test do # Ca Call ll 'b 'bye yebug bug' ' an anyw ywher here e in the co code de to st stop op ex execu ecuti tion on # an and d get a de debug bugge ger r co cons nsole ole gem 'byebug', gem 'byebug', platform : :mri end group :development do # Ac Acce cess ss an IR IRB B co cons nsole ole on ex excep cepti tion on pa pages ges or by us usin ing g # 2.0. 2.0.0' 0' end # Win Windo dows ws do does es no not t in inclu clude de zon zonein einfo fo fil files es, , so bu bund ndle le th the e tz tzinf infoo-dat data a gem gem 'tzinfo-data', gem 'tzinfo-data', platforms platforms: : [:mingw :mingw, , :mswin, :mswin, :x64_mingw, :x64_mingw, :jruby] :jruby]
1.3. THE FIRST APPLICA APPLICATION
25
Many of these lines are commented out with the hash symbol # (Section 4.2.1 4.2.1); ); they are there to show you some commonly needed gems and to give examples of the Bun Bundle dlerr syn syntax tax.. For no now w, we won’ won’tt nee need d an any y gems gems oth other er than the defaults. Unless you specify a version number to the gem command, command, Bundler will automatically automa tically insta install ll the latest requested versi version on of the gem. This is the case, for example, in the code gem 'sqlite3' gem
There are also two common ways to specify a gem version range, which allows us to ex exert ert some control control over over the vers version ion used by Rails. The first look lookss lik likee this: gem 'uglifier', gem 'uglifier', '>= 1.3. 1.3.0' 0'
This installs the latest version of the uglifier gem (which handles file compression for the asset pipeline) as long as it’s greater than or equal to verThe second second metho method d looks looks like sion 1.3.0—even if it’s, say, version 7.2. The this: gem 'coffee-rails' gem 'coffee-rails', , '~> 4.0 4.0.0' .0'
This installs the gem coffee-rails as long as it’s newer than version 4.0.0 and not newer newer than 4.1. In ot othe herr wor words ds,, the >= notation always installs the latest gem, whereas the ~> 4. 4.0. 0.0 0 notation only installs updated gems where the last digit differs (e.g., from 4.0.0 to 4.0.1), but the digits before that releases (e.g., from 4.0 to 4.1 ).12 Unfortunately, experience shows that even minor point point releases can break the application, application, so for the Ruby on Rails Tutorial we’ll err on the side of caution by including exact version numbers for all gems. 12
~> 4. 4.0 0 would install version 4.9 of a gem but not 5.0 . This is especially useful if the project in Similarly, ~> question uses semantic versioning (also called “semver”), which is a convention for numbering releases designed to minimize the chances of breaking software dependencies.
26
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
You are welcome to use the most up-to-date version of any gem, including using the ~> construction in the Gemfile (which I generally recommend for more advanced users), but be warned that this may cause the tutorial to act unpredictably. Converting the Gemfile in in Listing Listing 1.4 1.4 to to use exact gem versions results in 1.5.. (You (You can determine the exact versio version n number the code shown in Listing in Listing 1.5 gem m li list st at the command line, but for each gem by running ge Listin Listing g 1.5 1.5 saves saves you the trouble.) Note that we’ve also taken this opportunity to arrange for the sqlite3 gem to be included only in a development or 7.1.1), ), which prevents potential conflicts with the test environment (Section (Section 7.1.1 1.5). ). Important note: For all the Gemfiles database used by Heroku (Section (Section 1.5 in this book, you should use the version numbers listed at gemfiles-4thed.railstutorial.org instead ed.railstutorial.org instead of the ones listed below (although they should be identical if you are reading this online). Listing 1.5: A Gemfile with an explicit version for each Ruby gem. source 'https://rubygems.org' gem 'rails', gem 'rails', '5.0.1' gem 'puma', gem 'puma', '3.4.0' gem 'sass-rails', gem 'sass-rails', '5.0.6' gem 'uglifier', gem 'uglifier', '3.0.0' gem 'coffee-rails', gem 'coffee-rails', '4.2.1' gem 'jquery-rails', gem 'jquery-rails', '4.1.1' gem 'turbolinks', gem 'turbolinks', '5.0.1' gem 'jbuilder', gem 'jbuilder', '2.4.1' group :development, :development, :test do gem 'sqlite3', gem 'sqlite3', '1.3.12' gem 'byebug', gem 'byebug', '9.0.0', '9.0.0', platform : :mri end group :development do gem 'web-console', gem 'web-console', '3.1.1' gem 'listen', gem 'listen', '3.0.8' gem 'spring', gem 'spring', '1.7.2' gem 'spring-watcher-listen', gem 'spring-watcher-listen', '2.0.0' end # Win Windo dows ws do does es no not t in inclu clude de zon zonein einfo fo fil files es, , so bu bund ndle le th the e tz tzinf infoo-dat data a gem gem 'tzinfo-data', gem 'tzinfo-data', platforms platforms: : [:mingw :mingw, , :mswin, :mswin, :x64_mingw, :x64_mingw, :jruby] :jruby]
1.3. THE FIRST APPLICA APPLICATION
27
Once you’ve placed the contents of Listing Listing 1.5 1.5 into into the application’s Gem13 file, install the gems using bund le ins instal tall l: bundle $ cd cd hello_app/ $ bundle bundle install Fet Fetchin ching g sou source rce inde index x for http https:// s://ruby rubygem gems.or s.org/ g/ . . .
The bundl bundle e ins instal tall l command might take a few moments, but when it’s done our application will be ready to run. bund undle le ins instal tall l it’s possible that you’ll get By the way, when you run b a message saying you need to run bu bundl ndle e upd update ate firs first. t. In this this case case yo you u bundle dle upd update ate first. (Learn (Learning ing not to panic when things don’t should... run bun go exactly as planned is a key part of technical sophistication, and you’ll be amazed at how often the “error” message contains the exact instructions you need to fix the problem at hand.)
1.3.2 rai rails ls serv server er rail ils s ne new w i in n Section 1.3 1.3 and and bundl bundle e ins instal tall l in SecThanks to running ra tion tio n 1. 1.3. 3.1 1, we alr alrea eady dy ha have ve an ap appl plica icati tion on we ca can n ru run— n—b but how? how? Happily Happily,, Rails Rails comes with a command-line program, or script , that runs a local webserver to assist ass ist us in de deve velop loping ing our app applica licatio tion. n. The exac exactt com comman mand d depend dependss on the rails s ser server ver environme enviro nment nt you’ you’re re using: on a loc local al system system,, you just run rail (Listing 1.6), 1.6), whereas on Cloud9 you need to supply an additional IP bind to tell the Rails server the address it can use to ing address and port number to make the application visible to the outside world (Listing (Listing 1.7). 1.7).14 (Cloud9 uses the special environm environment ent variables $IP and $PORT to assign the IP address and port number dynamically. If you want to see the values of these variables, type echo ho $I $IP P or ech echo o $P $POR ORT T at the command line.) ec 13
As noted in Table in Table 3.1, 3.1, you can even leave off install, as the bundle command by itself is an alias for bundle install. 14 Normally, websites run on port 80, but this usually requires special privileges, so it’s conventional to use a less restricted higher-numbered port for the development server server..
28
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
If your system complains about the lack of a JavaScript runtime, visit the GitHub for for a list of possib possibilities. ilities. I particularly particularly recommend inexecjs page at GitHub Node.js.. stalling Node.js stalling Listing 1.6: Running the Rails server server on a local machine. machine. $ cd cd ~/workspace/hello_app/ $ rails serv server er => Boo Booti ting ng Pu Puma ma => Rail Rails s app applica lication tion star starting ting on htt http:// p://loca localhos lhost:30 t:3000 00 => Run `ra `rail ils s se serve rver r -h` fo for r mo more re st start artup up op opti tions ons => Ctr Ctrll-C C to shu shutdo tdown wn ser serve ver r
Listing 1.7: Running the Rails server server on the cloud IDE. cd ~/workspace/hello_app/ $ cd $ rails rails ser serve ver r -b $IP -p $PORT => Boo Booti ting ng Pu Puma ma => Rail Rails s app applica lication tion star starting ting on htt http:// p://loca localhos lhost:80 t:8080 80 => Run `ra `rail ils s se serve rver r -h` fo for r mo more re st start artup up op opti tions ons => Ctr Ctrll-C C to shu shutdo tdown wn ser serve ver r
Whichever option you choose, I recommend running the rai rails ls ser server ver command in a second terminal tab so that you can still issue commands in the first tab, as shown in Figure in Figure 1.7 1.7 and and Figure Figure 1.8 1.8.. (If you already started a server in your first tab, press Ctrl-C to shut it down.) 15 On a local server, paste the http://localhost:3000 into into the address bar of your browser; on the cloud URL http://localhost:3000 URL 1.9). ). IDE, go to Share and click on the Application address to open it (Figure ( Figure 1.9 In either case, the result should look something like Figure like Figure 1.10 1.10.. Exercises
railstutorial.org/solutions with with Solutions to exercises are available for free at railstutorial.org/solutions any Rails Tutorial Tutorial purchase. To see other people’ people’ss answers and to record your Learn Enough Society Society at at learnenough.com/society learnenough.com/society.. own,, join the own the Learn 15
Here “C” refers to the character on the keyboard, not the capital letter, so there’s no need to hold down the Shift key to get a capital “C”.
1.3. THE FIRST APPLICA APPLICATION
Figure 1.7: Openin Opening g a new termina terminall tab.
29
30
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Figure 1.8: Runni Running ng the Rails serve serverr in a separate tab.
1.3. THE FIRST APPLICA APPLICATION
Figure 1.9: Sharin Sharing g the local server runni running ng on the cloud workspac workspace. e.
31
32
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Figure 1.10: The default Rails page served by rai rails ls ser server ver.
1.3. THE FIRST APPLICA APPLICATION
33
1. Accord According ing to the defau default lt Rails page page,, what is the version of Rub Ruby y on your system?? Confir system Confirm m by running running ru ruby by -v at the command line. 2. Wh What at is the the versi ersion on of Ra Rail ils? s? C Con onfir firm m th that at it matc matche hess th thee versi ersion on in inst stal alle led d in Listing in Listing 1.1. 1.1.
1.3.3 1.3. 3
Model-V Model-View-C iew-Contr ontroller oller (MVC)
Even at this early stage, it’s helpful to get a high-level overview of how Rails applications work, as illustrated in Figure in Figure 1.11. 1.11. You might have have noticed that the standard Rails application structure (Figure ( Figure 1.5) 1.5) has an application directory called app/ containing three subdir subdirectorie ectories: s: models, views, and conthe model-view-controller (MVC) (MVC) trollers. This is a hint that Rails follows the model-view-controller architectural pattern, which enforces a separation between the data in the application (such as user information) and the code used to display it, which is a common way of structu structuring ring a graphi graphical cal user interf interface ace (GUI). When interacting with a Rails application, a browser sends a request , which is received by a webserver and passed on to a Rails controller , which is in char ch arge ge of wh what at to do next next.. In some some case cases, s, the cont contro roll ller er will will imme immedi diat atel ely y rend render er a view, which is a template that gets converted to HTML and sent back to the browse bro wserr. Mor Moree com common monly ly for dynam dynamic ic sites, sites, the contr controlle ollerr inte interac racts ts with a model , which a Ruby that represents an element ofAfter the site (such as a user) and is inischarge ofobject communicating with the database. invoking the
model, the controller then renders the view and returns the complete web page to the browser as HTML. If this discussion seems a bit abstract right now, don’t worry; we’ll cover these ideas in more detail later in this book. In particular, Section particular, Section 1.3.4 shows 1.3.4 shows a 2.2.2 includes includes a more detailed first tentative application of MVC, while Section while Section 2.2.2 discussion of MVC in the context of the toy app. Finally, the full sample app will use all aspects of MVC: we’ll cover controllers and views starting in Secin Section 3.2, 3.2, models starting in Section in Section 6.1 6.1,, and we’ll see all three working together in Section in Section 7.1.2. 7.1.2.
34
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
View
Controller
Model
Database
Figure 1.11: A schematic representation of the model-view-controller (MVC) architecture.
1.3. THE FIRST APPLICA APPLICATION
1.3. 1. 3.4 4
35
Hello Hello,, wo worl rld! d!
change As a first application of the MVC framework, we’ll make a wafer-thin a wafer-thin change to the first app by adding a controller action to render the string “hello, world!” 1.10.. (W (We’l e’lll learn mor moree about to replace the default Rails page from Figure 1.10 2.2.2.) .) controller contro ller actions startin starting g in Section in Section 2.2.2 As implied by their name, controller actions are defined inside controllers. We’ll call our action hello and place it in the Application controller. Indeed, at this point the Application controller is the only controller we have, which you can verif verify y by runnin running g $ ls app/con app/controllers trollers/ /* _controller.rb
to view the cur curren rentt control controller lers. s. (W (We’l e’lll sta start rt cre creati ating ng our own controlle controllers rs in 2.) Listing Chapter 2.) Listing 1.8 shows 1.8 shows the resulting definition of hello hello, which uses the (Don’t worry about render function to return the HTML text “hello, world!”. (Don’t 4.) .) the Ruby syntax right now; it will be covered in more depth in Chapter in Chapter 4 Listing 1.8: Adding a hello action to the Application controller. app/controllers/application_controller.rb class ApplicationController < ActionController:: ActionController::Base Base protect_from_forgery with: with: :exception def hello render html html: : "hell "hello, o, world!" end end
Having Havi ng de defin fined ed an acti action on th that at retu return rnss th thee de desi sire red d st stri ring ng,, we need need to te tell ll Rail Railss to use that action instead of the default page in Figure in Figure 1.10. 1.10. To do this, we’ll 1.11 and and deedit the Rails router , which sits in front of the controller in Figure in Figure 1.11 termines where to send requests that come in from the browser. (I’ve omitted the router from Figure from Figure 1.11 1.11 for for simplicity, but we’ll discuss it in more detail starting in Section in Section 2.2.2 2.2.2.) .) In partic particula ularr, we want to change change the defa default ult page, page,
36
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
the root route, which determines the page that is served on the root URL. Because it’s the URL for an address like http://www.example.com/ (where nothing comes after the final forward slash), the root URL is often referred to as / (“slash”) for short. As seen in Listing in Listing 1.9 1.9,, the Rails routes file (config/routes.rb) includes a comment directing us to the Rails the Rails Guide on Routing, Routing, which includes instructions on how to define the root route. The syntax looks like this: root 'controller_name#action_name'
In the present case, the controller name is application and the action name is hello, which results in the code shown in Listing in Listing 1.10. 1.10. Listing 1.9: The default default routing file (formatted to fit). config/routes.rb Rails. .application application. .routes routes. .draw do Rails # Fo For r det detai ails ls on th the e DS DSL L ava availa ilabl ble e wi with thin in thi this s fil file, e, # see http://g http://guides.ru uides.rubyonrai byonrails.org/r ls.org/routing.h outing.html tml end
Listing 1.10: Setting the root route. config/routes.rb Rails Rails. .application application. .routes routes. .draw do root 'application#hello' end
With the code from Listing 1.8 and Listing 1.10, 1.10, the root route returns 16 Figure 1.12 1.12). ). Hello, world! “hello,, world! “hello world!”” as requir required ed ((Figure 16
The base URL for the Rails Tutorial Cloud9 shared URLs has changed from rails-tutorial-c9-mhartl.c9.io to rails-tutorial-mhartl.c9users.io, but in many cases the screenshots are identical, so the browser address bar will show old-style URLs in some figures (such as Figure 1.12). 1.12). This is the sort of minor discrepancy you can resolve using your technical sophistication (Box (Box 1.1 1.1). ).
1.3. THE FIRST APPLICA APPLICATION
Figure 1.12: Viewing “hello, world!” in the browser.
37
38
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Exercises
railstutorial.org/solutions with with Solutions to exercises are available for free at railstutorial.org/solutions any Rails Tutorial Tutorial purchase. To see other people’ people’ss answers and to record your own, join the own, the Learn Learn Enough Society Society at at learnenough.com/society learnenough.com/society.. 1. Ch Chan ange ge the co cont nten entt of the hello action in Listing 1.8 to read “hola, mundo!” instead of “hello, world!”. 2. Sho Show w that Rail Railss suppor supports ts nonnon-ASCII ASCII characters characters by including an inverted exclamation point, as in “¡Hola, mundo!” (Figure ( Figure 1.13). 1.13).17 To get a ¡ character on a Mac, you can use Option-1; otherwise, you can always copy-and-paste the character into your editor. in Listing 1.8 1.8,, add a sec3. By follo following wing the eexample xample o off the hello action in Listing ond action called goodbye that renders the text “goodbye, world!”. world!”. Edit the routes file from Listing from Listing 1.10 1.10 so so that the root route goes to goodbye instead of to hello ( (Figure Figure 1.14). 1.14).
1.4
Versio ersion n co contr ntrol ol with with Git
Now that we have a working “hello, world” application, we’ll take a moment for for a ste step p that that,, wh while ile tec techn hnica ically lly op optio tiona nal, l, w wou ould ld be vi view ewed ed by expe experi rien ence ced d so softftware developer developerss as practi practically cally essential essential:: placing our application application source code under version control. Version ersion contr control ol system systemss allo allow w us to track track change changess to our project’s code, collaborate more easily, and roll back any inadvertent errors (such as accidentally deleting files). Knowing how to use a version control system is a required skill for every professional-grade software developer. There are many options for version control, but the Rails community has largely standardized on Git on Git,, a distributed version control system originally developed by Linus Torvalds to host the Linux kernel. Git is a large subject, and 17
Your editor may display a message like “invalid multibyte character”, but this is not a cause for concern. You can Google can message if you want to learn how to make it go away. Google the error message if
1.4. VERSION VERSION CONTR CONTROL OL WITH G GIT IT
Figure 1.13: Chang Changing ing the root route to return “¡Hola, mundo!”.
39
40
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Figure 1.14: Chang Changing ing the root route to return “goodbye, world! world!”. ”.
1.4. VERSION VERSION CONTR CONTROL OL WITH G GIT IT
41
we’ll only be scratching the surface in this book; for a more thorough introduction, see Learn Enough Git to Be Dangerous .18 Putting your source code under version control with Git is strongly recommended, not only because it’s nearly a universal practice in the Rails world, but also because it will allow you to back up and share your code more eas1.4.3)) and deploy your application right here in the first chapter ily (Section (Section 1.4.3 (Section 1.5). 1.5).
1.4.1 1.4 .1
Instal Installat lation ion and setup setup
1.2.1 includes includes Git by default, so no The cloud IDE recommended in Section 1.2.1 installation is necessary in this case. Otherwise, Learn Enough Git to Be Dan includes instructions instructions for for installing Git on your system. gerous includes First-time system setup
Before using Git, you should perform a couple of one-time setup steps. These are system setups, meaning you only have to do them once per computer: config ig --gl --global obal user user.nam .name e "Your "Your Nam Name" e" $ git conf $ git config --global user.email your.em your.email@exam
[email protected] ple.com
Note that in theany name and emailyou address use in your Git configuration configuration will be available repositories makeyou public. First-time repository setup
Now we come to some steps that are necessary each time you create a new repository (sometimes called a repo for short). short). The first step is to navig navigate ate to the root directory of the first app and initialize a new repository:
18
learnenough.com/git
42
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
init $ git init Initial Initialized ized empty Git reposito repository ry in /home/ub /home/ubuntu/wor untu/workspace/ kspace/hello_ap hello_app/.git/ p/.git/
The next step is to add all the project files to the repository using gi git t ad add d -A : $ git git ad add d -A
This command adds all the files in the current directory apart from those that match the patterns in a special file called .gitignore. The rail rails s ne new w command automatically generates a .gitignore file appropriate to a Rails project, but you can add additional patterns as well.19 The added files are initially placed in a staging area, which contains pending changes to our project. We can see which files are in the staging area using the status command: status us $ git stat On bran branch ch mas master ter Initial commit Changes to be com Changes committ mitted: ed: (use (us e "gi "git t rm ---cac cache hed d ..." .." to un unsta stage ge) ) new ne w fi file le: :
.git .g itig igno nore re
new new new ne w new ne w new ne w . . .
Gemfil Gemf ile e Gemf Ge mfil ile. e.lo lock ck READ RE ADME ME.m .md d Rake Ra kefi file le
file: file : file fi le: : file fi le: : file fi le: :
To tell Git we want to keep the changes, we use the commit command:
19
Although we’ll never need to edit it in the main tutorial, an example of adding a rule to the .gitignore file appears in Section in Section 3.6.2, 3.6.2, which is part of the optional advanced testing setup in Section in Section 3.6 3.6..
1.4. VERSION VERSION CONTR CONTROL OL WITH G GIT IT
43
commit t -m -m "Initiali "Initialize ze reposit repository" ory" $ git commi [master (root-commit) (root-commit) df0a62f] Initialize repository . . .
The -m flag lets us add a message for the commit; if we omit -m , Git will open the system’s default editor and have us enter the message there. (All the flag.) examples in this book will use the -m flag.) It is important to note that Git commits are local, recorded only on the machine on which the commits occur. We’ll see how to push the changes up to git t pu push sh) in Section in Section 1.4.4 1.4.4.. a remote repositor repository y (using gi By the way, we can see a list of the commit messages using the log command: af72946fbebc159 bebc15903b2770f 03b2770f92fae908 92fae9081243dd1 1243dd1a1 a1 commit af72946f Author: Michael Hartl Date Da te: : Thu Th u May 12 19:2 19:25: 5:07 07 2016 2016 +000 +0000 0 Initialize Initial ize reposit repository ory
Depending on the length of the repository’s log history, you may have to type to quit. (As explained in Learn Enough Git to Be Dangerous, gi git t lo log g uses q to the less interface interface covered covered in in Learn Enough Command Line to Be Dangerous.)
1.4.2 1.4 .2
What What good good does does Git do you? you?
If you’ve never used version control before, it may not be entirely clear at thiss poi thi point nt what good it doe doess you you,, so let me gi give ve just one example. example. Suppos Supposee you’ve made some accidental changes, such as (D’oh!) deleting the critical app/controllers/ directory. app/controllers trollers/ / $ ls app/con applica application_con tion_controller troller.rb .rb concerns concerns/ / $ rm -rf app app/con /control trollers lers/ / $ ls app/con app/controllers trollers/ / app/con /control trollers lers/: /: No such file or dir directo ectory ry ls: app
44
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Here we’re using the Unix ls command to list the contents of the app/con command to remove it (Table (Table 1.1 1.1). ). As noted As noted trollers/ directory and the rm command in Learn Enough Command Line to Be Dangerous, the -rf flag means “recursive force”, which recursively removes all files, directories, subdirectories, and so on, withou withoutt asking for explicit confirmati confirmation on of each deletion deletion.. Let’ss check the status to see what changed: Let’ $ git stat status us branch ch mas master ter On bran Changed Cha nged but not upda updated: ted: (use (us e "gi "git t add add/r /rm m ..." .." to up updat date e wha what t wil will l be co commi mmitte tted) d) (use "git chec checkout kout -- ..." .." to dis discard card changes changes in work working ing dir directo ectory) ry) deleted dele ted: :
app/cont app/ controll rollers/ ers/appl applica ication tion_con _control troller. ler.rb rb
no cha chang nges es ad added ded to co commi mmit t (us (use e "g "git it ad add" d" an and/o d/or r "gi "git t com commi mit t -a -a") ")
We see here that a file has been deleted, but the changes are only on the “working tree”; they haven’t been committed yet. This means we can still undo the changes using the checkout command with the -f flag to force overwriting the current changes: checkou out t -f $ git check $ git stat status us # On bra branch nch mast master er not nothing hing to comm commit it (wo (workin rking g dire director ctory y cle clean) an) $ ls app/con app/controllers trollers/ / applica application_con tion_controller troller.rb .rb concerns concerns/ /
The missing files and directories are back. That’s That’s a relief!
1.4. 1. 4.3 3
Bitb Bitbuc ucke kett
Now that we’ve put our project under version control with Git, it’s time to push our code up to Bitbucket to Bitbucket,, a site optimized for hosting and sharing Git reposDangerous ous uses uses GitHub GitHub,, but see Box see Box 1.4 1.4 to itories ito ries.. ( Learn Enough Git to Be Danger learn the reasons why this tutorial uses Bitbucke Bitbuckett instead.) Putting a copy of your Git repository at Bitbucket serves two purposes: it’s a full backup of your
1.4. VERSION VERSION CONTR CONTROL OL WITH G GIT IT
45
code (including the full history of commits), and it makes any future collaboration much easier.
Box 1.4. GitHub and Bitbucket
By far the two most popular sites for hosting Git repositories are GitHub and Bitb Bi tbuc ucke ket. t. Th Thee tw two o serv servic ices es share share many many simil similari aritie ties: s: bot both h sites sites al allo low w fo forr Git Git repo repossitory hosting and collaboration, as well as offering convenient ways to browse and search sea rch reposi repositor tories. ies. The import important ant dif differ ferenc ences es (fro (from m the per perspe specti ctive ve of this tutorial) are that GitHub offers unlimited free repositories (with collaboration) for open-source repositories while charging for private repos, whereas Bitbucket allows unlimited free private repos while charging for more than a certain number of collaborators. Which service you use for a particular repo thus depends on your specific needs. Learn Enough Git to Be Danger Dangerous ous (and some previous editions of this tutorial) use GitHub because of its emphasis on supporting open-source code, but growing concerns about security have led me to recommend that all web application repositories repositories be priv private ate by default. The issue is that such repositorie repositoriess might contain potentially sensitive information such as cryptographic keys or passwords, which whi ch could be used to compro compromise mise the secu security rity of a site running running the code. It is possible, of course, to arrange for this information to be handled securely (by having Git ignore it, for example), but this is error-prone and requires significant expertise. As it happens, the sample application created in this tutorial is safe for exposure on the web, but it is dangerous to rely on this fact in general. Thus, to be as secure as possible, we will err on the side of caution and use private repositories by default. Since GitHub charges for private repositories while Bitbucket offers an unlimited number for free, for our present purposes Bitbucket is a better fit than GitHub. (By the way, recently a third major Git hosting company has emerged, called GitLab. Origina inally lly designed designed princ principa ipally lly as an open-s open-sour ource ce Git tool tool you hosted hosted GitLab. Orig yourself, yourse lf, GitLab now offers a hosted version as well, and in fact allows allows for unlim-
46
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
ited public and private private repositories. This makes GitLab an excellent alternative to GitHub or Bitbucket for future projects.)
Getting started with Bitbucket is straightforward, though it may take a little 1.1)) to get everything to work just right: technical sophistication (Box (Box 1.1 1. Sign up for a Bitbucket account if account if you don’t already have one. 2. Co Copy py yo your ur public key to your your clipbo clipboard ard.. As indic indicated ated in in Listing Listing 1.11 1.11,, users of the cloud IDE can view their public key using the cat command, which can then be selected and copied. If you’re using your own system 1.11,account , follow.the and see no output when running the command in Listing in Listing 1.11 instructions on how on how to install a public key on your Bitbucket account. 3. Add your publi publicc ke key y to Bitbu Bitbucke ckett by clicking clicking on the avata avatarr imag imagee in the upper right and selecting “Bitbucket settings” and then “SSH keys” (Figure 1.15). 1.15). Listing 1.11: Printing the public key using cat . ~/.ssh/id_rsa.p id_rsa.pub ub $ cat ~/.ssh/
Once yo Once you’ u’ve ve ad adde ded d yo your ur pu publ blic ic ke key y, click click on “Cre “Creat ate” e” to crea create te a ne new w re repo possitory,, as shown in Figure itory in Figure 1.16 1.16.. When filling in the information for the project, take care to leave the box next to “This is a private repository.” checked. After clicking clickin g “Crea “Create te reposi repository”, tory”, follow the instructions instructions under “Command line > I 1.12.. (If have an existing project”, which should look something like Listing 1.12 it doesn’t look like Listing like Listing 1.12, 1.12, it might be because the public key didn’t get added correctly, in which case I suggest trying that step again.) When pushing up the repository, answer yes if you see the question “Are you sure you want to continue connecting (yes/no)?”
1.4. VERSION VERSION CONTR CONTROL OL WITH G GIT IT
Figure 1.15: Adding the SSH public key.
47
48
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Figure 1.16: Creatin Creating g the first app repos repository itory at Bitbucket. Bitbucket.
1.4. VERSION VERSION CONTR CONTROL OL WITH G GIT IT
49
Listing 1.12: Adding Bitbucket and pushing up the repository.
[email protected] bucket.org:/hello_app ello_app.git .git $ git remote add origin git@bit $ git push push -u origi origin n --a --all ll
The commands in Listing in Listing 1.12 first 1.12 first tell Git that you want to add Bitbucket as the origin for your repository, and then push your repository up to the remote origin. (Don’t worry about what the -u flag does; if you’re curious, do a web search for “git set upstream”.) upstream”.) Of course, you should repl replace ace with your actual username. For exampl example, e, the comman command d I ran was $ git remote add origin git@bit
[email protected] bucket.org:rails rg:railstutoria tutorial/hello_ l/hello_app.git app.git
The result is a page at Bitbucket for the hello_app repository, with file browsing, full commit history, and lots of other goodies (Figure (Figure 1.17 1.17). ).20
1.4.4 1.4 .4
Branc Branch, h, edit, edit, commit commit,, merge merge
If you’ve followed the steps in Section in Section 1.4.3 1.4.3,, you might notice that Bitbucket 1.17.. auto au toma matic tical ally ly ren rende dere red d the repo reposi sito tory’ ry’ss RE READM ADME E fil file, e, as sh sho own in Figure Figure 1.17 This file, called README.md , was generated automatically by the command in Listing g 1.3 1.3.. As indicated by the filename extension .md , it is written in MarkListin down,21 a human-readable markup language designed to be easy to convert to HTML—which is exactly what Bitbucket has done. This automatic rendering of the README is convenient, but of course it would be better if we tailored the contents of the file to the project at hand. In this section, we’ll customize the README by adding some Rails Tutorial– specifi spe cificc con conten tent. t. In the proces process, s, we’ we’ll ll see a firs firstt exa exampl mplee of the branch branch,, edi edit, t, 22 commit, merge workflow workflow that I recommend recommend using with Git. 20
Because of how my public keys are set up on Cloud9, I created the repository as railstutorial and then added my main account, mhartl, as a collaborator. As a result, I can make commits under either account name. 21 See Learn Enough Text Editor to Be Danger Dangerous ous and Learn Enough Git to Be Dangerous for more information about Markdown. 22 For a convenient way to visualize Git repositories, take a look at Atlassian’s SourceTree app. app.
50
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Figure 1.17: A Bitbucket repository page.
1.4. VERSION VERSION CONTR CONTROL OL WITH G GIT IT
Figure 1.18: Bitbucket’s rendering of the default Rails README.
51
52
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Branch
Git is incredibly good at making branches, which are effectively copies of a repository where we can make (possi repository (possibly bly experimenta experimental) l) changes changes without modifying the parent files. In most cases, the parent repository is the master branch, branch, and we can create a new topic branch by using checkout with the -b flag: $ git chec checkou kout t -b mod modifyify-READ README ME Swi Switche tched d to a new bra branch nch 'mod 'modifyify-REA README' DME' $ git bran branch ch master * modify-README
gi git t br bran anch ch
Herethe theasterisk second *command, , jus just li lists sts all the local l br bran anch ches es,, and identifies identifies which branch we’ we’re ret currently on.loca Note that git checko che ckout ut -b mod modify ify-RE -READM ADME E both creates a new branch and switches to it, as indicated by the asterisk in front of the modify-README branch. The full value of branching only becomes clear when working on a project with multiple developers,23 but branches are helpful even for a single-developer tutoriall such as this one. In particular, tutoria particular, becaus becausee the master branch branch is insulated insulated from any changes we make to the topic branch, even if we really mess things up we can always abandon the changes by checking out the master branch and deleting the topic branch. We’ll see how to do this at the end of the section. By the way, for a change as small as this one I wouldn’t normally bother with a new branch (opting instead to work directly on the master branch), but in the presen presentt context context it’s a prime opportun opportunity ity to start practicing practicing good habits. Edit
After creating the topic branch, we’ll edit the README to add custom content, 1.13.. as shown in Listing in Listing 1.13
23
See, for example, the section on Collaborating on Collaborating in in Learn Enough Git to Be Dangerous .
1.4. VERSION VERSION CONTR CONTROL OL WITH G GIT IT
53
Listing 1.13: The new README file. README.md # Ruby Ruby on Rails Rails Tuto Tutori rial al ## "hel "hello, lo, worl world!" d!" This This is the fir first st appl applica icati tion on for the the [*Rub Ruby y on Rails Rails Tut Tutor orial ial*](http://www.railstutorial.org/) by [Michael Hartl](http://www.michael Hartl](http://www.michaelhartl.com/). hartl.com/). Hello, world!
Commit
With the changes made, we can take a look at the status of our branch: $ git stat status us On bran branch ch mod modifyify-READ README ME Changes Cha nges not stag staged ed for com commit: mit: (use (us e "gi "git t add ..." ." to upd updat ate e wh what at wi will ll be com commi mitte tted) d) (use "git chec checkout kout -- ..." .." to dis discard card changes changes in work working ing dir directo ectory) ry) modified:
README.md
no cha chang nges es ad added ded to co commi mmit t (us (use e "g "git it ad add" d" an and/o d/or r "gi "git t com commi mit t -a -a") ")
At this point, we could use git add -A as as in Section in Section 1.4.1, 1.4.1, but gi git t co comm mmit it provides the -a flag as a shortcut for the (very common) case of committing all modifications to existing files: $ git git co comm mmit it -a -m -m "Improv "Improve e the READ README ME file file" " [modify [mo dify-REA -README DME 9dc4 9dc4f64 f64] ] Imp Improve rove the READ README ME fil file e 1 file changed, changed, 5 ins inserti ertions( ons(+), +), 22 del deletio etions(ns(-) )
Be careful about using the -a flag improperly; if you have added any new files to the project since the last commit, you still have to tell Git about them using first. git add -A first. Note that we write the commit message in the present tense (and, technically speaking, the imperative mood). mood). Git Git models models commi commits ts as a serie seriess of
54
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
patches, and in this context it makes sense to describe what each commit does, rather than what it did. Moreover Moreover,, this usage matches matches up with the commit mesGit from from sages sag es gener generated ated by Git comma commands nds thems themselv elves. es. See See Committing to Git Learn Enough Git to Be Danger Dangerous ous for more information. Merge
Now that we’ve finished making our changes, we’re ready to merge the results back into our master branch: checkou kout t mast master er $ git chec Swi Switche tched d to bran branch ch 'ma 'master ster' ' $ git merg merge e modi modify-R fy-READM EADME E Updatin Updating g af72946 af72946..9dc4f6 ..9dc4f64 4 Fast-forward README.md README. md | 27 +++++--+++++-------------------------------------1 file changed, changed, 5 ins inserti ertions( ons(+), +), 22 del deletio etions(ns(-) )
Note that the Git output frequently includes things like 34f06b7, which are related to Git’s internal representation representation of repositories repositories.. Your exact results will differ in these details, but otherwise should essentially match the output shown above. After you’ve merged in the changes, you can tidy up your branches by deleting deletin g the topic branch using gi if you’re done with it: git t br bran anch ch -d if $ git bran branch ch -d modi modify-R fy-READ EADME ME Del Deleted eted bran branch ch modi modifyfy-READ README ME (was 9dc4 9dc4f64 f64). ).
This step is optional, and in fact it’s quite common to leave the topic branch intact. This way you can switch back and forth between the topic and master branches, merging in changes every time you reach a natural stopping point. As me ment ntion ioned ed ab abov ove, e, it’s it’s al also so po poss ssibl iblee to aban abando don n yo your ur to topic pic br bran anch ch changes, in this case with gi git t br bran anch ch -D:
1.5. DEPLOYING DEPLOYING
55
illustrat ratio ion n on only; ly; don't don't do th this is un unles less s yo you u mes mess s up a br bran anch ch # For illust $ git chec checkou kout t -b top topic-b ic-branc ranch h $ $ git git git $ git $ git $ git
ad add d -A co comm mmit it -a -m -m "Make "Make majo major r mist mistake" ake" chec checkou kout t mast master er bran branch ch -D topi topic-br c-branc anch h
flag, the -D flag will delete the branch even though we haven’t Unlike the -d flag, merged in the changes. Push
Now that we’ve updated the README, we can push the changes up to Bitbucket to see thewe result. Since wegin hav haveemas already one push 1.4.3 Section 1.4.3), origin master ter,done and simply run((Section gi git t pu push sh: ), on most systems can omit ori $ git push push
As with the default README, Bitbucket nicely converts the Markdown in our updated README to HTML (Figure (Figure 1.19). 1.19).
1.5
Dep eplo loy ying
Even though this is only the first chapter, we’re already going to deploy our (nearly (nearl y empty) Rails applic application ation to producti production. on. This step is optional optional,, but deploying early and often allows us to catch any deployment problems early in our development cycle. The alternative—deploying only after laborious effort sealed away in a development environment—often leads to terrible integration headaches when launch time comes.24 Deploying Rails applications used to be a pain, but the Rails deployment ecosystem has matured rapidly in the past few years, and now there are several 24
Though it shouldn’t matter for the example applications in the Rails Tutorial, if you’re worried about accidentally making your app public too soon there are several options; see Section 1.5.4 1.5.4 for for one.
56
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Figure 1.19: The improved README file at Bitbucket.
1.5. DEPLOYING DEPLOYING
57
great option great options. s. These These includ includee sha shared red hosts or virtual virtual private private servers servers run runnin ning g Phusion Passenger Passenger (a (a module for the Apache and Nginx 25 webservers), fulland Rails Rails Machine, Machine, and service deployment companies such as Engine as Engine Yard Yard and cloud deployment services such as Engine as Engine Yard Cloud Cloud and and Heroku Heroku.. My favorite Rails deployment option is Heroku, which is a hosted platform built specifically specifically for deploying Rails and other web applic applications. ations. Heroku makes deploying Rails applications ridiculously easy—as long as your source codee is under vers cod version ion contr control ol with Git. (This (This is yet ano anothe therr rea reason son to follow follow 1.4 if if you haven’t already.) In addition, for many the Git setup steps in Section in Section 1.4 purposes, including for this tutorial, Heroku’s free tier is more than sufficient. The rest of this section is dedicated to deploying our first application to Heroku Her oku.. Som Somee of the ideas ideas are fai fairly rly adv advanc anced, ed, so don don’t ’t worry about about under under-standing all the details; what’s important is that by the end of the process we’ll have deployed our application to the live web.
1.5. 1. 5.1 1
Hero Heroku ku setu setup p
Heroku uses the the PostgreSQL database (pronounced “post-gres-cue-ell”, and often called “Postgres” for short), which means that we need to add the pg gem in the produc production tion envi environmen ronmentt to allow Rails to talk to Postgres:26 group :production do gem 'pg', gem 'pg', '0.18.4' end
Also be sure to incorporate the changes made in Listing 1.5 preventing the sqlite3 gem from being included in a production environment, since SQLite isn’t supported at Heroku:
25
Pronounced “Engine X”. Generally speaking, it’s a good idea for the development and production environments to match as closely as possible, which includes using the same database, but for the purposes of this tutorial we’ll always use SQLite locally and PostgreSQL in production. See Section See Section 3.1 for 3.1 for more information. 26
58
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
group :development, :development, :test do gem 'sqlite3', gem 'sqlite3', '1.3.12' gem 'byebug', gem 'byebug', '9.0.0', '9.0.0', platform : :mri end
The resulting Gemfile appears as in Listing in Listing 1.14. 1.14. Listing 1.14: A Gemfile with added and rearranged gems. source 'https://rubygems.org' gem 'rails', gem 'rails', '5.0.1' gem 'puma', gem 'puma', '3.4.0' gem 'sass-rails', gem 'sass-rails', '5.0.6' gem 'uglifier', gem 'uglifier', '3.0.0' gem 'coffee-rails', gem 'coffee-rails', '4.2.1' gem 'jquery-rails', gem 'jquery-rails', '4.1.1' gem 'turbolinks', gem 'turbolinks', '5.0.1' gem 'jbuilder', gem 'jbuilder', '2.4.1' group :development, :development, :test do gem 'sqlite3', gem 'sqlite3', '1.3.12' gem 'byebug', gem 'byebug', '9.0.0', '9.0.0', platform : :mri end group :development do gem 'web-console', gem 'web-console', '3.1.1' gem 'listen', gem 'listen', '3.0.8' gem 'spring', gem 'spring', '1.7.2' gem 'spring-watcher-listen', gem 'spring-watcher-listen', '2.0.0' end group :production do gem 'pg', gem 'pg', '0.18.4' end # Win Windo dows ws do does es no not t in inclu clude de zon zonein einfo fo fil files es, , so bu bund ndle le th the e tz tzinf infoo-dat data a gem gem 'tzinfo-data', gem 'tzinfo-data', platforms platforms: : [:mingw :mingw, , :mswin, :mswin, :x64_mingw, :x64_mingw, :jruby] :jruby]
To prep prepar aree the syst system em for for de depl ploy oyme ment nt to prod produc uctio tion, n, we ru run n bundle install with a special flag to prevent the local installation of any production gems (which in this case consists of the pg gem):
1.5. DEPLOYING DEPLOYING
59
install tall --wi --withou thout t prod producti uction on $ bundle ins
1.14 is is restricted to a production enviBecause the only gem added in Listing in Listing 1.14 ronment, right now this command doesn’t actually install any additional local gems, but it’s needed to update Gemfile.lock with the pg g gem em.. We can can commit the resulting change as follows: $ git git co comm mmit it -a -m -m "Update "Update Gemf Gemfile ile for Hero Heroku" ku"
Next we have to create and configure a new Heroku account. The first step Then check check to see see if your sys syste tem m al alre read ady y has has th thee is to sign to sign up for Heroku. Heroku . Then Heroku command-line client installed: heroku version $ heroku
Those using the cloud IDE should see the Heroku version number, indicating that the heroku CLI is available, but on other systems it may be necessary to install it using the Heroku the Heroku Toolbelt. Toolbelt.27 Once you’ve verified that the Heroku command-line interface is installed, use the heroku command to log in and add your SSH key: heroku log login in $ heroku $ heroku heroku keys:ad keys:add d
Finally, use the hero heroku ku cre create ate command to create a place on the Heroku servers for the sample app to live (Listing ( Listing 1.15). 1.15). Listing 1.15: Creating a new application at Heroku. $ heroku heroku create Creating g app... done, fathomle fathomless-beyon ss-beyond-39164 d-39164 Creatin https://damp-fo https:/ /damp-fortressrtress-5769.her 5769.herokuapp.c okuapp.com/ om/ | https://git.heroku.com/damp-fortress-5769.git
27
toolbelt.heroku.com
60
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
The heroku command creates a new subdomain just for our application, available for immediate viewing. There’s nothing there yet, though, so let’s get busy deploying.
1.5.2 1.5 .2
Herok Heroku u deplo deployme yment, nt, step step one one
To deploy the application, the first step is to use Git to push the master branch up to Heroku: $ git push push herok heroku u mast master er
(You may see some warning messages, which you should ignore for now. We’ll (You Section 7.5.) discusss them further in discus in Section 7.5.)
1.5.3 1.5 .3
Herok Heroku u deplo deployme yment, nt, step step two two
There is no step two! We’re There e’re alrea already dy done. To see you yourr newly deploy deployed ed application, visit the address that you saw when you ran h hero eroku ku cre create ate (i.e., Listing 1.15). you’re worki working ng on you yourr loc local al machine machine ins instea tead d of the cloud cloud 1.15). (If you’re heroku oku ope open n.) The result appears in Figure in Figure 1.20 1.20.. The IDE, you can also use her page is identical to Figure to Figure 1.12 1.12,, but now it’s running in a production environment on the live web. Exercises
railstutorial.org/solutions with with Solutions to exercises are available for free at railstutorial.org/solutions any Rails Tutorial Tutorial purchase. To see other people’ people’ss answers and to record your Learn Enough Society Society at at learnenough.com/society learnenough.com/society.. own,, join the own the Learn 1. By mak making ing the sa same me change change as in in Section Section 1.3.4 1.3.4,, arrange for your production app to display “hola, mundo!” mundo!”.. 2. As in in Section 1.3.4, arrange for the root route to display the result of the Section 1.3.4, goodbye action. When deploying, confirm that you can omit master in git t pu push sh he hero roku ku. the Git push, as in gi
1.5. DEPLOYING DEPLOYING
Figure 1.20: The first Rails Tu Tutorial torial applicati application on running on Heroku. Heroku.
61
62
1.5.4 1.5 .4
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
Herok Heroku u comma commands nds
commands,, and we’ll barely scratch the surface in this There are many Heroku many Heroku commands book. Let’s take a minute to show just one of them by renaming the application as follows: $ heroku rename rails-tu rails-tutorialtorial-hello hello
Don’t use this name yourse Don’t yourself; lf; it’s already take taken n by me! In fact, you probably shouldn’t bother with this step right now; using the default address supplied by Heroku is fine. But if you do want to rename your applicati application, on, you can arrange for it to be reasonably secure by using a random or obscure subdomain, such as the following: hwpcbmze.herokuapp.com seyjhflo.herokuapp.com jhyicevg.herokuapp.com
With a random subdomain like this, someone could visit your site only if you gave them the address.28 (By the way, as a preview of Ruby’s compact awesomeness, somene ss, here’ here’ss the code I used to genera generate te the random subdom subdomains: ains: 'z') ).to_a to_a. .shuffle shuffle[0. [0.. .7]. 7].join join ('a'. 'a'..'z'
Pretty sweet.) In addition to supporting subdomains, Heroku also supports custom domains. (In fact, the Ruby the Ruby on Rails Tutorial site lives site lives at Heroku; if you’re reading this book online, you’re looking at a Heroku-hosted site right now!) See the Heroku documentation for documentation for more information about custom domains and other Heroku topics. 28
This solution, known as “security through obscurity”, is fine for hobby projects, but for sites that require This is a much much more advanc advanced ed greater initial security I recommend using Rails HTTP basic authentication. authentication. This implement. (Than (Thanks ks to technique, though, and requires significantly more technical sophistication (Box ( Box 1.1) 1.1) to implement. Alfie Pates for raising this issue.)
1.6. CONCLUSIO CONCLUSION N
63
Exercises
railstutorial.org/solutions with with Solutions to exercises are available for free at railstutorial.org/solutions any Rails Tutorial Tutorial purchase. To see other people’ people’ss answers and to record your own,, join the own the Learn Learn Enough Society Society at at learnenough.com/society learnenough.com/society.. heroku oku hel help p to see a list of Heroku commands. What is the com1. Ru Run n her mand to display logs for an app?
2. Use the command iden identified tified in the previous previous exerc exercise ise to inspect the activ activ-ity on on your your app applica licatio tion. n. Wha Whatt was tthe he mos mostt rec recent ent event? event? (This comman command d is often useful when debugging production apps.)
1.6
Concl nclusi usion
We’ve come a long way in this chapter: installation, development environment setup, version control, and deployment. In the next chapter, we’ll build on the foundation from Chapter from Chapter 1 1 to to make a database-backed toy app, which will give us our first real taste of what Rails can do. If you’d you’d like to share your progres progresss at this point, feel free to send a tweet or Facebook status update with something like this: @railstutorial utorial!! I’m learning Ruby on Rails with the @railst http://www.railstutorial.org/ I also recommend signing up for the Rails Tutorial email list29 , which will ensu en sure re that that yo you u rece receiv ivee prio priorit rity y up upda date tess (and (and exclu exclusi sive ve co coup upon on code codes) s) rega regard rdin ing g the Ruby on Rails Tutorial .
1.6.1 1.6 .1
What What we we learn learned ed in this this chapte chapterr
• Ruby on Rails is a web deve development lopment fram framewo ework rk written in the Ruby programming language. 29
railstutorial.org/email
64
CHAPTER CHAPTER 1. FROM FROM ZERO ZERO TO DEPLOY DEPLOY
• Instal Installing ling Rails, gener generating ating an applica application, tion, and editing the resul resulting ting files is easy using a pre-configured cloud environment. • Rails com comes es with a command command-line -line command command called called rails that can generat er atee ne new w ap appli plica catio tions ns (rail rails s ne new w) an and d ru run n lo loca call serv server erss (rail rails s se serrver). • We ad adde ded d a cont contro rolle llerr ac acti tion on and and modi modifie fied d the root rout routee to cr crea eate te a “hello, world” application. • We protected against data loss while enabling enabling collaboration collaboration by placin placing g our application source code under version control with Git and pushing the resulting code to a private repository at Bitbucket. • We deployed our application to a production environment environment using Heroku.
Chapter 2
A toy app In this chapter, we’ll develop a toy demo application to show off some of the power of Rails. The purpose is to get a high-level overview of Ruby on Rails prog progra ramm mmin ing g (and (and we web b deve develo lopm pmen entt in gene genera ral) l) by rapid rapidly ly gene genera ratin ting g an ap appl pliication using scaffold generators, which create a large amount of functionality automatically. As discussed in Box in Box 1.2, 1.2, the rest of the book will take the opposite approach, developing a full sample application incrementally and explaining each new concept as it arises, but for a quick overview (and some instant gratification) gratifi cation) there is no substitute for scaffold scaffolding. ing. The resulting toy app will allow us to interact with it through its URLs, giving us insight into the structure of a Rails application, including a first example of the REST architecture favored by Rails. As with the forthcoming sample application, the toy app will consist of users and their associated microposts (thus constituting a minimalist Twitterstyle app). The functionality will be utterly under-developed, and many of the steps will seem like magic, but worry not: the full sample app will develop a similar application application from the ground up starting in in Chapter 3, and I will provide Chapter 3, plentiful forward-references to later material. In the mean time, have patience and a little faith—the whole point of this tutorial is to take you beyond this this superficial, scaffold-driven approach to achieve a deeper understanding of Rails. 65
66
2.1
CHAPTE CHAPTER R 2. A TOY TOY APP
Planni Planning ng the appli applicat catio ion n
In this section, we’ll outline our plans for the toy application. As in Section in Section 1.3, 1.3, we’ll start by generating the application skeleton using the r rai ails ls ne new w command with a specifi specificc Rails versi version on number: $ cd cd ~/workspace $ rails rails _5.0 _5.0.1_ .1_ new toy_ toy_app app cd toy_app/ $ cd
1.2.1,, note that this If you’re using the cloud IDE as recommended in Section in Section 1.2.1 second app can be created in the same workspace as the first. It is not necessary to create a new workspace. In order to get the files to appear, you may need to click the gear icon in the file navigator area and select “Refresh File Tree”. Next, we’ll use a text editor to update the Gemfile needed by Bundler 2.1.. Important note: For all the Gemfiles in this with the contents of Listing Listing 2.1 book, you should use the version numbers listed at gemfiles-4th-ed.railsat gemfiles-4th-ed.railstutorial.org instead tutorial.org instead of the ones listed below (although they should be identical if you are reading this online). Listing 2.1: A Gemfile for the toy app. source 'https://rubygems.org' gem 'rails', gem 'rails', '5.0.1' gem 'puma', gem 'puma', '3.4.0' gem 'sass-rails', gem 'sass-rails', '5.0.6' gem 'uglifier', gem 'uglifier', '3.0.0' gem 'coffee-rails', gem 'coffee-rails', '4.2.1' gem 'jquery-rails', gem 'jquery-rails', '4.1.1' gem 'turbolinks', gem 'turbolinks', '5.0.1' gem 'jbuilder', gem 'jbuilder', '2.4.1' group :development, :development, :test do gem 'sqlite3', gem 'sqlite3', '1.3.12' gem 'byebug', gem 'byebug', '9.0.0', '9.0.0', platform : :mri end group :development do gem 'web-console', gem 'web-console', gem 'listen', gem 'listen',
'3.1.1' '3.0.8'
2.1. PLANNING THE APPLICA APPLICATION TION
67
gem 'spring', gem 'spring', '1.7.2' gem 'spring-watcher-listen', gem 'spring-watcher-listen', '2.0.0' end group :production do gem 'pg', gem 'pg', '0.18.4' end # Win Windo dows ws do does es no not t in inclu clude de zon zonein einfo fo fil files es, , so bu bund ndle le th the e tz tzinf infoo-dat data a gem gem 'tzinfo-data', gem 'tzinfo-data', platforms platforms: : [:mingw :mingw, , :mswin, :mswin, :x64_mingw, :x64_mingw, :jruby] :jruby]
Note that Listing that Listing 2.1 2.1 is is identical to Listing to Listing 1.14. 1.14. As in Section in Section 1.5.1, 1.5.1, we’ll install the local gems while suppressing the in--without hout produ production ction option: stallation stallat ion of produc production tion gems using the --wit install tall --wi --withou thout t prod producti uction on $ bundle ins
As noted in Section 1.3.1, 1.3.1, you may need to run bu bundl ndle e upd update ate as well (Box 1.1). 1.1). Finally,, we’ll put the toy app under versio Finally version n control with Git: init $ git init $ git git ad add d -A $ git commi commit t -m -m "Initiali "Initialize ze reposit repository" ory"
You should also create also create a new repository repository by by clicking on the “Create” button at Bitbucket (Figure (Figure 2.1), 2.1), and then push up to the remote repository: $ git remote add origin git@bit
[email protected] bucket.org:/toy_app.g oy_app.git it push -u origi origin n --a --all ll $ git push
Finally, it’s never too early to deploy, which I suggest doing by following in Listing 2.2 and 2.2 and the same “hello, world!” steps from Section from Section 1.3.4, 1.3.4, as shown in Listing 2.3. Listing 2.3.
68
CHAPTE CHAPTER R 2. A TOY TOY APP
Figure 2.1: Creatin Creating g the toy app repository at Bitbuck Bitbucket. et.
2.1. PLANNING THE APPLICA APPLICATION TION
69
Listing 2.2: Adding a hello action to the Application controller. app/controllers/application_controller.rb ActionController::Base Base class ApplicationController < ActionController:: protect_from_forgery with: with: :exception def hello render html html: : "hell "hello, o, world!" end end
Listing 2.3: Setting the root route. config/routes.rb Rails Rails. .application application. .routes routes. .draw do root 'application#hello' end
Then commit the changes and push up to Heroku: $ git commi commit t -am "Add hell hello" o" $ heroku heroku create $ git push push herok heroku u mast master er
(As in Section in Section 1.5, 1.5, you may see some warning messages, which you should ignore for now. We’ll deal with them in Section in Section 7.5.) 7.5.) Apart from the URL of the Heroku app, the result should be the same as in Figure in Figure 1.20. 1.20. Now we’re ready to start making the app itself. The typical first step when making a web application is to create a data model, which is a representation of the structures needed by our application. In our case, the toy app will be a Twitter witter-style -style microb microblog, log, with only users and short (micro)posts (micro)posts.. Thus, we’ll begin with a model for users of the app (Section (Section 2.1.1), 2.1.1), and then we’ll add a Section 2.1.2). model for microposts ( (Section 2.1.2).
2.1. 2. 1.1 1
A toy toy mode modell for us user erss
There are as many choices for a user data model as there are different registration forms on the web; for simplicity, we’ll go with a distinctly minimalist
70
CHAPTE CHAPTER R 2. A TOY TOY APP
users
id
integer name string email string
Figure 2.2: The data model for users. approach. Users of our toy app will have a unique identifier called id (of (of type integer), a publicly viewable name (of type string), and an email address double ble as a uni unique que userna username. me. A summary summary of (also of type string) that will dou the data model for users appears in Figure in Figure 2.2 2.2.. 6.1.1,, the label users in in Figure Figure 2.2 cor2.2 corAs we’ll see starting in Section in Section 6.1.1 responds to a table in a database, and the id , name, and email attributes are columns in that table.
2.1.2 2.1 .2
A toy model model for for micro micropos posts ts
The core of the micropost data model is even simpler than the one for users: and a content field for the micropost’s text (of a micropost has only an id and 1 type text). There’s an additional complication, though: we want to associate each micropost micropost with a particular user user.. We’ll accomplis accomplish h this by recording the of the owner of the post. The results are shown in Figure 2.3 2.3.. user_id of 2.3.3 (and (and more fully in Chapter in Chapter 13) 13) how this user_id We’ll see in Section in Section 2.3.3 attribute allows us to succinctly express the notion that a user potentially has many associated microposts. 1
Because microposts are short by design, the string type is actually big enough to contain them, but using text better expresses our intent, while also giving us greater flexibility should we ever wish to relax the length constraint.
2.2. THE USERS RESOURCE RESOURCE
71
microposts id integer content text user_id integer
Figure 2.3: The data model for microposts.
2.2 2. 2
The The User Userss res esou ourrce
2.1.1,, along In this section, we’ll implement the users data model in Section 2.1.1 with a web interf interface ace to that model. The combina combination tion will constitute a Users resource, which will allow us to think of users as objects that can be created, read, updated, and deleted through the web via the HTTP the HTTP protocol protocol.. As promised in the introduction, our Users resource will be created by a scaffold generator program, which comes standard standard with each Rails project. I urge you not to look too closely at the generated code; at this stage, it will only serve to confuse you. command to the Rails scaffolding is generated by passing the scaffold command rails ls gen genera erate te sscri cript. pt. The ar argum gument ent of the scaffold command is the rai singular version of the resource name (in this case, User), together with optional parameters for the data model’s attributes: 2 $ rails gene generate rate scaf scaffold fold User name name:str :string ing emai email:s l:strin tring g invo invoke ke act active_ ive_reco record rd create crea te db/migra db/m igrate/ te/2016 20160515 05150010 001017_c 17_crea reate_u te_users sers.rb .rb creat cr eate e app/m ap p/mode odels ls/us /user er.rb .rb invo vok ke test st_ _uni nit t crea cr eate te test te st/m /mod odel els/ s/us user er_t _tes est. t.rb rb crea cr eate te test te st/f /fix ixtu ture res/ s/us user ers. s.ym yml l invoke invo ke res resourc ource_ro e_route ute rout ro ute e reso re sour urce ces s :u :use sers rs invoke invo ke sca scaffol ffold_co d_contro ntrolle ller r create crea te app/cont app/ control rollers lers/use /users_c rs_contr ontroll oller.r er.rb b 2
The name of the scaffold follows the convention of models models, which are singular, rather than resources and
Users. controllers, which are plural. Thus, we have User instead of Users
72
invoke crea eat te creat cr eate e
CHAPTE CHAPTER R 2. A TOY TOY APP
erb app/vi vie ews/u /us sers app/ ap p/vie views ws/us /users ers/i /inde ndex. x.htm html. l.erb erb
cr crea eate te crea cr eate te crea cr eate te creat cr eate e invo vok ke creat cr eate e invoke crea cr eate te invoke invo vok ke creat cr eate e creat cr eate e invok in voke e invoke creat cr eate e invoke
ap app/ p/vi view ews/ s/us user ers/ s/ed edit it.h .htm tml. l.er erb b app/ ap p/vi view ews/ s/us user ers/ s/sh show ow.h .htm tml. l.er erb b app/ ap p/vi view ews/ s/us user ers/ s/ne new. w.ht html ml.e .erb rb app/ ap p/vie views ws/us /users ers/_ /_for form. m.htm html. l.erb erb test st_ _uni nit t test te st/co /cont ntrol roller lers/ s/use users rs_co _cont ntrol rolle ler_t r_tes est.r t.rb b helper app/ ap p/he help lper ers/ s/us user ers_ s_he help lper er.r .rb b test_unit jbui uil lder app/ ap p/vie views ws/us /users ers/i /inde ndex. x.jso json. n.jbu jbuil ilder der app/ ap p/vie views ws/us /users ers/s /show how.j .json son.j .jbui build lder er asse as sets ts coffee app/ ap p/ass asset ets/j s/java avasc scrip ripts ts/us /user ers.c s.cof offee fee scss
cr creat eate e invo in voke ke create crea te
app/ p/ass asset ets/s s/styl tyles eshee heets ts/us /user ers.s s.scs css s scssap scss app/asse app/ assets/ ts/styl styleshe esheets/ ets/scaf scaffol folds.s ds.scss css
By including name:string and email:string, we have arranged for the User model to have the form shown in Figure in Figure 2.2. 2.2. (Note that there is no need automatically by Rails for use as the to include a parameter for id ; it is created automatically primary key in the database.) To proceed with the toy application, we first need to migrate the database using rails db:mi db:migrate grate, as shown in Listing in Listing 2.4 2.4.. Listing 2.4: Migrating the database. $ rail rails s db:m db:migra igrate te == CreateUsers: CreateUsers: migrating ========= ================= ================ =============== =============== =============== ============ ===== -- create_t create_table(:us able(:users) ers) -> 0.00 0.0017s 17s == CreateUsers: CreateUsers: migrated (0.0018s (0.0018s) ) ============= ===================== =============== =============== =============== =======
The effect of Listing Listing 2.4 is 2.4 is to update the database with our new users data model. (We’ll learn more about database migrations starting in Section in Section 6.1.1.) 6.1.1.) By the way, it is important to note that in every version of Rails before Rails 5, the db:migrate command used rake in place of rails rails, so for the sake of legacy applications it’s important to know how to use Rake (Box (Box 2.1 2.1))
2.2. THE USERS RESOURCE RESOURCE
73
Box 2.1. Rake
In the Unix tradition, the Make utility has played an important role in buil building ding executable programs from source code. Rake is Ruby make, a Make-like language written in Ruby. Before Rails 5, Ruby on Rails used Rake extensively, so for the sake of legacy Rails Rai ls applic applicatio ations ns it’ it’ss importa important nt to know how to use it. Probab Probably ly the two most common Rake commands in a Rails context are rake db:m db:migra igrate te (to update the database with a data model) and ra rake ke te test st (to run the automated test suite). rake, it’s important to ensure that the command uses In these and other uses of rake the version of Rake corresponding to the Rails application’s Gemfile, which is accomplished using the Bundler command bun bundle dler r exe exec c. Thus, the migr migration ation command $ ra rake ke db db:m :mig igra rate te
would be written as $ bu bund ndle le ex exec ec ra rake ke db db:m :mig igra rate te
2.4,, we can run the local webserver in Having run the migration in Listing in Listing 2.4 a separate tab (Figure (Figure 1.8) 1.8) as follows:
$ rails rails ser serve ver r -b $IP -p $PORT
# Use `rails `rails server server` ` if ru runni nning ng locall locally. y.
Now the toy application should be available on the local server as described 1.3.2.. (If you’re using the cloud IDE, be sure to open the resulting in Section in Section 1.3.2 development server in a new browser tab, tab, not inside the IDE itself.)
74
URL /users /users/1 /users/new /users/ne w /users/1/editt /users/1/edi
CHAPTE CHAPTER R 2. A TOY TOY APP
Action index show new edit
Purpose page to list all users page to show user with id 1 page to make a new user page to edit user with id 1
Tabl ablee 2.1 2.1:: The corre correspo sponde ndence nce betwe between en pag pages es and URLs for the Use Users rs resource.
2.2. 2. 2.1 1
A user user tour tour
Section 1.3.4), If we visit the root URL at / (read “slas “slash”, h”, as noted in in Section 1.3.4), we get the same “hello, world!” page shown in Figure in Figure 1.12, 1.12, but in generating the Users resource scaffolding we have also created a large number of pages for manipulating users. users. For exam example, ple, the page for listing all users is at /users, and the page for making making a ne new w use userr is at /us /users ers/ne /new w. The rest of this this sec sectio tion n is dedicated dedicated to taking taking a whir whirlwi lwind nd tour throu through gh these user pag pages. es. As we pro procee ceed, d, it may help to refer to Table to Table 2.1 2.1,, which shows the correspondence between pages and URLs. We start with the page to show all the users in our application, called index and located located at /users. /users. As you might expect, expect, initia initially lly there there are no users at all 2.4). ). (Figure 2.4 in FigTo make a new user, we visit the new page at /users/new, as shown in Figure 2.5. 2.5. In Chapter In Chapter 7 7,, this will become the user signup page. We can create a user by entering name and email values in the text fields and then then clicki clicking ng the Cr Crea eate te User but button ton.. The The resu result lt is the us user er show page at 2.6.. (The green welcome message is accomplished /users/1, as seen in Figure in Figure 2.6 using the flash, which we’ll learn about in Section in Section 7.4.2.) 7.4.2.) Note that the URL is attribute /users/1; as you might suspect, the number 1 is simply the user’s id attribute Figure 2.2 2.2.. In Section In Section 7.1 7.1,, this page will become the user’s profile page. from Figure from To change a user’s information, we visit the edit page at /users/1/edit (Fig(Figure 2.7). 2.7). By modifying the user information and clicking the Update User button, we arrange to change the information for the user in the toy application we’l ’lll see see in de detai taill star startin ting g in Chapter 6, 6, this user data is (Figure 2.8). 2.8). (As we stored in a database back-end.) We’ll add user edit/update functionality to the
2.2. THE USERS RESOURCE RESOURCE
Figure 2.4: The initial index page for the Users resourc resourcee (/users).
75
76
CHAPTE CHAPTER R 2. A TOY TOY APP
Figure 2.5: The new user page (/users/n (/users/new). ew).
2.2. THE USERS RESOURCE RESOURCE
Figure 2.6: The page to show a user (/users/1).
77
78
CHAPTE CHAPTER R 2. A TOY TOY APP
Figure 2.7: The user edit page (/users/1/edit) (/users/1/edit)..
sample application in Section in Section 10.1. 10.1. Now we’ll create a second user by revisiting the new page at /users/new and submitting a second set of user information. The resulting user index is shown in Figure in Figure 2.9 2.9.. Section 7.1 7.1 will will develop the user index into a more polished page for showing all users. Having shown how to create, show, and edit users, we come finally to destroying them (Figure (Figure 2.10 2.10). ). You should verify that clicking on the link in Figin Figure 2.10 destroys 2.10 destroys the second user, yielding an index page with only one user. (If it doesn’t work, be sure that JavaScript is enabled in your browser; Rails uses JavaScript to issue the request needed to destroy a user.) Section user.) Section 10.4 adds 10.4 adds user deletion to the sample app, taking care to restrict its use to a special class of