learn ruby - the hard way

128
Learn Ruby The Hard Way Welcome to Learn Ruby the hard way. This is a translation of "Learn Python The Hard Way" to teach total beginners Ruby. It's in the same style, and the content is nearly the same, but it will teach you Ruby. The Hard Way Is Easier This simle boo! is meant to get you started in rogramming. The title says it's the hard way to learn to write code but it's actually not. It's only the "hard" way because it's the way  eole used  to teach things. With the hel of this boo!, you will do the incredibly simle things that all rogrammers need to do to learn a language# $. %o through ea ch e &ercise . . Tye i n ea ch sa mle e& act ly. (. )a!e it run. That's it. This will be very difficult at first, but stic! with it. If you go through this boo!, and do each e&ercise for one or two hours a night, you will ha*e a good foundation for mo*ing onto another boo!. +ou might not really learn "rogramming" from this boo!, but you will learn the foundation s!ills you need to start learning the language. This boo!'s ob is to teach you the three most essential s!ills that a beginning rogrammer needs to !now# Reading and Writing, -ttention to etail, /otting ifferences. Reading and Writing It seems stuidly ob*ious, but, if you ha*e a roblem tying, you will ha*e a roblem learning to code. 0secially if you ha*e a roblem tying the fairly odd characters in source code. Without this simle s!ill you will be unable to learn e*en the most basic things about how software wor!s. Tying the code samles and getting them to run will hel you learn the names of the symbols, get familiar with tying them, and get you reading the language.  Attention to Detail The one s!ill that searates bad rogrammers from good rogrammers is attention to detail. In fact, it's what searates the good from the bad in any rofession. Without aying attention to the tiniest details of your wor!, you will miss !ey elements of what you create. In  rogramming, this is how you end u with bugs and difficult1to1use systems. 2y going through this boo!, and coying each e&amle exactly, you will be training your  brain to focus on the details of what you are doing, as you are doing it. $

Upload: gteodorescu

Post on 04-Jun-2018

246 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 1/128

Learn Ruby The Hard Way

Welcome to Learn Ruby the hard way. This is a translation of "Learn Python The Hard Way"

to teach total beginners Ruby. It's in the same style, and the content is nearly the same, but it

will teach you Ruby.

The Hard Way Is Easier

This simle boo! is meant to get you started in rogramming. The title says it's the hard way

to learn to write code but it's actually not. It's only the "hard" way because it's the way

 eole used  to teach things. With the hel of this boo!, you will do the incredibly simle

things that all rogrammers need to do to learn a language#

$. %o through each e&ercise.. Tye in each samle e&actly.

(. )a!e it run.

That's it. This will be very difficult at first, but stic! with it. If you go through this boo!, and

do each e&ercise for one or two hours a night, you will ha*e a good foundation for mo*ing

onto another boo!. +ou might not really learn "rogramming" from this boo!, but you will

learn the foundation s!ills you need to start learning the language.

This boo!'s ob is to teach you the three most essential s!ills that a beginning rogrammer

needs to !now# Reading and Writing, -ttention to etail, /otting ifferences.

Reading and Writing 

It seems stuidly ob*ious, but, if you ha*e a roblem tying, you will ha*e a roblem

learning to code. 0secially if you ha*e a roblem tying the fairly odd characters in source

code. Without this simle s!ill you will be unable to learn e*en the most basic things about

how software wor!s.

Tying the code samles and getting them to run will hel you learn the names of the

symbols, get familiar with tying them, and get you reading the language.

 Attention to Detail 

The one s!ill that searates bad rogrammers from good rogrammers is attention to detail.

In fact, it's what searates the good from the bad in any rofession. Without aying attention

to the tiniest details of your wor!, you will miss !ey elements of what you create. In

 rogramming, this is how you end u with bugs and difficult1to1use systems.

2y going through this boo!, and coying each e&amle exactly, you will be training your

 brain to focus on the details of what you are doing, as you are doing it.

$

Page 2: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 2/128

Spotting Differences

- *ery imortant s!ill 11 that most rogrammers de*elo o*er time 11 is the ability to *isually

notice differences between things. -n e&erienced rogrammer can ta!e two ieces of code

that are slightly different and immediately start ointing out the differences. Programmers

ha*e in*ented tools to ma!e this e*en easier, but we won't be using any of these. +ou firstha*e to train your brain the hard way, then you can use the tools.

While you do these e&ercises, tying each one in, you will be ma!ing mista!es. It's

ine*itable e*en seasoned rogrammers would ma!e a few. +our ob is to comare what you

ha*e written to what's re3uired, and fi& all the differences. 2y doing so, you will train

yourself to notice mista!es, bugs, and other roblems.

Do Not Copy-Paste

+ou must type each of these e&ercises in, manually. If you coy and aste, you might as well ust not e*en do them. The oint of these e&ercises is to train your hands, your brain, and

your mind in how to read, write, and see code. If you coy1aste, you are cheating yourself

out of the effecti*eness of the lessons.

 A Note On Practice And Persistence

While you are studying rogramming, I'm studying how to lay guitar. I ractice it e*ery day

for at least hours a day. I lay scales, chords, and areggios for an hour at least and then

learn music theory, ear training, songs and anything else I can. /ome days I study guitar and

music for 4 hours because I feel li!e it and it's fun. To me reetiti*e ractice is natural and

 ust how to learn something. I !now that to get good at anything you ha*e to ractice e*eryday, e*en if I suc! that day 5which is often6 or it's difficult. 7ee trying and e*entually it'll be

easier and fun.

-s you study this boo!, and continue with rogramming, remember that anything worth

doing is difficult at first. )aybe you are the !ind of erson who is afraid of failure so you

gi*e u at the first sign of difficulty. )aybe you ne*er learned self1disciline so you can't do

anything that's "boring". )aybe you were told that you are "gifted" so you ne*er attemt

anything that might ma!e you seem stuid or not a rodigy. )aybe you are cometiti*e and

unfairly comare yourself to someone li!e me who's been rogramming for 89 years.

Whate*er your reason for wanting to 3uit, !ee at it. :orce yourself. If you run into an 0&tra;redit you can't do, or a lesson you ust do not understand, then s!i it and come bac! to it

later. <ust !ee going because with rogramming there's this *ery odd thing that haens.

-t first, you will not understand anything. It'll be weird, ust li!e with learning any human

language. +ou will struggle with words, and not !now what symbols are what, and it'll all be

*ery confusing. Then one day BANG your brain will sna and you will suddenly "get it". If

you !ee doing the e&ercises and !ee trying to understand them, you will get it. +ou might

not be a master coder, but you will at least understand how rogramming wor!s.

Page 3: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 3/128

If you gi*e u, you won't e*er reach this oint. +ou will hit the first confusing thing 5which is

e*erything at first6 and then sto. If you !ee trying, !ee tying it in, trying to understand it

and reading about it, you will e*entually get it.

2ut, if you go through this whole boo!, and you still do not understand how to code, at least

you ga*e it a shot. +ou can say you tried your best and a little more and it didn't wor! out, but at least you tried. +ou can be roud of that.

License

This boo! is ;oyright 5;6 8$$ by =ed -. /haw. +ou are free to distribute this boo! to

anyone you want, so long as you do not  charge anything for it, and  it is not altered. +ou must

gi*e away the boo! in its entirety, or not at all. This means it's alright for you to teach a class

using the boo!, so long as you aren't charging students for the book  and you gi*e them the

whole boo! unmodified.

Special Thanks

I'd li!e to than! a few eole who heled with this edition of the boo!. :irst is my editor at

 Pretty Girl Editing Services who heled me edit the boo! and is ust lo*ely all by herself.

Then there's Greg Newman, who did the co*er ac!et and artwor!, lus re*iewed coies of

the boo!. His artwor! made the boo! loo! li!e a real boo!, and didn't mind that I totally

forgot to gi*e him credit in the first edition. I'd also li!e to than!  Brian Shumate for doing the

website landing age and other site design hel, which I need a lot of hel on.

:inally, I'd li!e to than! the hundreds of thousands of eole who read the first edition and

esecially the ones who submitted bug reorts and comments to imro*e the boo!. It reallymade this edition solid and I couldn't ha*e done it without all of you. Than! you.

Exercise 0: The Setup

This e&ercise has no code. It is simly the e&ercise you comlete to get your comuter setu

to run Ruby. +ou should follow these instructions as e&actly as ossible.

This tutorial assumes that you are using Ruby *ersion $.>.(.

+our system might already ha*e Ruby installed. ?en u a console and try running#

$ ruby -vruby 1.9.3

If you don't already ha*e Ruby installed on your system, I highly recommend using Ruby

@ersion )anager 5R@)6 to install it, regardless of which ?/ you are running.

Mac OS 

To comlete this e&ercise, comlete the following tas!s#

(

Page 4: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 4/128

$. %o to htt#AAwww.barebones.comAroductsAte&twranglerA with your browser, get the

TextWrangler te&t editor, and install it.

. Put Te&tWrangler 5your editor6 in your oc! so you can reach it easily.

(. :ind your "Terminal" rogram. /earch for it. +ou will find it.

B. Put your Terminal in your oc! as well.

C. Run your Terminal rogram. It won't loo! li!e much.D. In your Terminal rogram, run irb 5Interacti*e Ruby6. +ou run things in Terminal by

 ust tying their name and hitting R0TERF.

$. If you run irb and it's not there 5irb is not recogniGed..6. Install it using Ruby

@ersion )anager 5R@)6.

. Hit ;TRL1 5^D6 and get out of irb.

4. +ou should be bac! at a romt similar to what you had before you tyed irb. If not

find out why.

>. Learn how to ma!e a directory in the Terminal. /earch online for hel.

$8. Learn how to change into a directory in the Terminal. -gain search online.

$$. Ese your editor to create a file in this directory. +ou will ma!e the file, "/a*e" or

"/a*e -s...", and ic! this directory.

$. %o bac! to Terminal using ust the !eyboard to switch windows. Loo! it u if you

can't figure it out.

$(. 2ac! in Terminal, see if you can list the directory to see your newly created file.

/earch online for how to list a directory.

OS! What "o# Sho#ld See

Here's me doing the abo*e on my comuter in Terminal. +our comuter would be different,

so see if you can figure out all the differences between what I did and what you should do.

Last login: Sat Apr ! "":#:#! on ttys""1% $ irbruby-1.9.-p1&" :""1 'ruby-1.9.-p1&" :"" ' ^D% $ ()*ir (ystu++% $ ,* (ystu++(ystu++ $ ls ... se TextWrangler /ere to e*it test.txt....(ystu++ $ lstest.txt(ystu++ $

Windo$s

 Fote

;ontributed by Ghmar!.

$. %o to htt#AAnotead1lus1lus.orgA with your browser, get the 0otepa* te&t editor,

and install it. +ou do not need to be administrator to do this.

. )a!e sure you can get to Fotead99 easily by utting it on your des!to andAor in

uic! Launch. 2oth otions are a*ailable during setu.

(. :ind your "Terminal" rogram. It's called 2o((an* ro(pt. -lternati*ely ust run

,(*.

B

Page 5: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 5/128

B. )a!e a shortcut to it on your des!to andAor 4ui,) Laun,/ for your con*enience.

C. Run your Terminal rogram. It won't loo! li!e much.

D. In your Terminal rogram, run irb 5Interacti*e Ruby6. +ou run things in Terminal by

 ust tying their name and hitting R0TERF.

$. If you run irb and it's not there 5irb is not recogniGed..6. Install it using Ruby

@ersion )anager 5R@)6.. Hit ;TRL1= 5J=6, 0nter and get out of irb.

4. +ou should be bac! at a romt similar to what you had before you tyed irb. If not

find out why.

>. Learn how to ma!e a directory in the Terminal. /earch online for hel.

$8. Learn how to change into a directory in the Terminal. -gain search online.

$$. Ese your editor to create a file in this directory. )a!e the file, "/a*e" or "/a*e -s...",

and ic! this directory.

$. %o bac! to Terminal using ust the !eyboard to switch windows. Loo! it u if you

can't figure it out.

$(. 2ac! in Terminal, see if you can list the directory to see your newly created file.

/earch online for how to list a directory.

Warning

Windows is a big roblem for Ruby. /ometimes you install Ruby and one comuter will ha*e

no roblems, and another comuter will be missing imortant features. If you ha*e roblems,

 lease *isit# htt#AArubyinstaller.orgA

Windo$s! What "o# Sho#ld See2:5Do,u(ents an* Settings5you'irb

ruby-1.9.-p1&" :""1 'ruby-1.9.-p1&" :""1 ' ^6

2:5Do,u(ents an* Settings5you'()*ir (ystu++

2:5Do,u(ents an* Settings5you',* (ystu++

... 7ere you 8oul* use 0otepa* to (a)e test.txt in (ystu++ ...

2:5Do,u(ents an* Settings5you5(ystu++'  bun,/ o+ uni(portant errors i+ you istalle* it as non-a*(in - ignoret/e( - /it nter'2:5Do,u(ents an* Settings5you5(ystu++'*ir

 ;olu(e in *rive 2 is ;olu(e Serial 0u(ber is "&#2-<"

 Dire,tory o+ 2:5Do,u(ents an* Settings5you5(ystu++

"!."#."1" 3:3 D=>' ."!."#."1" 3:3 D=>' .."!."#."1" 3:3 test.txt  1 ?ile@s bytes  Dir@s 1! &"! 3 3" bytes +ree

2:5Do,u(ents an* Settings5you5(ystu++'

+ou will robably see a *ery different romt, Ruby information, and other stuff but this isthe general idea. If your system is different let us !now and we'll fi& it.

C

Page 6: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 6/128

Lin#% 

Linu& is a *aried oerating system with a bunch of different ways to install software. I'm

assuming if you are running Linu& then you !now how to install ac!ages so here are your

instructions#

$. Ese your Linu& ac!age manager and install the ge*it te&t editor.

. )a!e sure you can get to gedit easily by utting it in your window manager's menu.

$. Run gedit so we can fi& some stuid defaults it has.

. ?en re+eren,es select the *itor tab.

(. ;hange Tab 8i*t/# to .

B. /elect 5ma!e sure a chec! mar! is in6 =nsert spa,es instea* o+ tabs.

C. Turn on "-utomatic indentation" as well.

D. ?en the ;ie8 tab turn on "islay line numbers".

(. :ind your "Terminal" rogram. It could be called %F?)0 Terminal, 7onsole, or

&term.B. Put your Terminal in your oc! as well.

C. Run your Terminal rogram. It won't loo! li!e much.

D. In your Terminal rogram, run irb 5Interacti*e Ruby6. +ou run things in Terminal by

 ust tying their name and hitting R0TERF.

$. If you run irb and it's not there 5irb is not recogniGed..6. Install it using Ruby

@ersion )anager 5R@)6.

. Hit ;TRL1 5^D6 and get out of irb.

4. +ou should be bac! at a romt similar to what you had before you tyed irb. If not

find out why.

>. Learn how to ma!e a directory in the Terminal. /earch online for hel.

$8. Learn how to change into a directory in the Terminal. -gain search online.$$. Ese your editor to create a file in this directory. Tyically you will ma!e the file,

"/a*e" or "/a*e -s..", and ic! this directory.

$. %o bac! to Terminal using ust the !eyboard to switch windows. Loo! it u if you

can't figure it out.

$(. 2ac! in Terminal see if you can list the directory to see your newly created file.

/earch online for how to list a directory.

Lin#%! What "o# Sho#ld See$ irbruby-1.9.-p1&" :""1 '

ruby-1.9.-p1&" :"" ' ^D$ ()*ir (ystu++$ ,* (ystu++ ... se ge*it /ere to e*it test.txt ...$ lstest.txt$

+ou will robably see a *ery different romt, Ruby information, and other stuff but this is

the general idea.

D

Page 7: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 7/128

Warnings &or 'eginners

+ou are done with this e&ercise. This e&ercise might be hard for you deending on your

familiarity with your comuter. If it is difficult, ta!e the time to read and study and get

through it, because until you can do these *ery basic things you will find it difficult to get

much rogramming done.

If a rogrammer tells you to use vi( or e(a,s, tell them, "Fo." These editors are for when

you are a better rogrammer. -ll you need right now is an editor that lets you ut te&t into a

file. We will use ge*it, TextWraingler, or 0otepa* 5from now on called "the te&t editor"

or "a te&t editor"6 because it is simle and the same on all comuters. Professional

 rogrammers use these te&t editors so it's good enough for you starting out.

- rogrammer will e*entually tell you to use )ac ?/K or Linu&. If the rogrammer li!es

fonts and tyograhy, they'll tell you to get a )ac ?/K comuter. If they li!e control and

ha*e a huge beard, they'll tell you to install Linu&. -gain, use whate*er comuter you ha*e

right now that wor!s. -ll you need is ge*it, a Terminal, and Ruby.

:inally the urose of this setu is so you can do three things *ery reliably while you wor! on

the e&ercises#

$.   Write e&ercises using ge*it.

.   un the e&ercises you wrote.

(.   !ix them when they are bro!en.

B. Reeat.

-nything else will only confuse you, so stic! to the lan.

Exercise 1: A Good First ro!ra"

Remember, you should ha*e sent a good amount of time in 0&ercise 8 learning how to

install a te&t editor, run the te&t editor, run the Terminal, and wor! with both of them. If you

ha*en't done that then do not go on. +ou will not ha*e a good time. This is the only time I'll

start an e&ercise with a warning that you should not s!i or get ahead of yourself.

Tye the following into a single file named ex1.rb. This is imortant as Ruby wor!s best

with files ending in .rb.

13!#<

puts B7ello Worl*CBputs B7ello AgainBputs B= li)e typing t/is.Bputs BT/is is +un.Bputs EayC rinting.puts B=* (u,/ rat/er you not.Bputs = Bsai*B *o not tou,/ t/is.

Then in Terminal run the file by tying#

ruby ex1.rb

Page 8: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 8/128

If you did it right then you should see the same outut I ha*e below. If not, you ha*e done

something wrong. Fo, the comuter is not wrong.

What "o# Sho#ld See$ ruby ex1.rb

7ello Worl*C7ello Again= li)e typing t/is.T/is is +un.EayC rinting.=* (u,/ rat/er you not.= Bsai*B *o not tou,/ t/is.$

+ou may see the name of your directory before the $ which is fine, but if your outut is not

e&actly the same, find out why and fi& it.

If you ha*e an error it will loo! li!e this#

ruby ex1.rbex1.rb:!: syntax errorF unexpe,te* t2G0STA0TF expe,ting $en*puts BT/is is +un.B  ^

It's imortant that you can read these since you will be ma!ing many of these mista!es. 0*en

I ma!e many of these mista!es. Let's loo! at this line1by1line.

$. Here we ran our command in the terminal to run the e&$.rb scrit.

. Ruby then tells us that the file e&$.rb has an error on line B.(. It then rints this line for us.

B. Then it uts a ^ 5caret6 character to oint at where the roblem is.

C. :inally, it rints out a "synta& error" and tells us something about what might be the

error. Esually these are *ery crytic, but if you coy that te&t into a search engine,

you will find someone else who's had that error and you can robably figure out how

to fi& it.

(%tra Credit 

+ou will also ha*e 0&tra ;redit. The 0&tra ;redit contains things you should try to do. If you

can't, s!i it and come bac! later.

:or this e&ercise, try these things#

$. )a!e your scrit rint another line.

. )a!e your scrit rint only one of the lines.

(. Put a  5octothore6 character at the beginning of a line. What did it do Try to find

out what this character does.

B. :rom now on, I won't e&lain how each e&ercise wor!s unless an e&ercise is different.

4

Page 9: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 9/128

 Fote

-n 'octothore' is also called a 'ound', 'hash', 'mesh', or any number of names. Pic! the one

that ma!es you chill out.

Exercise #: $o""ents And ound$haracters

;omments are *ery imortant in your rograms. They are used to tell you what something

does in 0nglish, and they also are used to disable arts of your rogram if you need to

remo*e them temorarily. Here's how you use comments in Ruby#

1

3!#<&9

A ,o((entF t/is is so you ,an rea* your progra( later. Anyt/ing a+ter t/e is ignore* by >uby.

puts B= ,oul* /ave ,o*e li)e t/is.B an* t/e ,o((ent a+ter is ignore*

Eou ,an also use a ,o((ent to B*isableB or ,o((ent out a pie,e o+ ,o*e: puts BT/is 8ont run.B

puts BT/is 8ill run.B

What "o# Sho#ld See$ ruby ex.rb= ,oul* /ave ,o*e li)e t/is.T/is 8ill run.

$

(%tra Credit 

$. :ind out if you were right about what the  character does and ma!e sure you !now

what it's called 5octothore or ound character6.

. Ta!e your ex.rb file and re*iew each line going bac!wards. /tart at the last line,

and chec! each word in re*erse against what you should ha*e tyed.

(. id you find more mista!es :i& them.

B. Read what you tyed abo*e out loud, including saying each character by its name.

id you find more mista!es :i& them.

Exercise %: &u"bers And 'ath

0*ery rogramming language has some !ind of way of doing numbers and math. o not

worry, rogrammers lie fre3uently about being math geniuses when they really aren't. If they

were math geniuses, they would be doing math, not writing ads and social networ! games to

steal eole's money.

This e&ercise has lots of math symbols. Let's name them right away so you !now what they

are called. -s you tye this one in, say the names. When saying them feels boring you can

sto saying them. Here are the names#

plus

>

Page 10: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 10/128

- (inusH slas/I asteris)J per,ent less-t/an' greater-t/an

K less-t/an-eual'K greater-t/an-eual

 Fotice how the oerations are missing -fter you tye in the code for this e&ercise, go bac!

and figure out what each of these does and comlete the table. :or e&amle,  does addition.

 1  3 ! # 

 < & 91"111131!1#11<1&19

"13

puts B= 8ill no8 ,ount (y ,/i,)ens:B

puts B7ensBF # 3" H puts B>oostersBF 1"" - # I 3 J !

puts B0o8 = 8ill ,ount t/e eggs:B

puts 3 1 - # ! J - 1 H !

puts B=s it true t/at 3 # - <MB

puts 3 # - <

puts BW/at is 3 MBF 3 puts BW/at is # - <MBF # - <

puts BG/F t/ats 8/y its +alse.B

puts B7o8 about so(e (ore.B

puts B=s it greaterMBF # ' -puts B=s it greater or eualMBF # 'K -puts B=s it less or eualMBF # K -

What "o# Sho#ld See$ ruby ex3.rb= 8ill no8 ,ount (y ,/i,)ens:7ens3">oosters9<0o8 = 8ill ,ount t/e eggs:

<=s it true t/at 3 # - <M+alseW/at is 3 M#W/at is # - <M-G/F t/ats 8/y its +alse.7o8 about so(e (ore.=s it greaterMtrue=s it greater or eualMtrue

=s it less or eualM+alse

$8

Page 11: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 11/128

$

(%tra Credit 

$. -bo*e each line, use the  to write a comment to yourself e&laining what the line

does.

. Remember in 0&ercise 8 when you started IR2 /tart IR2 this way again and usingthe abo*e characters and what you !now, use Ruby as a calculator.

(. :ind something you need to calculate and write a new .rb file that does it.

B. Fotice the math seems "wrong" There are no fractions, only whole numbers. :ind

out why by researching what a "floating oint" number is.

C. Rewrite ex3.rb to use floating oint numbers so it's more accurate 5hint# 8.8 is

floating oint6.

Exercise (: )ariab*es And &a"es

 Fow you can rint things with puts and you can do math. The ne&t ste is to learn about

*ariables. In rogramming a *ariable is nothing more than a name for something so you can

use the name rather than the something as you code. Programmers use these *ariable names

to ma!e their code read more li!e 0nglish, and because they ha*e lousy memories. If they

didn't use good names for things in their software, they'd get lost when they tried to read their

code again.

If you get stuc! with this e&ercise, remember the tric!s you ha*e been taught so far of finding

differences and focusing on details#

$. Write a comment abo*e each line e&laining to yourself what it does in 0nglish.. Read your .rb file bac!wards.

(. Read your .rb file out loud saying e*en the characters.

 1  3 ! #  < & 91"111131!1#

,ars K 1""spa,eNinNaN,ar K !."*rivers K 3"passengers K 9",arsNnotN*riven K ,ars - *rivers,arsN*riven K *rivers,arpoolN,apa,ity K ,arsN*riven I spa,eNinNaN,araverageNpassengersNperN,ar K passengers H ,arsN*riven

puts BT/ere are O,arsP ,ars available.Bputs BT/ere are only O*riversP *rivers available.Bputs BT/ere 8ill be O,arsNnotN*rivenP e(pty ,ars to*ay.Bputs BWe ,an transport O,arpoolN,apa,ityP people to*ay.Bputs BWe /ave OpassengersP passengers to ,arpool to*ay.Bputs BWe nee* to put about OaverageNpassengersNperN,arP in ea,/ ,ar.B

 Fote

$$

Page 12: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 12/128

The N in spa,eNinNaN,ar is called an underscore character. :ind out how to tye it if you do

not already !now. We use this character a lot to ut an imaginary sace between words in

*ariable names.

What "o# Sho#ld See$ ruby ex!.rbT/ere are 1"" ,ars available.T/ere are only 3" *rivers available.T/ere 8ill be <" e(pty ,ars to*ay.We ,an transport 1"." people to*ay.We /ave 9" passengers to ,arpool to*ay.We nee* to put about 3 in ea,/ ,ar.$

(%tra Credit 

When I wrote this rogram the first time I had a mista!e, and Ruby told me about it li!e this#

ex!.rb:&:in Q(ain': un*e+ine* lo,al variable or (et/o*Q,arNpoolN,apa,ity +or (ain:GbRe,t @0a(error

0&lain this error in your own words. )a!e sure you use line numbers and e&lain why.

)ere*s +ore e%tra credit!

$. I used B.8 for spa,eNinNaN,ar, but is that necessary What haens if it's ust B

. Remember that B.8 is a "floating oint" number. :ind out what that means.

(. Write comments abo*e each of the *ariable assignments.

B. )a!e sure you !now what K is called 5e3uals6 and that it's ma!ing names for things.C. Remember N is an underscore character.

D. Try running IR2 as a calculator li!e you did before and use *ariable names to do your

calculations. Poular *ariable names are also i, x, and R.

Exercise +: 'ore )ariab*es And rintin!

 Fow we'll do e*en more tying of *ariables and rinting them out. This time we'll use

something called a "format string". 0*ery time you ut B 5double13uotes6 around a iece of

te&t you ha*e been ma!ing a string. - string is how you ma!e something that your rogram

might gi*e to a human. +ou rint them, sa*e them to files, send them to web ser*ers, all sortsof things.

/trings are really handy, so in this e&ercise you will learn how to ma!e strings that ha*e

*ariables embedded in them. +ou embed *ariables inside a string by using secialiGed format

se3uences and then utting the *ariables at the end with a secial synta& that tells Ruby,

"Hey, this is a format string, ut these *ariables in there."

-s usual, ust tye this in e*en if you do not understand it and ma!e it e&actly the same.

 1

  3

(yNna(e K 6e* A. S/a8

(yNage K 3# not a lie(yN/eig/t K <! in,/es

$

Page 13: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 13/128

 ! #  < & 9

1"111131!1#11<1&

(yN8eig/t K 1&" lbs(yNeyes K lue(yNteet/ K W/ite(yN/air K ro8n

puts BLets tal) about Js.B J (yNna(e

puts B7es J* in,/es tall.B J (yN/eig/tputs B7es J* poun*s /eavy.B J (yN8eig/tputs BA,tually t/ats not too /eavy.Bputs B7es got Js eyes an* Js /air.B J (yNeyesF (yN/airUputs B7is teet/ are usually Js *epen*ing on t/e ,o++ee.B J (yNteet/

t/is line is tri,)yF try to get it exa,tly rig/tputs B=+ = a** J*F J*F an* J* = get J*.B J   (yNageF (yN/eig/tF (yN8eig/tF (yNage (yN/eig/t (yN8eig/tU

What "o# Sho#ld See$ ruby ex#.rb

Lets tal) about 6e* A. S/a8.7es <! in,/es tall.7es 1&" poun*s /eavy.A,tually t/ats not too /eavy.7es got lue eyes an* ro8n /air.7is teet/ are usually W/ite *epen*ing on t/e ,o++ee.=+ = a** 3#F <!F an* 1&" = get &9.$

(%tra Credit 

$. ;hange all the *ariables so there isn't the (yN in front. )a!e sure you change the

name e*erywhere, not ust where you used K to set them.

. Try more format se3uences.(. /earch online for all of the Ruby format se3uences.

B. Try to write some *ariables that con*ert the inches and ounds to centimeters and

!ilos. o not ust tye in the measurements. Wor! out the math in Ruby.

Exercise ,: Strin!s And Text

While you ha*e already been writing strings, you still do not !now what they do. In this

e&ercise we create a bunch of *ariables with comle& strings so you can see what they are

for. :irst an e&lanation of strings.

- string is usually a bit of te&t you want to dislay to someone, or "e&ort" out of the

 rogram you are writing. Ruby !nows you want something to be a string when you ut either

B 5double13uotes6 or  5single13uotes6 around the te&t. +ou saw this many times with your

use of puts when you ut the te&t you want to go to the string inside B or  after the puts.

Then Ruby dislays it.

/trings may contain the format characters you ha*e disco*ered so far. +ou simly ut the

formatted *ariables in the string, and then a J 5ercent6 character, followed by the *ariable.

The only catch is that if you want multile formats in your string to rint multile *ariables,

you need to ut them inside U 5brac!ets6 searated by F 5commas6. It's as if you were

$(

Page 14: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 14/128

telling me to buy you a list of items from the store and you said, "I want mil!, eggs, bread,

and sou." ?nly as a rogrammer we say, "Mmil!, eggs, bread, souN".

-nother way of inecting *ariables into your strings is to use something called "string

interolation", which uses the O P 5ound and curly brace6 characters. /o, instead of using

format strings#

na(e1 K BVoeBna(e K BaryBputs B7ello JsF 8/ere is JsMB J na(e1F na(eU

We can tye#

na(e1 K BVoeBna(e K BaryBputs B7ello Ona(e1PF 8/ere is Ona(ePMB

We will now tye in a whole bunch of strings, *ariables, formats, and rint them. +ou willalso ractice using short abbre*iated *ariable names. Programmers lo*e sa*ing themsel*es

time at your e&ense by using annoying crytic *ariable names, so let's get you started being

able to read and write them early on.

 1  3 ! #  <

 & 91"111131!1#11<1&19"

x K BT/ere are O1"P types o+ people.Bbinary K BbinaryB*oNnot K B*ontBy K BT/ose 8/o )no8 ObinaryP an* t/ose 8/o O*oNnotP.B

puts xputs y

puts B= sai*: OxP.Bputs B= also sai*: OyP.B

/ilarious K +alseRo)eNevaluation K B=snt t/at Ro)e so +unnyMC O/ilariousPB

puts Ro)eNevaluation

8 K BT/is is t/e le+t si*e o+...Be K Ba string 8it/ a rig/t si*e.B

puts 8 e

What "o# Sho#ld SeeT/ere are 1" types o+ people.T/ose 8/o )no8 binary an* t/ose 8/o *ont.= sai*: T/ere are 1" types o+ people..= also sai*: T/ose 8/o )no8 binary an* t/ose 8/o *ont..=snt t/at Ro)e so +unnyMC +alseT/is is t/e le+t si*e o+...a string 8it/ a rig/t si*e.

(%tra Credit 

$. %o through this rogram and write a comment abo*e each line e&laining it.

. :ind all the laces where a string is ut inside a string. There are four laces.(. -re you sure there's only four laces How do you !now )aybe I li!e lying.

$B

Page 15: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 15/128

B. 0&lain why adding the two strings 8 and e with  ma!es a longer string.

Exercise -: 'ore rintin!

 Fow we are going to do a bunch of e&ercises where you ust tye code in and ma!e it run. Iwon't be e&laining much since it is ust more of the same. The urose is to build u your

chos. /ee you in a few e&ercises, and do not s!iO o not asteO

 1  3 ! #  < &

 91"111131!1#11<1&19"1

3!#

puts Bary /a* a little la(b.Bputs B=ts +lee,e 8as 8/ite as Js.B J sno8puts BAn* every8/ere t/at ary 8ent.Bputs B.B I 1" 8/at* t/at *oM

en*1 K B2Ben* K B/Ben*3 K BeB

en*! K BeBen*# K BsBen* K BeBen*< K BBen*& K BuBen*9 K BrBen*1" K BgBen*11 K BeBen*1 K BrB

noti,e /o8 8e are using print instea* o+ puts /ere. ,/ange it to puts an* see 8/at /appens.print en*1 en* en*3 en*! en*# en*

print en*< en*& en*9 en*1" en*11 en*1

t/is Rust is polite use o+ t/e ter(inalF try re(oving itputs

What "o# Sho#ld See$ ruby ex<.rbary /a* a little la(b.=ts +lee,e 8as 8/ite as sno8.An* every8/ere t/at ary 8ent...........2/eeseurger$

(%tra Credit 

:or these ne&t few e&ercises, you will ha*e the e&act same e&tra credit.

$. %o bac! through and write a comment on what each line does.

. Read each one bac!wards or out loud to find your errors.

(. :rom now on, when you ma!e mista!es write down on a iece of aer what !ind of

mista!e you made.

B. When you go to the ne&t e&ercise, loo! at the last mista!es you made and try not to

ma!e them in this new one.

$C

Page 16: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 16/128

C. Remember that e*eryone ma!es mista!es. Programmers are li!e magicians who li!e

e*eryone to thin! they are erfect and ne*er wrong, but it's all an act. They ma!e

mista!es all the time.

Exercise .: rintin!/ rintin! 1  3 ! #  < & 91"11

1

+or(atter K BJs Js Js JsB

puts +or(atter J 1F F 3F !Uputs +or(atter J BoneBF Bt8oBF Bt/reeBF B+ourBUputs +or(atter J trueF +alseF +alseF trueUputs +or(atter J +or(atterF +or(atterF +or(atterF +or(atterUputs +or(atter J   B= /a* t/is t/ing.BF  BT/at you ,oul* type up rig/t.BF  But it *i*nt sing.BF  BSo = sai* goo*nig/t.B

U

What "o# Sho#ld See$ ruby ex&.rb1 3 !one t8o t/ree +ourtrue +alse +alse trueJs Js Js Js Js Js Js Js Js Js Js Js Js Js Js Js= /a* t/is t/ing. T/at you ,oul* type up rig/t. ut it *i*nt sing. So =sai* goo*nig/t.$

(%tra Credit $. o your chec!s of your wor!, write down your mista!es, try not to ma!e them on the

ne&t e&ercise.

Exercise : rintin!/ rintin!/ rintin!

 1  3 !

 #  < & 91"111131!

7eres so(e ne8 strange stu++F re(e(ber type it exa,tly.

*ays K Bon Tue We* T/u ?ri Sat SunB(ont/s K BVan5n?eb5nar5nApr5nay5nVun5nVul5nAugB

puts B7ere are t/e *ays: BF *aysputs B7ere are t/e (ont/s: BF (ont/s

puts A>AX>A7T/eres so(et/ing going on /ere.Wit/ t/e A>AX>A7 t/ingWell be able to type as (u,/ as 8e li)e.ven ! lines i+ 8e 8antF or #F or .A>AX>A7

What "o# Sho#ld See

$ ruby ex9.rb7ere are t/e *ays:on Tue We* T/u ?ri Sat Sun

$D

Page 17: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 17/128

7ere are t/e (ont/s:Van?ebarApray

VunVulAugT/eres so(et/ing going on /ere.Wit/ t/e A>AX>A7 t/ingWell be able to type as (u,/ as 8e li)e.ven ! lines i+ 8e 8antF or #F or .

(%tra Credit 

o your chec!s of your wor!, write down your mista!es, try not to ma!e them on the ne&t

e&ercise.

Exercise 10: What Was That

In 0&ercise > I threw you some new stuff, ust to !ee you on your toes. I showed you two

ways to ma!e a string that goes across multile lines. In the first way, I ut the characters 5n 

5bac!1slash n6 between the names of the months. What these two characters do is ut a new

line character into the string at that oint.

This use of the 5 5bac!1slash6 character is a way we can ut difficult1to1tye characters into a

string. There are lenty of these "escae se3uences" a*ailable for different characters you

might want to ut in, but there's a secial one, the double bac!1slash which is ust two ofthem 55. These two characters will rint ust one bac!1slash. We'll try a few of these

se3uences so you can see what I mean.

-nother imortant escae se3uence is to escae a single13uote  or double13uote B. Imagine

you ha*e a string that uses double13uotes and you want to ut a double13uote in for the

outut. If you do this B= Bun*erstan*B Roe.B then Ruby will get confused since it will

thin! the B around Bun*erstan*B actually ends the string. +ou need a way to tell Ruby that

the B inside the string isn't a real double13uote.

To sol*e this roblem you escae double13uotes and single13uotes so Ruby !nows to includein the string. Here's an e&amle#

B= a( 5B tall.B es,ape *ouble-uote insi*e string= a( 5B tall. es,ape single-uote insi*e string

The second way is by using here document synta&, which uses 0A and wor!s li!e a

string, but you also can ut as many lines of te&t you as want until you tye 0A again. We'll

also lay with these.

 1  3 !

tabbyN,at K B5t=( tabbe* in.BpersianN,at K B=( split5non a line.Bba,)slas/N,at K B=( 55 a 55 ,at.B

$

Page 18: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 18/128

 #  < & 91"

111131!1#

+atN,at K EN7>DG2=ll *o a list:5tI 2at +oo*5tI ?is/ies5tI 2atnip5n5tI XrassEN7>DG2

puts tabbyN,atputs persianN,atputs ba,)slas/N,atputs +atN,at

What "o# Sho#ld See

Loo! for the tab characters that you made. In this e&ercise the sacing is imortant to get

right.

$ ruby ex1".rb

  =( tabbe* in.=( spliton a line.=( 5 a 5 ,at.=ll *o a list:  I 2at +oo*  I ?is/ies  I 2atnip  I Xrass

$

(%tra Credit $. /earch online to see what other escae se3uences are a*ailable.

. ;ombine escae se3uences and format strings to create a more comle& format.

Exercise 11: As2in! 3uestions

 Fow it is time to ic! u the ace. I ha*e got you doing a lot of rinting so that you get used

to tying simle things, but those simle things are fairly boring. What we want to do now is

get data into your rograms. This is a little tric!y because you ha*e learn to do two things

that may not ma!e sense right away, but trust me and do it anyway. It will ma!e sense in a

few e&ercises.

)ost of what software does is the following#

$. Ta!e some !ind of inut from a erson.

. ;hange it.

(. Print out something to show how it changed.

/o far you ha*e only been rinting, but you ha*en't been able to get any inut from a erson,

or change it. +ou may not e*en !now what "inut" means, so rather than tal! about it, let's

ha*e you do some and see if you get it. Fe&t e&ercise we'll do more to e&lain it.

1 print B7o8 ol* are youM B

$4

Page 19: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 19/128

3!#<

&

age K gets.,/o(p@print B7o8 tall are youM B/eig/t K gets.,/o(p@print B7o8 (u,/ *o you 8eig/M B8eig/t K gets.,/o(p@

puts BSoF youre OageP years ol*F O/eig/tP tall an* O8eig/tP /eavy.B

 Fote

 Fotice that we are using print instead of puts to do the romting. print doesn't add a new

line automatically, so your answer can go on the same line as the 3uestion. puts on the other

hand, adds a newline automatically.

What "o# Sho#ld See$ ruby ex11.rb7o8 ol* are youM 3#

7o8 tall are youM B7o8 (u,/ *o you 8eig/M 1&"lbsSoF youre 3# ol*F B tall an* 1&"lbs /eavy.$

(%tra Credit 

$. %o online and find out what Rubys gets and ,/o(p methods do.

. ;an you find other ways to use gets.,/o(p Try some of the samles you find.

(. Write another "form" li!e this to as! some other 3uestions.

Exercise 1#: LibrariesTa!e a loo! at this code#

 1  3 ! #  < & 91"

reuire open-uri

open@B/ttp:HH888.ruby-lang.orgHenB *o Y+Y  +.ea,/Nline OYlineY p lineP  puts +.baseNuri >=::7TT:"x!"ee+ >L:/ttp:HH888.ruby-lang.orgHenH'  puts +.,ontentNtype BtextH/t(lB  puts +.,/arset Biso-&&#9-1B

  puts +.,ontentNen,o*ing U  puts +.lastN(o*i+ie* T/u De, "# ":!#:" T2 ""en*

?n line $ we ha*e what's called a "re3uire". This is how you add features to your scrit from

the Ruby feature set or other sources 5e.g., Ruby %ems, stuff you wrote yourself6. Rather than

gi*e you all the features at once, Ruby as!s you to say what you lan to use. This !ees your

 rograms small, but it also acts as documentation for other rogrammers who read your code

later.

$>

Page 20: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 20/128

)old ,p &eat#res )a.e Another Na+e

I call them "features" here 5these little things you re3uire to ma!e your Ruby rogram do

more6 but nobody else calls them features. I ust used that name because I needed to tric! you

into learning what they are without argon. 2efore you can continue, you need to learn their

real name# libraries.

:rom now on we will be calling these "features" that we re3uire libraries. I'll say things

li!e, "+ou want to re3uire the open-uri library." They are also called "modules" by other

 rogrammers, but let's ust stic! with libraries.

(%tra Credit 

$. Research the difference between reuire and in,lu*e. How are they different

. ;an you reuire a scrit that doesn't contain a library secifically

(. :igure out which directories on your system Ruby will loo! in to find the libraries you

re3uire.

Exercise 1%: ara"eters/ 4npac2in!/

)ariab*es

In this e&ercise we will co*er one more inut method you can use to ass *ariables to a scrit

5scrit being another name for your .rb files6. +ou !now how you tye ruby ex13.rb to run

the ex13.rb file Well the ex13.rb art of the command is called an "argument". What we'll

do now is write a scrit that also accets arguments.

Tye this rogram and I'll e&lain it in detail#

13!#

+irstF se,on*F t/ir* K A>X;

puts BT/e s,ript is ,alle*: O$"PBputs BEour +irst variable is: O+irstPBputs BEour se,on* variable is: Ose,on*PBputs BEour t/ir* variable is: Ot/ir*PB

The A>X; is the "argument *ariable", a *ery standard name in rogramming, that you will

find used in many other languages. It's in all cas because it's a constant, meaning youshouldn't change the *alue once it's been assigned. This *ariable holds the arguments you

 ass to your Ruby scrit when you run it. In the e&ercises you will get to lay with this more

and see what haens.

Line $ "unac!s" A>X; so that, rather than holding all the arguments, it gets assigned to three

*ariables you can wor! with# +irst, se,on*, and t/ir*. The name of the scrit itself is

stored in a secial *ariable $", which we don't need to unac!. This may loo! strange, but

"unac!" is robably the best word to describe what it does. It ust says, "Ta!e whate*er is in

A>X;, unac! it, and assign it to all of these *ariables on the left in order."

-fter that we ust rint them out li!e normal.

8

Page 21: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 21/128

What "o# Sho#ld See

Run the rogram li!e this#

ruby ex13.rb +irst n* 3r*

This is what you should see when you do a few different runs with different arguments#

$ ruby ex13.rb +irst n* 3r*T/e s,ript is ,alle*: ex13.rbEour +irst variable is: +irstEour se,on* variable is: n*Eour t/ir* variable is: 3r*

$ ruby ex13.rb ,/eese apples brea*T/e s,ript is ,alle*: ex13.rbEour +irst variable is: ,/eeseEour se,on* variable is: applesEour t/ir* variable is: brea*

$ ruby ex13.rb 6e* A. S/a8T/e s,ript is ,alle*: ex13.rbEour +irst variable is: 6e*Eour se,on* variable is: A.Eour t/ir* variable is: S/a8

+ou can actually relace "first", "nd", and "(rd" with any three things. +ou do not ha*e to

gi*e these arameters either, you can gi*e any ( strings you want#

ruby ex13.rb stu++ = li)e

ruby ex13.rb anyt/ing <

(%tra Credit 

$. Try gi*ing fewer than three arguments to your scrit. What *alues are used for the

missing arguments

. Write a scrit that has fewer arguments and one that has more. )a!e sure you gi*e

the unac!ed *ariables good names.

(. ;ombine STD=0.gets.,/o(p@  with A>X; to ma!e a scrit that gets more inut from

a user.

Exercise 1(: ro"ptin! And assin!Let's do one e&ercise that uses A>X; and gets.,/o(p@ together to as! the user something

secific. +ou will need this for the ne&t e&ercise where we learn to read and write files. In

this e&ercise we'll rint a simle ' romt. This is similar to a game li!e =or! or -d*enture.

 1  3 ! #

  <

user K A>X;.+irstpro(pt K '

puts B7i OuserPF =( t/e O$"P s,ript.Bputs B=* li)e to as) you a +e8 uestions.B

puts BDo you li)e (e OuserPMBprint pro(pt

$

Page 22: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 22/128

 & 91"11113

1!1#11<1&19"1

li)es K STD=0.gets.,/o(p@

puts BW/ere *o you live OuserPMBprint pro(ptlives K STD=0.gets.,/o(p@

puts BW/at )in* o+ ,o(puter *o you /aveMBprint pro(pt,o(puter K STD=0.gets.,/o(p@

puts SSAXAlrig/tF so you sai* Oli)esP about li)ing (e.Eou live in OlivesP. 0ot sure 8/ere t/at is.An* you /ave a O,o(puterP ,o(puter. 0i,e.SSAX

I"portant: -lso notice that we're using STD=0.gets instead of lain 'ol gets. That is

 because if there is stuff in A>X;, the default gets method tries to treat the first one as a file

and read from that. To read from the user's inut 5i.e., st*in6 in such a situation, you ha*e touse it STD=0.gets e&licitly.

What "o# Sho#ld See

When you run this, remember that you ha*e to gi*e the scrit your name for the A>X; 

arguments.

$ ruby ex1!.rb 6e*7i 6e*F =( t/e exHex1!.rb s,ript.=* li)e to as) you a +e8 uestions.

Do you li)e (e 6e*M' EesW/ere *o you live 6e*M' A(eri,aW/at )in* o+ ,o(puter *o you /aveM' Tan*yAlrig/tF so you sai* Ees about li)ing (e.Eou live in A(eri,a. 0ot sure 8/ere t/at is.An* you /ave a Tan*y ,o(puter. 0i,e.

(%tra Credit 

$. :ind out what =or! and -d*enture were. Try to find a coy and lay it.

. ;hange the pro(pt *ariable to something else entirely.(. -dd another argument and use it in your scrit.

B. )a!e sure you understand how I combined a SGT7=0X style multi1line string

with O P string interolation as the last rint.

Exercise 1+: Readin! Fi*es

0*erything you'*e learned about STD=0.gets and A>X; is so you can start reading files. +ou

may ha*e to lay with this e&ercise the most to understand what's going on, so do it carefully

and remember your chec!s. Wor!ing with files is an easy way to erase your wor! if you are

not careful.

Page 23: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 23/128

This e&ercise in*ol*es writing two files. ?ne is your usual ex1#.rb file that you will run, but

the other is named ex1#Nsa(ple.txt. This second file isn't a scrit but a lain te&t file we'll

 be reading in our scrit. Here are the contents of that file#

T/is is stu++ = type* into a +ile.

=t is really ,ool stu++.Lots an* lots o+ +un to /ave in /ere.

What we want to do is "oen" that file in our scrit and rint it out. Howe*er, we do not want

to ust "hard code" the name ex1#Nsa(ple.txt into our scrit. "Hard coding" means utting

some bit of information that should come from the user as a string right in our rogram.

That's bad because we want it to load other files later. The solution is to use A>X; and

STD=0.gets to as! the user what file they want instead of "hard coding" the file's name.

 1  3 ! #  < & 91"111131!1#

+ilena(e K A>X;.+irst

pro(pt K B' Btxt K ?ile.open@+ilena(e

puts B7eres your +ile: O+ilena(ePBputs txt.rea*@

puts B=ll also as) you to type it again:Bprint pro(pt+ileNagain K STD=0.gets.,/o(p@

txtNagain K ?ile.open@+ileNagain

puts txtNagain.rea*@

- few fancy things are going on in this file, so let's brea! it down real 3uic!#

Line $1( should be a familiar use of A>X; to get a filename and setting u the romt. Fe&t

we ha*e line B where we use a new command ?ile.open. Right now, run ri ?ile.open 

from the command line and read the instructions. Fotice how li!e your own scrits, it ta!es a

 arameter and returns a *alue you can set to your own *ariable. +ou ust oened a file.

Line D we rint a little line, but on line we ha*e something *ery new and e&citing. We call a

function on txt. What you got bac! from open is a +ile, and it's also got commands you can

gi*e it. +ou gi*e a file a command by using the . 5dot or eriod6, the name of the command,

and arameters. <ust li!e with ?ile.open. The difference is that when you say txt.rea*@ you are saying, "Hey t&tO o your read command with no arametersO"

The remainder of the file is more of the same, but we'll lea*e the analysis to you in the e&tra

credit.

What "o# Sho#ld See

I made a file called "e&$Csamle.t&t" and ran my scrit.

$ ruby ex1#.rb ex1#Nsa(ple.txt

7eres your +ile ex1#Nsa(ple.txt:T/is is stu++ = type* into a +ile.

(

Page 24: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 24/128

=t is really ,ool stu++.Lots an* lots o+ +un to /ave in /ere.

=ll also as) you to type it again:' ex1#Nsa(ple.txtT/is is stu++ = type* into a +ile.

=t is really ,ool stu++.Lots an* lots o+ +un to /ave in /ere.

$

(%tra Credit 

This is a big um so be sure you do this e&tra credit as best you can before mo*ing on.

$. -bo*e each line write out in 0nglish what that line does.

. If you are not sure as! someone for hel or search online. )any times searching for

"ruby THIF%" will find answers for what that THIF% does in Ruby. Try searching

for "ruby file.oen".

(. I used the name "commands" here, but they are also called "functions" and "methods".

/earch around online to see what other eole do to define these. o not worry if they

confuse you. It's normal for a rogrammer to confuse you with their *ast e&tensi*e

!nowledge.

B. %et rid of the art from line >1$C where you use STD=0.gets and try the scrit then.

C. Ese only STD=0.gets and try the scrit that way. Thin! of why one way of getting

the filename would be better than another.

D. Run ri ?ile and scroll down until you see the rea*@ command 5methodAfunction6.

/ee all the other ones you can use Try some of the other commands.

. /tartu IR2 again and use ?ile.open from the romt. Fotice how you can oenfiles and run read on them right there

4. Ha*e your scrit also do a ,lose@ on the txt and txtNagain *ariables. It's

imortant to close files when you are done with them.

Exercise 1,: Readin! And Writin! Fi*es

If you did the e&tra credit from the last e&ercise you should ha*e seen all sorts of commands

5methodsAfunctions6 you can gi*e to files. Here's the list of commands I want you to

remember#

• close 11 ;loses the file. Li!e ?ile-'Save.. in your editor.

• read 11 Reads the contents of the file, you can assign the result to a *ariable.

• readline 11 Reads ust one line of a te&t file.

• truncate 11 0mties the file, watch out if you care about the file.

• write5stuff6 11 Writes stuff to the file.

:or now these are the imortant commands you need to !now. /ome of them ta!e

 arameters, but we do not really care about that. +ou only need to remember that write ta!es

a arameter of a string you want to write to the file.

Let's use some of this to ma!e a simle little te&t editor#

B

Page 25: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 25/128

 1  3 ! # 

 < & 91"111131!1#11<1&19

"13!#<&93"313

33

+ilena(e K A>X;.+irsts,ript K $"

puts BWere going to erase O+ilena(eP.Bputs B=+ you *ont 8ant t/atF /it 2T>L-2 @^2.Bputs B=+ you *o 8ant t/atF /it >T>0.B

print BM BSTD=0.gets

puts BGpening t/e +ile...Btarget K ?ile.open@+ilena(eF 8

puts BTrun,ating t/e +ile. Xoo*byeCBtarget.trun,[email protected]

puts B0o8 =( going to as) you +or t/ree lines.B

print Bline 1: B[ line1 K STD=0.gets.,/o(p@

print Bline : B[ line K STD=0.gets.,/o(p@print Bline 3: B[ line3 K STD=0.gets.,/o(p@

puts B=( going to 8rite t/ese to t/e +ile.B

[email protected]@[email protected]@[email protected]@B5nB

puts BAn* +inallyF 8e ,lose it.B

target.,lose@

Warnin!

If you get errors in this scrit it is robably because you are using Ruby $.4 and the boo!

assumes Ruby $.>. To see what *ersion you ha*e tye# ruby -v If you need to install a newer

*ersion then go bac! to the beginning of the boo! where 0&ercise 8 tells you how.

That's a large file, robably the largest you ha*e tyed in. /o go slow, do your chec!s, and

ma!e it run. ?ne tric! is to get bits of it running at a time. %et lines $14 running, then C more,

then a few more, etc., until it's all done and running.

What "o# Sho#ld See

There are actually two things you will see, first the outut of your new scrit#

$ ruby ex1.rb test.txtWere going to erase test.txt.=+ you *ont 8ant t/atF /it 2T>L-2 @^2.=+ you *o 8ant t/atF /it >T>0.MGpening t/e +ile...Trun,ating t/e +ile. Xoo*byeC

0o8 =( going to as) you +or t/ree lines.line 1: To all t/e people out t/ere.

C

Page 26: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 26/128

line : = say = *ont li)e (y /air.line 3: = nee* to s/ave it o++.=( going to 8rite t/ese to t/e +ile.An* +inallyF 8e ,lose it.$

 Fow, oen u the file you made 5in my case test.t&t6 in your editor and chec! it out. Featright

(%tra Credit 

$. If you feel you do not understand this, go bac! through and use the comment tric! to

get it s3uared away in your mind. ?ne simle 0nglish comment abo*e each line will

hel you understand, or at least let you !now what you need to research more.

. Write a scrit similar to the last e&ercise that uses read and arg* to read the file you

 ust created.

(. There's too much reetition in this file. Ese strings, formats, and escaes to rint out

line$, line, and line( with ust one target.8rite@ command instead of D.B. :ind out why we had to ass a 8 as an e&tra arameter to oen. Hint# oen tries to

 be safe by ma!ing you e&licitly say you want to write a file.

C. If you oen the file with 8 mode, then do you really need the target.trun,ate@

%o read the docs for Ruby's ?ile.open function and see if that's true.

Exercise 1-: 'ore Fi*es

 Fow let's do a few more things with files. We're going to actually write a Ruby scrit to coy

one file to another. It'll be *ery short but will gi*e you some ideas about other things you can

do with files.

 1  3 ! #  < & 91"111131!1#11<1&19"1

+ro(N+ileF toN+ile K A>X;s,ript K $"

puts B2opying +ro( O+ro(N+ileP to OtoN+ilePB

8e ,oul* *o t/ese t8o on one line tooF /o8Minput K ?ile.open@+ro(N+ilein*ata K input.rea*@

puts BT/e input +ile is Oin*ata.lengt/P bytes longB

puts BDoes t/e output +ile existM O?ile.existsM toN+ilePBputs B>ea*yF /it >T>0 to ,ontinueF 2T>L-2 to abort.BSTD=0.gets

output K ?ile.open@toN+ileF 8output.8rite@in*ata

puts BAlrig/tF all *one.B

output.,lose@input.,lose@

D

Page 27: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 27/128

Here we used a new method called ?ile.existsM. This returns true if a file e&ists, based on

its name in a string as an argument. It returns 5a*se if not. We'll be using this function in the

second half of this boo! to do lots of things.

What "o# Sho#ld See

<ust li!e your other scrits, run this one with two arguments, the file to coy from and the file

to coy it to. If we use your test.txt file from before we get this#

$ ruby ex1<.rb test.txt ,opie*.txt2opying +ro( test.txt to ,opie*.txtT/e input +ile is &1 bytes longDoes t/e output +ile existM ?alse>ea*yF /it >T>0 to ,ontinueF 2T>L-2 to abort.

Alrig/tF all *one.

$ ,at ,opie*.txtTo all t/e people out t/ere.= say = *ont li)e (y /air.= nee* to s/ave it o++.$

It should wor! with any file. Try a bunch more and see what haens. <ust be careful you do

not blast an imortant file.

Warnin!

id you see that tric! I did with ,at It only wor!s on Linu& or ?/K, on Windows use type 

to do the same thing.

(%tra Credit 

$. %o read u on Ruby's reuire statement, and start Ruby to try it out. Try imorting

some things and see if you can get it right. It's alright if you do not.

. This scrit is really annoying. There's no need to as! you before doing the coy, and it

 rints too much out to the screen. Try to ma!e it more friendly to use by remo*ing

features.

(. /ee how short you can ma!e the scrit. I could ma!e this $ line long.

B. Fotice at the end of the W+// I used something called ,at It's an old command that

"conQcatQenates" files together, but mostly it's ust an easy way to rint a file to thescreen. Tye (an ,at to read about it.

C. Windows eole, find the alternati*e to ,at that Linu&A?/K eole ha*e. o not

worry about (an since there is nothing li!e that.

D. :ind out why you had to do output.,lose@ in the code.

Exercise 1.: &a"es/ )ariab*es/ $ode/

Functions

Page 28: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 28/128

2ig title right I am about to introduce you to the functionO um dum dahO 0*ery

 rogrammer will go on and on about functions and all the different ideas about how they

wor! and what they do, but I will gi*e you the simlest e&lanation you can use right now.

:unctions do three things#

$. They name ieces of code the way *ariables name strings and numbers.

. They ta!e arguments the way your scrits ta!e A>X;.

(. Esing $ and they let you ma!e your own "mini scrits" or "tiny commands".

+ou can create a function 5also called "methods"6 by using the word *e+ in Ruby. I'm going

to ha*e you ma!e four different functions that wor! li!e your scrits, and then show you how

each one is related.

 1 

 3 ! #  < & 91"111131!1#

11<1&19"13!#

t/is one is li)e your s,ripts 8it/ argv*e+ putsNt8o@Iargs

  arg1F arg K args  puts Barg1: Oarg1PF arg: OargPBen*

o)F t/at Iargs is a,tually pointlessF 8e ,an Rust *o t/is*e+ putsNt8oNagain@arg1F arg  puts Barg1: Oarg1PF arg: OargPBen*

t/is Rust ta)es one argu(ent*e+ putsNone@arg1  puts Barg1: Oarg1PBen*

t/is one ta)es no argu(ents*e+ putsNnone@  puts B= got not/in.Ben*

putsNt8o@B6e*BFBS/a8BputsNt8oNagain@B6e*BFBS/a8BputsNone@B?irstCBputsNnone@

Let's brea! down the first function, putsNt8o which is the most similar to what you already

!now from ma!ing scrits#

$. :irst we tell Ruby we want to ma!e a function using *e+ for "define".

. ?n the same line as *e+ we then gi*e the function a name, in this case we ust called it

"utstwo" but it could be "eanuts" too. It doesn't matter, e&cet that your function

should ha*e a short name that says what it does.

(. Then we tell it we want Iargs 5asteris! args6 which is a lot li!e your A>X; arameter

 but for functions.

B. -fter the definition, all the lines that are indented saces will become attached to

this name, putsNt8o. ?ur first indented line is one that unac!s the arguments the

same as with your scrits.

C. To demonstrate how it wor!s we rint these arguments out, ust li!e we would in ascrit. Fow, the roblem with putsNt8o is that it's not the easiest way to ma!e a

4

Page 29: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 29/128

function. In Ruby we can s!i the whole unac!ing args and ust use the names we

want right inside @. That's what putsNt8oNagain does.

-fter that you ha*e an e&amle of how you ma!e a function that ta!es one argument in

putsNone.

:inally you ha*e a function that has no arguments in putsNnone.

Warnin!

This is *ery imortant. o not get discouraged right now if this doesn't 3uite ma!e sense.

We're going to do a few e&ercises lin!ing functions to your scrits and show you how to

ma!e more. :or now ust !ee thin!ing "mini scrit" when I say "function" and !ee laying

with them.

What "o# Sho#ld SeeIf you run the abo*e scrit you should see#

$ ruby ex1&.rbarg1: 6e*F arg: S/a8arg1: 6e*F arg: S/a8arg1: ?irstC= got not/in.$

Right away you can see how a function wor!s. Fotice that you used your functions the way

you use things li!e ?ile.existsM, ?ile.open, and other "commands". In fact, I'*e beentric!ing you because in Ruby those "commands" are ust functions. This means you can ma!e

your own commands and use them in your scrits too.

(%tra Credit 

Write out a function chec!list for later e&ercises. Write these on an inde& card and !ee it by

you while you comlete the rest of these e&ercises or until you feel you do not need it#

$. id you start your function definition with *e+

. oes your function name ha*e only characters and N 5underscore6 characters

(. id you ut an oen arenthesis @ right after the function name

B. id you ut your arguments after the arenthesis @ searated by commas

C. id you ma!e each argument uni3ue 5meaning no dulicated names6.

D. id you ut a close arenthesis  after the arguments

. id you indent all lines of code you want in the function saces

4. id you close your function body by tying "end"

-nd when you run 5a!a "use" or "call"6 a function, chec! these things#

$. id you callAuseArun this function by tying its name

. id you ut @ character after the name to run it 5this isn't re3uired, but is idiomatic6(. id you ut the *alues you want into the arenthesis searated by commas

>

Page 30: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 30/128

B. id you end the function call with a  character.

Ese these two chec!lists on the remaining lessons until you do not need them anymore.

:inally, reeat this a few times#

"To 'run', 'call', or 'use' a function all mean the same thing."

Exercise 1: Functions And )ariab*es

:unctions may ha*e been a mind1blowing amount of information, but do not worry. <ust !ee

doing these e&ercises and going through your chec!list from the last e&ercise and you will

e*entually get it.

There is one tiny oint though that you might not ha*e realiGed which we'll reinforce right

now# The *ariables in your function are not connected to the *ariables in your scrit. Here's

an e&ercise to get you thin!ing about this#

 1  3 ! #  < & 9

1"111131!1#11<1&19"1

*e+ ,/eeseNan*N,ra,)ers@,/eeseN,ountF boxesNo+N,ra,)ers  puts BEou /ave O,/eeseN,ountP ,/eesesCB  puts BEou /ave OboxesNo+N,ra,)ersP boxes o+ ,ra,)ersCB  puts Ban t/ats enoug/ +or a partyCB  puts BXet a blan)et.B  puts a blan) lineen*

puts BWe ,an Rust give t/e +un,tion nu(bers *ire,tly:B

,/eeseNan*N,ra,)ers@"F 3"

puts BG>F 8e ,an use variables +ro( our s,ript:Ba(ountNo+N,/eese K 1"a(ountNo+N,ra,)ers K #",/eeseNan*N,ra,)ers@a(ountNo+N,/eeseF a(ountNo+N,ra,)ers

puts BWe ,an even *o (at/ insi*e too:B,/eeseNan*N,ra,)ers@1" "F #

puts BAn* 8e ,an ,o(bine t/e t8oF variables an* (at/:B,/eeseNan*N,ra,)ers@a(ountNo+N,/eese 1""F a(ountNo+N,ra,)ers 1"""

This shows all different ways we're able to gi*e our function ,/eeseNan*N,ra,)ers the*alues it needs to rint them. We can gi*e it straight numbers. We can gi*e it *ariables. We

can gi*e it math. We can e*en combine math and *ariables.

In a way, the arguments to a function are !ind of li!e our K character when we ma!e a

*ariable. In fact, if you can use K to name something, you can usually ass it to a function as

an argument.

What "o# Sho#ld See

+ou should study the outut of this scrit and comare it with what you thin! you should getfor each of the e&amles in the scrit.

(8

Page 31: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 31/128

$ ruby ex19.rbWe ,an Rust give t/e +un,tion nu(bers *ire,tly:Eou /ave " ,/eesesCEou /ave 3" boxes o+ ,ra,)ersCan t/ats enoug/ +or a partyCXet a blan)et.

G>F 8e ,an use variables +ro( our s,ript:Eou /ave 1" ,/eesesCEou /ave #" boxes o+ ,ra,)ersCan t/ats enoug/ +or a partyCXet a blan)et.

We ,an even *o (at/ insi*e too:Eou /ave 3" ,/eesesCEou /ave 11 boxes o+ ,ra,)ersCan t/ats enoug/ +or a partyCXet a blan)et.

An* 8e ,an ,o(bine t/e t8oF variables an* (at/:Eou /ave 11" ,/eesesCEou /ave 1"#" boxes o+ ,ra,)ersCan t/ats enoug/ +or a partyCXet a blan)et.$

(%tra Credit 

$. %o bac! through the scrit and tye a comment abo*e each line e&laining in 0nglish

what it does.

. /tart at the bottom and read each line bac!wards, saying all the imortant characters.

(. Write at least one more function of your own design, and run it $8 different ways.

Exercise #0: Functions And Fi*esRemember your chec!list for functions, then do this e&ercise aying close attention to how

functions and files can wor! together to ma!e useful stuff.

 1  3 ! #  < & 91"

inputN+ile K A>X;"U

*e+ printNall@+  puts +.rea*@en*

*e+ re8in*@+  +.see)@"F =G::S\NSTen*

($

Page 32: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 32/128

111131!1#1

1<1&19"13!#<&9

3"313333!3#

*e+ printNaNline@lineN,ountF +  puts BOlineN,ountP O+.rea*line@PBen*

,urrentN+ile K ?ile.open@inputN+ile

puts B?irst lets print t/e 8/ole +ile:Bputs a blan) line

printNall@,urrentN+ile

puts B0o8 lets re8in*F )in* o+ li)e a tape.B

re8in*@,urrentN+ile

puts BLets print t/ree lines:B

,urrentNline K 1printNaNline@,urrentNlineF ,urrentN+ile

,urrentNline K ,urrentNline 1printNaNline@,urrentNlineF ,urrentN+ile

,urrentNline K ,urrentNline 1printNaNline@,urrentNlineF ,urrentN+ile

Pay close attention to how we ass in the current line number each time we run

printNaNline.

What "o# Sho#ld See$ ruby ex".rb test.txt?irst lets print t/e 8/ole +ile:

To all t/e people out t/ere.= say = *ont li)e (y /air.= nee* to s/ave it o++.

0o8 lets re8in*F )in* o+ li)e a tape.Lets print t/ree lines:1 To all t/e people out t/ere. = say = *ont li)e (y /air.3 = nee* to s/ave it o++.

$

(%tra Credit 

$. %o through and write 0nglish comments for each line to understand what's going on.

. 0ach time printNaNline is run you are assing in a *ariable ,urrentNline. Write

out what ,urrentNline is e3ual to on each function call, and trace how it becomes

lineN,ount in printNaNline.

(. :ind each lace a function is used, and go chec! its def to ma!e sure that you are

gi*ing it the right arguments.

B. Research online what the see) function for file does. Loo! at the r*o, documentation

using the ri command and see if you can figure it out from there.

C. Research the shorthand notation K and rewrite the scrit to use that.

(

Page 33: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 33/128

Exercise #1: Functions $an Return

So"ethin!

+ou ha*e been using the K character to name *ariables and set them to numbers or strings.We're now going to blow your mind again by showing you how to use K to set *ariables to be

a *alue from a function. There will be one thing to ay close attention to, but first tye this in#

 1  3 ! #  < &

 91"111131!1#11<1&19"1

3!#<&93"313333!

3#

*e+ a**@aF b  puts BADD=0X OaP ObPB  a ben*

*e+ subtra,t@aF b  puts BST>A2T=0X OaP - ObPB  a - b

en*

*e+ (ultiply@aF b  puts BLT=LE=0X OaP I ObPB  a I ben*

*e+ *ivi*e@aF b  puts BD=;=D=0X OaP H ObPB  a H ben*

puts BLets *o so(e (at/ 8it/ Rust +un,tionsCB

age K a**@3"F #/eig/t K subtra,t@<&F!8eig/t K (ultiply@9"F i K *ivi*e@1""F

puts BAge: OagePF 7eig/t: O/eig/tPF Weig/t: O8eig/tPF =4: OiPB

A puZZle +or t/e extra ,re*itF type it in any8ay.puts B7ere is a puZZle.B

8/at K a**@ageF subtra,t@/eig/tF (ultiply@8eig/tF *ivi*e@iF

puts BT/at be,o(es: O8/atP 2an you *o it by /an*MB

We are now doing our own math functions for a**, subtra,t, (ultiply, and *ivi*e. The

imortant thing to notice is the last line where we say a b 5in a**6. What this does is the

following#

$. ?ur function is called with two arguments# a and b.

. We rint out what our function is doing, in this case "-IF%".

(. Then we tell Ruby to do something !ind of bac!ward# we return the addition of a

b. +ou might say this as, "I add a and b then return them." In Ruby, the last e*aluated

statement in a method is its return *alue. +ou can be more e&licit if you want and

tye return a b, but that is totally otional.

((

Page 34: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 34/128

B. Ruby adds the two numbers. Then when the function ends any line that runs it will be

able to assign this a 9 b result to a *ariable.

-s with many other things in this boo!, you should ta!e this real slow, brea! it down and try

to trace what's going on. To hel there's e&tra credit to get you to sol*e a uGGle and learn

something cool.

What "o# Sho#ld See$ ruby ex1.rbLets *o so(e (at/ 8it/ Rust +un,tionsCADD=0X 3" #ST>A2T=0X <& - !LT=LE=0X 9" I D=;=D=0X 1"" H Age: 3#F 7eig/t: <!F Weig/t: 1&"F =4: #"7ere is a puZZle.D=;=D=0X #" H

LT=LE=0X 1&" I #ST>A2T=0X <! - !#""ADD=0X 3# -!!T/at be,o(es: -!391 2an you *o it by /an*M$

(%tra Credit 

$. If you aren't really sure what return *alues are, try writing a few of your own

functions and ha*e them return some *alues. +ou can return anything that you can ut

to the right of an K.

. -t the end of the scrit is a uGGle. I'm ta!ing the return *alue of one function, and

using it as the argument of another function. I'm doing this in a chain so that I'm !indof creating a formula using the functions. It loo!s really weird, but if you run the

scrit you can see the results. What you should do is try to figure out the normal

formula that would recreate this same set of oerations.

(. ?nce you ha*e the formula wor!ed out for the uGGle, get in there and see what

haens when you modify the arts of the functions. Try to change it on urose to

ma!e another *alue.

B. :inally, do the in*erse. Write out a simle formula and use the functions in the same

way to calculate it.

This e&ercise might really whac! your brain out, but ta!e it slow and easy and treat it li!e a

little game. :iguring out uGGles li!e this is what ma!es rogramming fun, so I'll be gi*ingyou more little roblems li!e this as we go.

Exercise ##: What 6o 7ou 8no9 So Far

There won't be any code in this e&ercise or the ne&t one, so there's no W+// or 0&tra ;redit

either. In fact, this e&ercise is li!e one giant 0&tra ;redit. I'm going to ha*e you do a form of

re*iew what you ha*e learned so far.

:irst, go bac! through e*ery e&ercise you ha*e done so far and write down e*ery word and

symbol 5another name for 'character'6 that you ha*e used. )a!e sure your list of symbols iscomlete.

(B

Page 35: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 35/128

 Fe&t to each word or symbol, write its name and what it does. If you can't find a name for a

symbol in this boo!, then loo! for it online. If you do not !now what a word or symbol does,

then go read about it again and try using it in some code.

+ou may run into a few things you ust can't find out or !now, so ust !ee those on the list

and be ready to loo! them u when you find them.

?nce you ha*e your list, send a few days rewriting the list and double chec!ing that it's

correct. This may get boring but ush through and really nail it down.

?nce you ha*e memoriGed the list and what they do, then you should ste it u by writing out

tables of symbols, their names, and what they do from memory. When you hit some you can't

recall "rom memory, go bac! and memoriGe them again.

Warnin!

The most imortant thing when doing this e&ercise is# "There is no failure, only trying."

What "o# are Learning 

It's imortant when you are doing a boring mindless memoriGation e&ercise li!e this to !now

why. It hels you focus on a goal and !now the urose of all your efforts.

In this e&ercise you are learning the names of symbols so that you can read source code more

easily. It's similar to learning the alhabet and basic words of 0nglish, e&cet that Ruby's

alhabet has e&tra symbols you might not !now.

<ust ta!e it slow and do not hurt your brain. Hoefully by now these symbols are natural for

you so this isn't a big effort. It's best to ta!e $C minutes at a time with your list and then ta!e a

 brea!. %i*ing your brain a rest will hel you learn faster with less frustration.

Exercise #%: Read So"e $ode

+ou should ha*e sent last wee! getting your list of symbols straight and loc!ed in your

mind. Fow you get to aly this to another wee! reading code on the internet. This e&ercisewill be daunting at first. I'm going to throw you in the dee end for a few days and ha*e you

 ust try your best to read and understand some source code from real roects. The goal isn't

to get you to understand code, but to teach you the following three s!ills#

$. :inding Ruby source code for things you need.

. Reading through the code and loo!ing for files.

(. Trying to understand code you find.

B. -t your le*el you really do not ha*e the s!ills to e*aluate the things you find, but you

can benefit from getting e&osure and seeing how things loo!.

(C

Page 36: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 36/128

When you do this e&ercise, thin! of yourself as an anthroologist, truc!ing through a new

land with ust barely enough of the local language to get around and sur*i*e. 0&cet, of

course, that you will actually get out ali*e because the internet isn't a ungle. -nyway.

Here's what you do#

$. %o to github.com with your fa*orite web browser and search for "ruby".

. Pic! a random roect and clic! on it.

(. ;lic! on the /ource tab and browse through the list of files and directories until you

find a .rb file.

B. /tart at the to and read through it, ta!ing notes on what you thin! it does.

C. If any symbols or strange words seem to interest you, write them down to research

later.

That's it. +our ob is to use what you !now so far and see if you can read the code and get a

gras of what it does. Try s!imming the code first, and then read it in detail. )aybe also try

ta!ing *ery difficult arts and reading each symbol you !now outloud.

 Fow try se*eral other sites#

• hero!u.com

• rubygems.org

•  bitbuc!et.org

?n each of these sites you may find weird files ending in .c so stic! to .rb files li!e the ones

you ha*e written in this boo!.

- final fun thing to do is use the abo*e four sources of Ruby code and tye in toics you are

interested in instead of "ruby". /earch for "ournalism", "coo!ing", "hysics", or anything

you are curious about. ;hances are there's some code out there you could use right away.

Exercise #(: 'ore ractice

+ou are getting to the end of this section. +ou should ha*e enough Ruby "under your

fingers" to mo*e onto learning about how rogramming really wor!s, but you should do

some more ractice. This e&ercise is longer and all about building u stamina. The ne&t

e&ercise will be similar. o them, get them e&actly right, and do your chec!s.

 1  3 ! #  < & 91"11

113

puts BLets pra,ti,e everyt/ing.Bputs BEou5* nee* to )no8 5bout es,apes 8it/ 55 t/at *o 5n ne8lines an*5t tabs.B

poe( K LT=NL=0NST>=0X

5tT/e lovely 8orl*8it/ logi, so +ir(ly plante*,annot *is,ern 5n t/e nee*s o+ lovenor ,o(pre/en* passion +ro( intuitionan* reuires an explanation

5n5t5t8/ere t/ere is none.

(D

Page 37: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 37/128

1!1#11<1&

19"13!#<&93"31

3333!3#33<3&

LT=NL=0NST>=0X

puts B--------------Bputs poe(puts B--------------B

+ive K 1" - 3 - puts BT/is s/oul* be +ive: O+ivePB

*e+ se,retN+or(ula@starte*  RellyNbeans K starte* I #""  Rars K RellyNbeans H 1"""  ,rates K Rars H 1""  return RellyNbeansF RarsF ,ratesen*

startNpoint K 1""""beansF RarsF ,rates K se,retN+or(ula@startNpoint

puts BWit/ a starting point o+: OstartNpointPBputs BWe* /ave ObeansP beansF ORarsP RarsF an* O,ratesP ,rates.B

startNpoint K startNpoint H 1"

puts BWe ,an also *o t/at t/is 8ay:Bputs BWe* /ave Js beansF Js RarsF an* Js ,rates.B Jse,retN+or(ula@startNpoint

What "o# Sho#ld See$ ruby ex!.rbLets pra,ti,e everyt/ing.Eou* nee* to )no8 bout es,apes 8it/ 5 t/at *o ne8lines an* tabs.--------------

  T/e lovely 8orl*8it/ logi, so +ir(ly plante*,annot *is,ern t/e nee*s o+ lovenor ,o(pre/en* passion +ro( intuitionan* reuires an explanation

  8/ere t/ere is none.

--------------T/is s/oul* be +ive: #Wit/ a starting point o+: 1""""We* /ave #"""""" beansF #""" RarsF an* #" ,rates.We ,an also *o t/at t/is 8ay:We* /ave #""""" beansF #"" RarsF an* # ,rates.$

(%tra Credit 

$. )a!e sure to do your chec!s# read it bac!wards, read it out loud, ut comments abo*e

confusing arts.

. 2rea! the file on urose, then run it to see what !inds of errors you get. )a!e sure

you can fi& it.

(

Page 38: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 38/128

Exercise #+: Een 'ore ractice

We're going to do some more ractice in*ol*ing functions and *ariables to ma!e sure you

!now them well. This e&ercise should be straight forward for you to tye in, brea! down, and

understand.

Howe*er, this e&ercise is a little different. +ou won't be running it. Instead  you will imort it

into your Ruby interreter and run the functions yourself.

 1  3 ! #  <

 & 91"111131!1#11<1&19"

13!#<&93"31333

3!3#33<3&39!"!1!!3!!

(o*ule x#  *e+ sel+.brea)N8or*s@stu++  T/is +un,tion 8ill brea) up 8or*s +or us.  8or*s K stu++.split@   8or*s  en*

  *e+ sel+.sortN8or*s@8or*s  Sorts t/e 8or*s.  8or*s.sort@en*

  *e+ sel+.printN+irstN8or*@8or*s  rints t/e +irst 8or* an* s/i+ts t/e ot/ers *o8n by one.  8or* K 8or*s.s/i+t@  puts 8or*  en*

  *e+ sel+.printNlastN8or*@8or*s  rints t/e last 8or* a+ter popping it o++ t/e en*.

  8or* K 8or*s.pop@  puts 8or*  en*

  *e+ sel+.sortNsenten,e@senten,e  Ta)es in a +ull senten,e an* returns t/e sorte* 8or*s.  8or*s K brea)N8or*s@senten,e  sortN8or*s@8or*s  en*

  *e+ sel+.printN+irstNan*Nlast@senten,e  rints t/e +irst an* last 8or*s o+ t/e senten,e.  8or*s K brea)N8or*s@senten,e

  printN+irstN8or*@8or*s  printNlastN8or*@8or*s  en*

  *e+ sel+.printN+irstNan*NlastNsorte*@senten,e  Sorts t/e 8or*s t/en prints t/e +irst an* last one.  8or*s K sortNsenten,e@senten,e  printN+irstN8or*@8or*s  printNlastN8or*@8or*s  en*en*

:irst, run this li!e normal with ruby ex#.rb to find any errors you ha*e made. ?nce you

ha*e found all of the errors you can and fi&ed them, you will then want to follow the W+//section to comlete the e&ercise.

(4

Page 39: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 39/128

What "o# Sho#ld See

In this e&ercise we're going to interact with your .rb file inside the Ruby interreter 5IR26

you used eriodically to do calculations.

Here's what it loo!s li!e when I do it#

$ irbirb@(ain:""1:"' reuire .Hex#K' trueirb@(ain:"":"' senten,e K BAll goo* t/ings ,o(e to t/ose 8/o 8ait.BK' BAll goo* t/ings ,o(e to t/ose 8/o 8ait.Birb@(ain:""3:"' 8or*s K x#.brea)N8or*s@senten,eK' BAllBF Bgoo*BF Bt/ingsBF B,o(eBF BtoBF Bt/oseBF B8/oBF B8ait.BUirb@(ain:""!:"' sorte*N8or*s K x#.sortN8or*s@8or*sK' BAllBF B,o(eBF Bgoo*BF Bt/ingsBF Bt/oseBF BtoBF B8ait.BF B8/oBUirb@(ain:""#:"' x#.printN+irstN8or*@8or*sAllK' nilirb@(ain:"":"' x#.printNlastN8or*@8or*s8ait.K' nilirb@(ain:""<:"' x#.8ro*s0oet/o*rror: un*e+ine* (et/o* Q8ro*s +or x#:o*ule  +ro( @irb:irb@(ain:""&:"' 8or*sK' Bgoo*BF Bt/ingsBF B,o(eBF BtoBF Bt/oseBF B8/oBUirb@(ain:""9:"' x#.printN+irstN8or*@sorte*N8or*sAllK' nilirb@(ain:"1":"' x#.printNlastN8or*@sorte*N8or*s8/oK' nilirb@(ain:"11:"' sorte*N8or*sK' B,o(eBF Bgoo*BF Bt/ingsBF Bt/oseBF BtoBF B8ait.BUirb@(ain:"1:"' x#.sortNsenten,e@senten,eK' BAllBF B,o(eBF Bgoo*BF Bt/ingsBF Bt/oseBF BtoBF B8ait.BF B8/oBUirb@(ain:"13:"' x#.printN+irstNan*Nlast@senten,eAll8ait.K' nilirb@(ain:"1!:"' x#.printN+irstNan*NlastNsorte*@senten,eAll8/o

K' nilirb@(ain:"1#:"' ^D$

Let's brea! this down line by line to ma!e sure you !now what's going on#

$. Line you re3uire your .Hex#.rb Ruby file, ust li!e other re3uires you ha*e done.

 Fotice you do not need to ut the .rb at the end to re3uire it. When you do this you

ma!e a (o*ule that has all your functions in it to use.

. Line B you made a senten,e to wor! with.

(. Line D you use the x# module and call your first function x#.brea)N8or*s. The

. 5dot, eriod6 symbol is how you tell Ruby, "Hey, inside x# there's a functioncalled brea)N8or*s and I want to run it."

(>

Page 40: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 40/128

B. Line 4 we do the same thing with x#.sortN8or*s to get a sorted sentence.

C. Lines $81$C we use x#.printN+irstN8or*  and x#.printNlastN8or*  to get the

first and last word rinted out.

D. Line $D is interesting. I made a mista!e and tyed the 8or*s *ariable as 8ro*s so

Ruby ga*e me an error on Lines $1$4.

. Lines $>18 is where we rint the modified words list. Fotice that since we rintedthe first and last one, those words are now missing.

4. The remaining lines are for you to figure out and analyGe in the e&tra credit.

(%tra Credit 

$. Ta!e the remaining lines of the W+// outut and figure out what they are doing.

)a!e sure you understand how you are running your functions in the 0&C module.

. The reason we ut our functions in a (o*ule is so they ha*e their own namesace. If

someone else writes a function called brea)N8or*s, we won't collide. Howe*er, if

tying x#. is annoying, you can tye in,lu*e x# which is li!e saying, "Include

e*erything from the 0&C module in my current module."(. Try brea!ing your file and see what it loo!s li!e in Ruby when you use it. +ou will

ha*e to 3uit IR2 with ;TRL1 to be able to reload it.

Exercise #,: $on!ratu*ations/ Ta2e A Test;

+ou are almost done with the first half of the boo!. The second half is where things get

interesting. +ou will learn logic and be able to do useful things li!e ma!e decisions.

2efore you continue, I ha*e a 3uiG for you. This 3uiG will be *ery hard because it re3uires

you to fi& someone else's code. When you are a rogrammer you often ha*e to deal withanother rogrammer's code, and also with their arrogance. They will *ery fre3uently claim

that their code is erfect.

These rogrammers are stuid eole who care little for others. - good rogrammer

assumes, li!e a good scientist, that there's always some robability their code is wrong. %ood

 rogrammers start from the remise that their software is bro!en and then wor! to rule out all

 ossible ways it could be wrong before finally admitting that maybe it really is the other

guy's code.

In this e&ercise, you will ractice dealing with a bad rogrammer by fi&ing a bad

 rogrammer's code. I ha*e oorly coied e&ercises B and C into a file and remo*ed random

characters and added flaws. )ost of the errors are things Ruby will tell you, while some of

them are math errors you should find. ?thers are formatting errors or selling mista!es in the

strings.

-ll of these errors are *ery common mista!es all rogrammers ma!e. 0*en e&erienced ones.

+our ob in this e&ercise is to correct this file. Ese all of your s!ills to ma!e this file better.

-nalyGe it first, maybe rinting it out to edit it li!e you would a school term aer. :i& each

flaw and !ee running it and fi&ing it until the scrit runs erfectly. Try not to get hel, and

instead if you get stuc! ta!e a brea! and come bac! to it later.

B8

Page 41: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 41/128

0*en if this ta!es days to do, bust through it and ma!e it right.

:inally, the oint of this e&ercise isn't to tye it in, but to fi& an e&isting file. To do that, you

must go to#

htt#AAruby.learncodethehardway.orgAboo!Ae&erciseD.t&t

;oy1aste the code into a file named ex.rb. This is the only time you are allowed to

coy1aste.

T/is +un,tion 8ill brea) up 8or*s +or us.*e+ brea)N8or*s@stu++  8or*s K stu++.split@   return 8or*sen*

Sorts t/e 8or*s.

*e+ sortN8or*s@8or*s  return sorte*@8or*sen*

rints t/e +irst 8or* a+ter popping it o++.*e+ putsN+irstN8or*@8or*s  8or* K 8or*s.poop@"  puts 8or*en*

rints t/e last 8or* a+ter popping it o++.*e+ putsNlastN8or*@8or*s  8or* K 8or*s.pop@-1

  puts 8or*en*

Ta)es in a +ull senten,e an* returns t/e sorte* 8or*s.*e+ sortNsenten,e@senten,e  8or*s K brea)N8or*s@senten,e  return sortN8or*s@8or*sen*

uts t/e +irst an* last 8or*s o+ t/e senten,e.*e+ putsN+irstNan*Nlast@senten,e  8or*s K brea)N8or*s@senten,e  putsN+irstN8or*@8or*s

  putsNlastN8or*@8or*sen*

Sorts t/e 8or*s t/en prints t/e +irst an* last one.*e+ putsN+irstNan*NlastNsorte*@senten,e  8or*s K sortNsenten,e@senten,e  putsN+irstN8or*@8or*s  putsNlastN8or*@8or*sen*

puts BLets pra,ti,e everyt/ing.Bputs Eou5* nee* to )no8 5bout es,apes 8it/ 55 t/at *o 5n ne8lines an* 5t

tabs.

poe( K G

B$

Page 42: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 42/128

5tT/e lovely 8orl*8it/ logi, so +ir(ly plante*,annot *is,ern 5n t/e nee*s o+ lovenor ,o(pre/en* passion +ro( intuitionan* reuires an explantion5n5t5t8/ere t/ere is none.

G

puts B--------------Bputs poe(puts B--------------B

+ive K 1" - 3 - #puts BT/is s/oul* be +ive: JsB J +ive

*e+ se,retN+or(ula@starte*  RellyNbeans K starte* I #""  Rars K RellyNbeans 5 1"""

  ,rates K Rars H 1""  return RellyNbeansF RarsF ,ratesen*

startNpoint K 1""""beansF RarsF ,rates KK se,retN+or(ula@start-point

puts BWit/ a starting point o+: J*B J startNpointputs BWe* /ave J* ReansF J* RarsF an* J* ,rates.B J @beansF RarsF ,rates

startNpoint K startNpoint H 1"

puts BWe ,an also *o t/at t/is 8ay:B

puts BWe* /ave J* beansF J* RarsF an* J* ,rabapples.B Jse,retN+or(ula@startNpont

senten,e K BAll go*5tt/ings ,o(e to t/ose 8/o 8eig/t.B

8or*s K ex#.brea)N8or*s@senten,esorte*N8or*s K ex#.sortN8or*s@8or*s

putsN+irstN8or*@8or*sputsNlastN8or*@8or*s.putsN+irstN8or*@sorte*N8or*sputsNlastN8or*@sorte*N8or*ssorte*N8or*s K ex#.sortNsenten,e@senten,eprin sorte*N8or*s

putsNirstNan*Nlast@senten,e

putsN+irstNaNlastNsorte*@senen,e

Exercise #-: 'e"ori<in! Lo!ic

Today is the day you start learning about logic. E to this oint you ha*e done e*erything

you ossibly can reading and writing files, to the terminal, and ha*e learned 3uite a lot of themath caabilities of Ruby.

B

Page 43: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 43/128

:rom now on, you will be learning logic. +ou won't learn comle& theories that academics

lo*e to study, but ust the simle basic logic that ma!es real rograms wor! and that real

 rogrammers need e*ery day.

Learning logic has to come after you do some memoriGation. I want you to do this e&ercise

for an entire wee!. o not falter. 0*en if you are bored out of your mind, !ee doing it. Thise&ercise has a set of logic tables you must memoriGe to ma!e it easier for you to do the later

e&ercises.

I'm warning you this won't be fun at first. It will be downright boring and tedious but this is

to teach you a *ery imortant s!ill you will need as a rogrammer. +ou will need to be able

to memoriGe imortant concets as you go in your life. )ost of these concets will be

e&citing once you get them. +ou will struggle with them, li!e wrestling a s3uid, then one day

sna you will understand it. -ll that wor! memoriGing the basics ays off big later.

Here's a ti on how to memoriGe something without going insane# o a tiny bit at a time

throughout the day and mar! down what you need to wor! on most. o not try to sit down fortwo hours straight and memoriGe these tables. This won't wor!. +our brain will really only

retain whate*er you studied in the first $C or (8 minutes anyway.

Instead, what you should do is create a bunch of inde& cards with each column on the left on

one side 5True or :alse6 and the column on the right on the bac!. +ou should then ull them

out, see the "True or :alse" and be able to immediately say "TrueO" 7ee racticing until you

can do this.

?nce you can do that, start writing out your own truth tables each night into a noteboo!. o

not ust coy them. Try to do them from memory, and when you get stuc! glance 3uic!ly at

the ones I ha*e here to refresh your memory. oing this will train your brain to remember the

whole table.

o not send more than one wee! on this, because you will be alying it as you go.

The Tr#th Ter+s

In Ruby we ha*e the following terms 5characters and hrases6 for determining if something is

"true" or "false". Logic on a comuter is all about seeing if some combination of these

characters and some *ariables is True at that oint in the rogram.

• an*

• or

• not

• CK 5not e3ual6

• KK 5e3ual6

• 'K 5greater1than1e3ual6

• K 5less1than1e3ual6

• true

• false

+ou actually ha*e run into these characters before, but maybe not the hrases. The hrases5and, or, not6 actually wor! the way you e&ect them to, ust li!e in 0nglish.

B(

Page 44: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 44/128

The Tr#th Ta/les

We will now use these characters to ma!e the truth tables you need to memoriGe.

&=T True

not :alse True

not True :alse

=R True

True or :alse True

True or True True

:alse or True True

:alse or :alse :alse

A&6 TrueTrue and :alse :alse

True and True True

:alse and True :alse

:alse and :alse :alse

&=T =R True

not 5True or :alse6 :alse

not 5True or True6 :alse

not 5:alse or True6 :alse

not 5:alse or :alse6 True

&=T A&6 True

not 5True and :alse6 True

not 5True and True6 :alse

not 5:alse and True6 True

not 5:alse and :alse6 True

;> True

$ OS 8 True

$ OS $ :alse

8 OS $ True

8 OS 8 :alse

>> True

$ SS 8 :alse

$ SS $ True

8 SS $ :alse

8 SS 8 True

BB

Page 45: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 45/128

 Fow use these tables to write u your own cards and send the wee! memoriGing them.

Remember though, there is no failing in this boo!, ust trying as hard as you can each day,

and then a little bit more.

Exercise #.: ?oo*ean racticeThe logic combinations you learned from the last e&ercise are called "boolean" logic

e&ressions. 2oolean logic is used e*erywhere in rogramming. They are essential

fundamental arts of comutation and !nowing them *ery well is a!in to !nowing your scales

in music.

In this e&ercise you will be ta!ing the logic e&ercises you memoriGed and start trying them

out in IR2. Ta!e each of these logic roblems, and write out what you thin! the answer will

 be. In each case it will be either true or false. ?nce you ha*e the answers written down, you

will start IR2 in your terminal and tye them in to confirm your answers.

1. true an* true. +alse an* true3. 1 KK 1 an* KK 1!. BtestB KK BtestB#. 1 KK 1 or CK 1. true an* 1 KK 1<. +alse an* " CK "&. true or 1 KK 19. BtestB KK BtestingB1". 1 CK " an* KK 111. BtestB CK BtestingB1. BtestB KK 113. not @true an* +alse1!. not @1 KK 1 an* " CK 11#. not @1" KK 1 or 1""" KK 1"""1. not @1 CK 1" or 3 KK !1<. not @BtestingB KK BtestingB an* B6e*B KK B2ool XuyB1&. 1 KK 1 an* not @BtestingB KK 1 or 1 KK "19. B,/un)yB KK Bba,onB an* not @3 KK ! or 3 KK 3". 3 KK 3 an* not @BtestingB KK BtestingB or B>ubyB KK B?unB

I will also gi*e you a tric! to hel you figure out the more comlicated ones toward the end.

Whene*er you see these boolean logic statements, you can sol*e them easily by this simle

 rocess#

$. :ind e3uality test 5KK or CK6 and relace it with its truth.

. :ind each andAor inside a arenthesis and sol*e those first.

(. :ind each not and in*ert it.

B. :ind any remaining andAor and sol*e it.

C. When you are done you should ha*e true or false.

I will demonstrate with a *ariation on 8#

3 CK ! an* not @BtestingB CK BtestB or B>ubyB KK B>ubyB

BC

Page 46: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 46/128

Here's me going through each of the stes and showing you the translation until I'*e boiled it

down to a single result#

$. /ol*e each e3uality test#

o 3 CK ! is True# true an* not @BtestingB CK BtestB or B>ubyB KK

B>ubyBo BtestingB CK BtestB is True# true an* not @true or B>ubyB KK

B>ubyB

o B>ubyB KK B>ubyB# true an* not @true or true

. :ind each andAor in arenthesis @#

o @true or true is True# true an* not @true ( :ind each not and in*ert

it#

o not @true is Fa*se# true an* +alse

(. :ind any remaining andAor and sol*e them#

o true an* +alse is Fa*se

With that we're done and !now the result is false.

Warnin!

The more comlicated ones may seem *ery hard at first. +ou should be able to gi*e a good

first stab at sol*ing them, but do not get discouraged. I'm ust getting you rimed for more of

these "logic gymnastics" so that later cool stuff is much easier. <ust stic! with it, and !ee

trac! of what you get wrong, but do not worry that it's not getting in your head 3uite yet. It'll

come.

What "o# Sho#ld See

-fter you ha*e tried to guess at these, this is what your session with IR2 might loo! li!e#

$ irbruby-1.9.-p1&" :""1 ' true an* true K' trueruby-1.9.-p1&" :"" ' 1 KK 1 an* KK  K' true

(%tra Credit $. There are a lot of oerators in Ruby similar to CK and KK. Try to find out as many

"e3uality oerators" as you can. They should be li!e#  or K.

. Write out the names of each of these e3uality oerators. :or e&amle, I call CK "not

e3ual".

(. Play with IR2 by tying out new boolean oerators, and before you hit enter try to

shout out what it is. o not thin! about it, ust the first thing that comes to mind.

Write it down then hit enter, and !ee trac! of how many you get right and wrong.

Throw away that iece of aer from ( away so you do not accidentally try to use it

later.

BD

Page 47: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 47/128

Exercise #: What I5 

Here is the ne&t scrit of Ruby you will enter, which introduces you to the i+-state(ent.

Tye this in, ma!e it run e&actly right, and then we'll try see if your ractice has aid off.

 1  3 ! #  < & 91"111

131!1#11<1&19"13!#

<&93"31333

people K ",ats K 3"*ogs K 1#

i+ people ,ats  puts BToo (any ,atsC T/e 8orl* is *oo(e*CBen*

i+ people ' ,ats  puts B0ot (any ,atsC T/e 8orl* is save*CBen*

i+ people *ogs  puts BT/e 8orl* is *roole* onCBen*

i+ people ' *ogs  puts BT/e 8orl* is *ryCBen*

*ogs K #

i+ people 'K *ogs  puts Beople are greater t/an or eual to *ogs.Ben*

i+ people K *ogs  puts Beople are less t/an or eual to *ogs.Ben*

i+ people KK *ogs  puts Beople are *ogs.Ben*

What "o# Sho#ld See$ ruby ex9.rbToo (any ,atsC T/e 8orl* is *oo(e*C

T/e 8orl* is *ryCeople are greater t/an or eual to *ogs.eople are less t/an or eual to *ogs.eople are *ogs.$

(%tra Credit 

In this e&tra credit, try to guess what you thin! the i+-state(ent is and what it does. Try to

answer these 3uestions in your own words before mo*ing onto the ne&t e&ercise#

$. What do you thin! the i+ does to the code under it

. ;an you ut other boolean e&ressions from 0&. in the i+-state(ent Try it.

(. What haens if you change the initial *ariables for eole, cats, and dogs

B

Page 48: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 48/128

Exercise %0: E*se And I5 

In the last e&ercise you wor!ed out some i+-state(ents, and then tried to guess what they

are and how they wor!. 2efore you learn more I'll e&lain what e*erything is by answering

the 3uestions you had from e&tra credit. +ou did the e&tra credit right

$. What do you thin! the if does to the code under it -n i+ statement creates what is

called a "branch" in the code. It's !ind of li!e those choose your own ad*enture boo!s

where you are as!ed to turn to one age if you ma!e one choice, and another if you go

a different direction. The i+-state(ent tells your scrit, "If this boolean e&ression

is True, then run the code under it, otherwise s!i it."

. ;an you ut other boolean e&ressions from 0&. in the i+ statement Try it. +es

you can, and they can be as comle& as you li!e, although really comle& things

generally are bad style.

(. What haens if you change the initial *alues for eole, cats, and dogs 2ecause you

are comaring numbers, if you change the numbers, different i+-state(ents will

e*aluate to True and the bloc!s of code under them will run. %o bac! and ut

different numbers in and see if you can figure out in your head what bloc!s of code

will run.

;omare my answers to your answers, and ma!e sure you really understand the concet of a

"bloc!" of code. This is imortant for when you do the ne&t e&ercise where you write all the

 arts of i+-state(ents that you can use.

Tye this one in and ma!e it wor! too.

 1  3 ! #  < & 91"111

131!1#11<1&19"13!#

people K 3",ars K !"buses K 1#

i+ ,ars ' people  puts BWe s/oul* ta)e t/e ,ars.Belsi+ ,ars people  puts BWe s/oul* not ta)e t/e ,ars.Belse  puts BWe ,ant *e,i*e.Ben*

i+ buses ' ,ars  puts BT/ats too (any buses.Belsi+ buses ,ars  puts Baybe 8e ,oul* ta)e t/e buses.Belse  puts BWe still ,ant *e,i*e.Ben*

i+ people ' buses  puts BAlrig/tF lets Rust ta)e t/e buses.Belse  puts B?ineF lets stay /o(e t/en.Ben*

B4

Page 49: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 49/128

What "o# Sho#ld See$ ruby ex3".rbWe s/oul* ta)e t/e ,ars.aybe 8e ,oul* ta)e t/e buses.Alrig/tF lets Rust ta)e t/e buses.$

(%tra Credit 

$. Try to guess what elsi+ and else are doing.

. ;hange the numbers of ,ars, people, and buses and then trace through each i+-

state(ent to see what will be rinted.

(. Try some more comle& boolean e&ressions li!e ,ars ' people an* buses

,ars. -bo*e each line write an 0nglish descrition of what the line does.

Exercise %1: 'a2in! 6ecisions

In the first half of this boo! you mostly ust rinted out things and called functions, but

e*erything was basically in a straight line. +our scrits ran starting at the to, and went to the

 bottom where they ended. If you made a function you could run that function later, but it still

didn't ha*e the !ind of branching you need to really ma!e decisions. Fow that you ha*e i+,

else, and elsi+ you can start to ma!e scrits that decide things.

In the last scrit you wrote out a simle set of tests as!ing some 3uestions. In this scrit you

will as! the user 3uestions and ma!e decisions based on their answers. Write this scrit, and

then lay with it 3uite a lot to figure it out.

 1  3 ! #  < & 91"111131!1#11<1&19"13!#<&

*e+ pro(pt  print B' Ben*

puts BEou enter a *ar) roo( 8it/ t8o *oors. Do you go t/roug/ *oor 1 or*oor MB

pro(pt[ *oor K gets.,/o(p

i+ *oor KK B1B  puts BT/eres a giant bear /ere eating a ,/eese ,a)e. W/at *o you *oMB  puts B1. Ta)e t/e ,a)e.B  puts B. S,rea( at t/e bear.B

  pro(pt[ bear K gets.,/o(p

  i+ bear KK B1B  puts BT/e bear eats your +a,e o++. Xoo* RobCB  elsi+ bear KK BB  puts BT/e bear eats your legs o++. Xoo* RobCB  else  puts BWellF *oing ObearP is probably better. ear runs a8ay.B  en*

elsi+ *oor KK BB  puts BEou stare into t/e en*less abyss at 2t/u/lus retina.B  puts B1. lueberries.B  puts B. Eello8 Ra,)et ,lot/espins.B

B>

Page 50: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 50/128

93"313333!3#33<3&39!"

  puts B3. n*erstan*ing revolvers yelling (elo*ies.B

  pro(pt[ insanity K gets.,/o(p

i+ insanity KK B1B or insanity KK BB  puts BEour bo*y survives po8ere* by a (in* o+ Rello. Xoo* RobCB

  else  puts BT/e insanity rots your eyes into a pool o+ (u,). Xoo* RobCB  en*

else  puts BEou stu(ble aroun* an* +all on a )ni+e an* *ie. Xoo* RobCBen*

- !ey oint here is that you are now utting the i+-state(ents inside i+-state(ents as

code that can run. This is *ery owerful and can be used to create "nested" decisions, where

one branch leads to another and another.

)a!e sure you understand this concet of i+-state(ents inside i+-state(ents. In fact, dothe e&tra credit to really nail it.

What "o# Sho#ld See

Here is me laying this little ad*enture game. I do not do so well.

$ ruby ex31.rbEou enter a *ar) roo( 8it/ t8o *oors. Do you go t/roug/ *oor 1 or *oorM' 1

T/eres a giant bear /ere eating a ,/eese ,a)e. W/at *o you *oM1. Ta)e t/e ,a)e.. S,rea( at t/e bear.' T/e bear eats your legs o++. Xoo* RobC

$ ruby ex31.rbEou enter a *ar) roo( 8it/ t8o *oors. Do you go t/roug/ *oor 1 or *oorM' 1T/eres a giant bear /ere eating a ,/eese ,a)e. W/at *o you *oM1. Ta)e t/e ,a)e.. S,rea( at t/e bear.

' 1T/e bear eats your +a,e o++. Xoo* RobC

$ ruby ex31.rbEou enter a *ar) roo( 8it/ t8o *oors. Do you go t/roug/ *oor 1 or *oorM' Eou stare into t/e en*less abyss at 2t/u/lus retina.1. lueberries.. Eello8 Ra,)et ,lot/espins.3. n*erstan*ing revolvers yelling (elo*ies.' 1Eour bo*y survives po8ere* by a (in* o+ Rello. Xoo* RobC

$ ruby ex31.rb

C8

Page 51: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 51/128

Eou enter a *ar) roo( 8it/ t8o *oors. Do you go t/roug/ *oor 1 or *oorM' Eou stare into t/e en*less abyss at 2t/u/lus retina.1. lueberries.. Eello8 Ra,)et ,lot/espins.

3. n*erstan*ing revolvers yelling (elo*ies.' 3T/e insanity rots your eyes into a pool o+ (u,). Xoo* RobC

$ ruby ex31.rbEou enter a *ar) roo( 8it/ t8o *oors. Do you go t/roug/ *oor 1 or *oorM' stu++Eou stu(ble aroun* an* +all on a )ni+e an* *ie. Xoo* RobC

$ ruby ex31.rbEou enter a *ar) roo( 8it/ t8o *oors. Do you go t/roug/ *oor 1 or *oorM

' 1T/eres a giant bear /ere eating a ,/eese ,a)e. W/at *o you *oM1. Ta)e t/e ,a)e.. S,rea( at t/e bear.' applesWellF *oing apples is probably better. ear runs a8ay.

(%tra Credit 

)a!e new arts of the game and change what decisions eole can ma!e. 0&and the game

out as much as you can before it gets ridiculous.

Exercise %#: Loops And Arrays

+ou should now be able to do some rograms that are much more interesting. If you ha*e

 been !eeing u, you should realiGe that now you can combine all the other things you ha*e

learned with i+-state(ents and boolean e&ressions to ma!e your rograms do smart

things.

Howe*er, rograms also need to do reetiti*e things *ery 3uic!ly. We are going to use a

+or-loop in this e&ercise to build and rint *arious arrays. When you do the e&ercise, you

will start to figure out what they are. I won't tell you right now. +ou ha*e to figure it out.

2efore you can use a +or-loop, you need a way to store the results of loos somewhere. The

 best way to do this is with an array. -n array is a container of things that are organiGed in

order. It's not comlicated you ust ha*e to learn a new synta&. :irst, there's how you ma!e

an array#

/airs K bro8nF blon*F re*Ueyes K bro8nF blueF greenU8eig/ts K 1F F 3F !U

What you do is start the array with the  5left1brac!et6 which "oens" the array. Then you ut

each item you want in the array searated by commas, ust li!e when you did function

C$

Page 52: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 52/128

arguments. Lastly you end the array with a U 5right1brac!et6 to indicate that it's o*er. Ruby

then ta!es this array and all its contents, and assigns them to the *ariable.

Warnin!

This is where things get tric!y for eole who can't rogram. +our brain has been taught thatthe world is flat. Remember in the last e&ercise where you ut i+-state(ents inside i+-

state(ents That robably made your brain hurt because most eole do not onder how to

"nest" things inside things. In rogramming this is all o*er the lace. +ou will find functions

that call other functions that ha*e i+-state(ents that ha*e arrays with arrays inside arrays.

If you see a structure li!e this that you can't figure out, ta!e out encil and aer and brea! it

down manually bit by bit until you understand it.

We now will build some arrays using some loos and rint them out#

 1

  3 ! #  < & 91"111131!

1#11<1&19"13!#<

&93"31333

t/eN,ount K 1F F 3F !F #U

+ruits K applesF orangesF pearsF apri,otsU,/ange K 1F penniesF F *i(esF 3F uartersU

t/is +irst )in* o+ +or-loop goes t/roug/ an array+or nu(ber in t/eN,ount  puts BT/is is ,ount Onu(berPBen*

sa(e as aboveF but using a blo,) instea*+ruits.ea,/ *o Y+ruitY  puts BA +ruit o+ type: O+ruitPBen*

also 8e ,an go t/roug/ (ixe* arrays too+or i in ,/ange  puts B= got OiPBen*

8e ,an also buil* arraysF +irst start 8it/ an e(pty oneele(ents K U

t/en use a range obRe,t to *o " to # ,ounts+or i in @"..#  puts BA**ing OiP to t/e list.B  pus/ is a +un,tion t/at arrays un*erstan*  ele(ents.pus/@i

en*

no8 8e ,an puts t/e( out too+or i in ele(ents  puts Ble(ent 8as: OiPBen*

What "o# Sho#ld See$ ruby ex3.rbT/is is ,ount 1T/is is ,ount T/is is ,ount 3

T/is is ,ount !T/is is ,ount #A +ruit o+ type: apples

C

Page 53: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 53/128

A +ruit o+ type: orangesA +ruit o+ type: pearsA +ruit o+ type: apri,ots= got 1= got pennies= got

= got *i(es= got 3= got uartersA**ing " to t/e list.A**ing 1 to t/e list.A**ing to t/e list.A**ing 3 to t/e list.A**ing ! to t/e list.A**ing # to t/e list.le(ent 8as: "le(ent 8as: 1le(ent 8as: le(ent 8as: 3

le(ent 8as: !le(ent 8as: #$

(%tra Credit 

$. Ta!e a loo! at how you used the range @"..#. Loo! u the >ange class to

understand it.

. ;ould you ha*e a*oided that +or-loop entirely on line B and ust assigned @"..# 

directly to ele(ents

(. :ind the Ruby documentation on arrays and read about them. What other oerations

can you do to arrays besides pus/

Exercise %%: Whi*e Loops

 Fow to totally blow your mind with a new loo, the 8/ile-loop. - 8/ile-loop will !ee

e&ecuting the code bloc! under it as long as a boolean e&ression is True.

Wait, you ha*e been !eeing u with the terminology right That if we write a statement

such as i+ ite(s ' # or +or +ruit in +ruits we are starting a code bloc!. Then we

indent the lines that follow, which are said to be within the bloc!, until we reach an en* 

statement, which closes the bloc!. This is all about structuring your rograms so that Ruby

!nows what you mean. If you do not get that idea then go bac! and do some more wor! withi+-state(ents, functions, and the +or-loop until you get it.

Later on we'll ha*e some e&ercises that will train your brain to read these structures, similar

to how we burned boolean e&ressions into your brain.

2ac! to 8/ile-loops. What they do is simly do a test li!e an i+-state(ent, but instead of

running the code bloc! once, they um bac! to the "to" where the 8/ile is, and reeat. It

!ees doing this until the e&ression is Fa*se.

C(

Page 54: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 54/128

Here's the roblem with 8/ile-loops# sometimes they do not sto. This is great if your

intention is to ust !ee looing until the end of the uni*erse. ?therwise you almost always

want your loos to end e*entually.

To a*oid these roblems, there's some rules to follow#

$. )a!e sure that you use 8/ile-loops saringly. Esually a +or-loop is better.

. Re*iew your 8/ile statements and ma!e sure that the thing you are testing will

 become Fa*se at some oint.

(. When in doubt, rint out your test *ariable at the to and bottom of the 8/ile-loop 

to see what it's doing.

In this e&ercise, you will learn the 8/ile-loop by doing the abo*e three things#

 1 

 3 ! #  < & 91"111131!1#

11<

i K "nu(bers K U

8/ile i   puts BAt t/e top i is OiPB  nu(bers.pus/@i

  i K i 1  puts B0u(bers no8: Onu(bersPB  puts BAt t/e botto( i is OiPBen*

puts BT/e nu(bers: B

+or nu( in nu(bers

  puts nu(en*

What "o# Sho#ld See$ ruby ex33.rbAt t/e top i is "0u(bers no8: "UAt t/e botto( i is 1At t/e top i is 10u(bers no8: "F 1UAt t/e botto( i is At t/e top i is

0u(bers no8: "F 1F UAt t/e botto( i is 3At t/e top i is 30u(bers no8: "F 1F F 3UAt t/e botto( i is !At t/e top i is !0u(bers no8: "F 1F F 3F !UAt t/e botto( i is #At t/e top i is #0u(bers no8: "F 1F F 3F !F #UAt t/e botto( i is T/e nu(bers:"

13

CB

Page 55: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 55/128

!#

(%tra Credit 

$. ;on*ert this 8/ile loo to a function that you can call, and relace D in the test @i

 with a *ariable.. Fow use this function to rewrite the scrit to try different numbers.

(. -dd another *ariable to the function arguments that you can ass in that lets you

change the 1 on line 4 so you can change how much it increments by.

B. Rewrite the scrit again to use this function to see what effect that has.

C. Fow, write it to use +or-loops and ranges instead. o you need the incrementor in

the middle anymore What haens if you do not get rid of it

If at any time that you are doing this it goes craGy 5it robably will6, ust hold down ;TRL

and hit c 5;TRL1c6 and the rogram will abort.

Exercise %(: Accessin! E*e"ents =5 Arrays

-rrays are retty useful, but unless you can get at the things in them they aren't all that great.

+ou can already go through the elements of a list in order, but what if you want say, the Cth

element +ou need to !now how to access the elements of an array. Here's how you would

access the first element of an array#

ani(als K bearF tigerF penguinF ZebraUbear K ani(als"U

+ou ta!e a list of animals, and then you get the first one using "O How does that wor!2ecause of the way math wor!s, Ruby start its lists at 8 rather than $. It seems weird, but

there's many ad*antages to this, e*en though it is mostly arbitrary.

The best way to e&lain why is by showing you the difference between how you use numbers

and how rogrammers use numbers.

Imagine you are watching the four animals in our array abo*e 5bearF tigerF

penguinF ZebraU6 run in a race. They win in the order we ha*e them in this array. The

race was really e&citing because the animals didn't eat each other and somehow managed to

run a race. +our friend, howe*er, shows u late and wants to !now who won. oes your

friend say, "Hey, who came in Geroth" Fo, he says, "Hey, who came in first"

This is because the order of the animals is imortant. +ou can't ha*e the second animal

without the first animal, and can't ha*e the third without the second. It's also imossible to

ha*e a "Geroth" animal since Gero means nothing. How can you ha*e a nothing win a race It

 ust doesn't ma!e sense. We call these !inds of numbers "ordinal" numbers, because they

indicate an ordering of things.

Programmers, howe*er, can't thin! this way because they can ic! any element out of a list at

any oint. To a rogrammer, the abo*e list is more li!e a dec! of cards. If they want the tiger,

they grab it. If they want the Gebra, they can ta!e it too. This need to ull elements out of listsat random means that they need a way to indicate elements consistently by an address, or an

CC

Page 56: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 56/128

"inde&", and the best way to do that is to start the indices at 8. Trust me on this, the math is

way easier for these !inds of accesses. This !ind of number is a "cardinal" number and means

you can ic! at random, so there needs to be a 8 element.

/o, how does this hel you wor! with arrays /imle, e*ery time you say to yourself, "I want

the (rd animal," you translate this "ordinal" number to a "cardinal" number by subtracting $.The "(rd" animal is at inde& and is the enguin. +ou ha*e to do this because you ha*e sent

your whole life using ordinal numbers, and now you ha*e to thin! in cardinal. <ust subtract $

and you will be good.

Remember# ordinal SS ordered, $st cardinal SS cards at random, 8.

Let's ractice this. Ta!e this list of animals, and follow the e&ercises where I tell you to write

down what animal you get for that ordinal or cardinal number. Remember if I say "first",

"second", etc. then I'm using ordinal, so subtract $. If I gi*e you cardinal 58, $, 6 then use it

directly.

 ani(als K bearF pyt/onF pea,o,)F)angarooF 8/aleF platypusU

The animal at $. The (rd animal. The $st animal. The animal at (. The Cth animal. The

animal at . The Dth animal. The animal at B.

:or each of these, write out a full sentence of the form# "The $st animal is at 8 and is a bear."

Then say it bac!wards, "The animal at 8 is the $st animal and is a bear."

Ese your Ruby to chec! your answers.

Hint: Ruby has also a few con*enience methods for accessing articular elements in an

array# ani(als.+irst and ani(als.last

(%tra Credit 

$. Read about ordinal and cardinal numbers online.

. With what you !now of the difference between these tyes of numbers, can you

e&lain why this really is 8$$ 5Hint, you can't ic! years at random.6

(. Write some more arrays and wor! out similar inde&es until you can translate them.

B. Ese Ruby to chec! your answers to this as well.

Warnin!

Programmers will tell you to read this guy named "i!stra" on this subect. I recommend

you a*oid his writings on this unless you enoy being yelled at by someone who stoed

 rogramming at the same time rogramming started.

Exercise %+: ?ranches and Functions

+ou ha*e learned to do i+-state(ents, functions, and arrays. Fow it's time to bend your

mind. Tye this in, and see if you can figure out what it's doing.

CD

Page 57: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 57/128

 1  3 ! # 

 < & 91"111131!1#11<1&19

"13!#<&93"313

333!3#33<3&39!"!1!!3!!!#

!!<!&!9#"#1##3#!####<#&#9"1

*e+ pro(pt@  print B' Ben*

*e+ gol*Nroo(@  puts BT/is roo( is +ull o+ gol*. 7o8 (u,/ *o you ta)eMB

  pro(pt[ nextN(ove K gets.,/o(pi+ nextN(ove.in,lu*eM B"B or nextN(ove.in,lu*eM B1B

  /o8N(u,/ K nextN(ove.toNi@  else  *ea*@BanF learn to type a nu(ber.B  en*

  i+ /o8N(u,/ #"  puts B0i,eF youre not gree*yF you 8inCB  ro,ess.exit@"  else  *ea*@BEou gree*y bastar*CB

  en*en*

*e+ bearNroo(@  puts BT/ere is a bear /ere.B  puts BT/e bear /as a bun,/ o+ /oney.B  puts BT/e +at bear is in +ront o+ anot/er *oor.B  puts B7o8 are you going to (ove t/e bearMB  bearN(ove* K +alse

  8/ile true  pro(pt[ nextN(ove K gets.,/o(p

  i+ nextN(ove KK Bta)e /oneyB  *ea*@BT/e bear loo)s at you t/en slaps your +a,e o++.B  elsi+ nextN(ove KK Btaunt bearB an* not bearN(ove*  puts BT/e bear /as (ove* +ro( t/e *oor. Eou ,an go t/roug/ it no8.B  bearN(ove* K true  elsi+ nextN(ove KK Btaunt bearB an* bearN(ove*  *ea*@BT/e bear gets pisse* o++ an* ,/e8s your leg o++.B  elsi+ nextN(ove KK Bopen *oorB an* bearN(ove*  gol*Nroo(@  else  puts B= got no i*ea 8/at t/at (eans.B  en*

  en*en*

*e+ ,t/ul/uNroo(@  puts B7ere you see t/e great evil 2t/ul/u.B  puts B7eF itF 8/atever stares at you an* you go insane.B  puts BDo you +lee +or your li+e or eat your /ea*MB

  pro(pt[ nextN(ove K gets.,/o(p

  i+ nextN(ove.in,lu*eM B+leeB  start@  elsi+ nextN(ove.in,lu*eM B/ea*B  *ea*@BWell t/at 8as tastyCB  else  ,t/ul/uNroo(@

C

Page 58: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 58/128

3!#<

&9<"<1<<3<!<#<<<<&<9&"

&1&&3&!&#&

  en*en*

*e+ *ea*@8/y  puts BO8/yP Xoo* RobCB  ro,ess.exit@"

en*

*e+ start@  puts BEou are in a *ar) roo(.B  puts BT/ere is a *oor to your rig/t an* le+t.B  puts BW/i,/ one *o you ta)eMB

  pro(pt[ nextN(ove K gets.,/o(p

  i+ nextN(ove KK Ble+tB  bearNroo(@  elsi+ nextN(ove KK Brig/tB  ,t/ul/uNroo(@

  else  *ea*@BEou stu(ble aroun* t/e roo( until you starve.B  en*en*

start@

What "o# Sho#ld See

Here's me laying the game#

$ ruby ex3#.rb

Eou are in a *ar) roo(.T/ere is a *oor to your rig/t an* le+t.W/i,/ one *o you ta)eM' le+tT/ere is a bear /ere.T/e bear /as a bun,/ o+ /oney.T/e +at bear is in +ront o+ anot/er *oor.7o8 are you going to (ove t/e bearM' taunt bearT/e bear /as (ove* +ro( t/e *oor. Eou ,an go t/roug/ it no8.' open *oorT/is roo( is +ull o+ gol*. 7o8 (u,/ *o you ta)eM' as+

anF learn to type a nu(ber. Xoo* RobC$

(%tra Credit 

$. raw a ma of the game and how you flow through it.

. :i& all of your mista!es, including selling mista!es.

(. Write comments for the functions you do not understand. Remember R6oc 

comments

B. -dd more to the game. What can you do to both simlify and e&and it.

C. The gol*Nroo( has a weird way of getting you to tye a number. What are all the

 bugs in this way of doing it ;an you ma!e it better than ust chec!ing if "$" or "8"

are in the number Loo! at how toNi@ wor!s for clues.

C4

Page 59: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 59/128

Exercise %,: 6esi!nin! and 6ebu!!in!

 Fow that you !now i+-state(ents, I'm going to gi*e you some rules for +or-loops and

8/ile-loops that will !ee you out of trouble. I'm also going to gi*e you some tis on

debugging so that you can figure out roblems with your rogram. :inally, you are going todesign a similar little game as in the last e&ercise but with a slight twist.

R#les &or 0f-State+ents

$. 0*ery i+-state(ent must ha*e an else.

. If this else should ne*er be run because it doesn't ma!e sense, then you must use a

*ie function in the else that rints out an error message and dies, ust li!e we did in

the last e&ercise. This will find many errors.

(. Fe*er nest i+-state(ents more than dee and always try to do them $ dee. This

means if you ut an i+ in an i+ then you should be loo!ing to mo*e that second i+ 

into another function.B. Treat i+-state(ents li!e aragrahs, where each i+,elsif,else grouing is li!e

a set of sentences. Put blan! lines before and after.

C. +our boolean tests should be simle. If they are comle&, mo*e their calculations to

*ariables earlier in your function and use a good name for the *ariable.

If you follow these simle rules, you will start writing better code than most rogrammers.

%o bac! to the last e&ercise and see if I followed all of these rules. If not, fi& it.

Warnin!

 Fe*er be a sla*e to the rules in real life. :or training uroses you need to follow these rulesto ma!e your mind strong, but in real life sometimes these rules are ust stuid. If you thin! a

rule is stuid, try not using it.

R#les &or Loops

$. Ese a 8/ile-loop only to loo fore*er, and that means robably ne*er. This only

alies to Ruby, other languages are different.

. Ese a +or-loop for all other !inds of looing, esecially if there is a fi&ed or limited

number of things to loo o*er.

Tips &or De/#gging $. o not use a "debugger". - debugger is li!e doing a full1body scan on a sic! erson.

+ou do not get any secific useful information, and you find a whole lot of

information that doesn't hel and is ust confusing.

. The best way to debug a rogram is to use puts or p to rint out the *alues of

*ariables at oints in the rogram to see where they go wrong.

(. )a!e sure arts of your rograms wor! as you wor! on them. o not write massi*e

files of code before you try to run them. ;ode a little, run a little, fi& a little.

C>

Page 60: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 60/128

)o+e$ork 

 Fow write a similar game to the one that I created in the last e&ercise. It can be any !ind of

game you want in the same fla*or. /end a wee! on it ma!ing it as interesting as ossible.

:or e&tra credit, use arrays, functions, and modules 5remember those from 0&. $(6 as much

as ossible, and find as many new ieces of Ruby as you can to ma!e the game wor!.

There is one catch though, write u your idea for the game first. 2efore you start coding you

must write u a ma for your game. ;reate the rooms, monsters, and tras that the layer

must go through on aer before you code.

?nce you ha*e your ma, try to code it u. If you find roblems with the ma then adust it

and ma!e the code match.

?ne final word of ad*ice# 0*ery rogrammer becomes aralyGed by irrational fear starting a

new large roect. They then use rocrastination to a*oid confronting this fear and end u not

getting their rogram wor!ing or e*en started. I do this. 0*eryone does this. The best way to

a*oid this is to ma!e a list of things you should do, and then do them one at a time.

<ust start doing it, do a small *ersion, ma!e it bigger, !ee a list of things to do, and do them.

Exercise %-: Sy"bo* Reie9It's time to re*iew the symbols and Ruby words you !now, and to try to ic! u a few more

for the ne&t few lessons. What I'*e done here is written out all the Ruby symbols and

!eywords that are imortant to !now.

In this lesson ta!e each !eyword, and first try to write out what it does from memory. Fe&t,

search online for it and see what it really does. It may be hard because some of these are

going to be imossible to search for, but !ee trying.

If you get one of these wrong from memory, write u an inde& card with the correct

definition and try to "correct" your memory. If you ust didn't !now about it, write it down,and sa*e it for later.

:inally, use each of these in a small Ruby rogram, or as many as you can get done. The !ey

here is to find out what the symbol does, ma!e sure you got it right, correct it if you do not,

then use it to loc! it in.

1ey$ords• alias

• an*

• X=0

• begin

• brea)

D8

Page 61: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 61/128

• ,ase

• ,lass

• *e+

• *e+ine*M

• *o

else• elsi+

• 0D

• en*

• ensure

• +alse

• +or

• i+

• in

• (o*ule

• next

• nil

• not

• or

• re*o

• res,ue

• retry

• return

• sel+

• super

• t/en

• true

• un*e+

• unless• until

• 8/en

• 8/ile

• yiel*

Data Types

:or data tyes, write out what ma!es u each one. :or e&amle, with strings write out how

you create a string. :or numbers write out a few numbers.

• true• 5a*se

• ni*• ,onstants

• strings

• nu(bers

• ranges

• arrays

• /as/es

/tring 0scaes /e3uences :or string escae se3uences, use them in strings to ma!e sure they

do what you thin! they do.

D$

Page 62: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 62/128

• 55

• 5

• 5B

• 5a

• 5b

5+• 5n

• 5r

• 5t

• 5v

?erators /ome of these may be unfamiliar to you, but loo! them u anyway. :ind out what

they do, and if you still can't figure it out, sa*e it for later.

• ::

• U

II• -@unary

• @unary

• C

• %

• I

• H

• J

• -

• ''

• ]

• Y

• '

• 'K

• K

• K'

• KK

• KKK

• CK

• K%

• C%• ]]

• YY

• ..

• ...

/end about a wee! on this, but if you finish faster that's great. The oint is to try to get

co*erage on all these symbols and ma!e sure they are loc!ed in your head. What's also

imortant is to find out what you do not !now so you can fi& it later.

Exercise %.: 6oin! Thin!s To Lists

D

Page 63: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 63/128

Warnin!

This is being rewritten based on the Python *ersion, there may be errors.

+ou ha*e learned about lists. When you learned about 8/ile-loops you "aended"

numbers to the end of a list and rinted them out. There was also e&tra credit where you weresuosed to find all the other things you can do to lists in the Ruby documentation. That was

a while bac!, so go find in the boo! where you did that and re*iew if you do not !now what

I'm tal!ing about.

:ound it Remember it %ood. When you did this you had a list, and you "called" the

function pus/ on it. Howe*er, you may not really understand what's going on so let's see

what we can do to lists.

When you tye Ruby code that reads (ystu++.pus/@/ello  you are actually setting off a

chain of e*ents inside Ruby to cause something to haen to the (ystu++ list. Here's how it

wor!s#

$. Ruby sees you mentioned (ystu++ and loo!s u that *ariable. It might ha*e to loo!

 bac!wards to see if you created with K, loo! and see if it is a function argument, or

maybe it's a global *ariable. 0ither way it has to find the (ystu++ first.

. ?nce it finds (ystu++ it then hits the . 5eriod6 oerator and starts to loo! at

variables that are a art of (ystu++. /ince (ystu++ is a list, it !nows that (ystu++ 

has a bunch of functions.

(. It then hits pus/ and comares the name "ush" to all the ones that (ystu++ says it

owns. If ush is in there 5it is6 then it grabs that  to use.

B. Fe&t Ruby sees the @ 5arenthesis6 and realiGes, "?h hey, this should be a function."-t this oint it calls 5a!a runs, e&ecutes6 the function ust li!e normally, but instead it

calls the function with an extra argument.

C. It then treats the pus/ as a function, gets it from (ystu++ and calls it with your

 arameter.

That might be a lot to ta!e in, but we're going to send a few e&ercises getting this concet

firm in your brain. To !ic! things off, here's an e&ercise that mi&es strings and lists for all

!inds of fun.

 1

  3 ! #  < & 91"111131!

1#11<

tenNt/ings K BApples Granges 2ro8s Telep/one Lig/t SugarB

puts BWait t/eres not 1" t/ings in t/at listF lets +ix t/at.B

stu++ K tenNt/ings.split@ (oreNstu++ K J8@Day 0ig/t Song ?risbee 2orn anana Xirl oy

8/ile stu++.lengt/ CK 1"  nextNone K (oreNstu++.pop@  puts BA**ing: OnextNonePB  stu++.pus/@nextNone  puts BT/eres Ostu++.lengt/P ite(s no8.Ben*

puts BT/ere 8e go: Ostu++PB

puts BLets *o so(e t/ings 8it/ stu++.B

D(

Page 64: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 64/128

1&19"13

puts stu++1Uputs stu++-1U 8/oaC +an,yputs stu++.pop@puts stu++.Roin@ 8/atM ,oolCputs stu++.valuesNat@3F#.Roin@ super stellarC

What "o# Sho#ld SeeWait t/eres not 1" t/ings in t/at listF lets +ix t/at.A**ing: oyT/eres < ite(s no8.A**ing: XirlT/eres & ite(s no8.A**ing: ananaT/eres 9 ite(s no8.A**ing: 2ornT/eres 1" ite(s no8.T/ere 8e go: ApplesGranges2ro8sTelep/oneLig/tSugaroyXirlanana2orn

Lets *o so(e t/ings 8it/ stu++.Granges2orn2ornApples Granges 2ro8s Telep/one Lig/t Sugar oy Xirl ananaTelep/oneSugar

(%tra Credit 

$. Ta!e each function that is called, and go through the stes outlined abo*e to translate

them to what Ruby does.

. Translate these function calls into 0nglish sentences. :or e&amle

(ystu++.pus/@/ello  would be, ":rom mystuff get the ush function and call it

with 'hello'".(. %o read about "?bect ?riented Programming" online. ;onfused I was too. o not

worry. +ou will learn enough to be dangerous, and you can slowly learn more later.

B. Read u on what a "class" is in Ruby. #o not read about how other languages use the

word $class$% That will only mess you u.

C. If you do not ha*e any idea what I'm tal!ing about do not worry. Programmers li!e to

feel smart so they in*ented ?bect ?riented Programming, named it ??P, and then

used it way too much. If you thin! that's hard, you should try to use "functional

 rogramming".

Exercise %: Hashes/ =h Loe*y HashesWarnin!

This is being rewritten based on the Python *ersion, there may be errors.

 Fow I ha*e to hurt you with another container you can use, because once you learn this

container a massi*e world of ultra1cool will be yours. It is the most useful container e*er# the

hash.

DB

Page 65: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 65/128

Ruby calls them "hashes", other languages call them, "ictionaries". I tend to use both

names, but it doesn't matter. What does matter is what they do when comared to -rrays.

+ou see, a -rray lets you do this#

'' t/ings K aFbF,F*U

K' BaBF BbBF B,BF B*BU'' puts t/ings1UbK' nil'' t/ings1U K ZK' BZB'' puts t/ings1UZK' nil'' puts t/ings.inspe,tBaBF BbBF B,BF B*BUK' nil''

+ou can use numbers to "inde&" into an -rray, meaning you can use numbers to find out

what's in -rrays. +ou should !now this about -rrays by now, but ma!e sure you understand

that you can only use numbers to get items out of a -rray.

What a 7as/ does is let you use anything , not ust numbers. +es, a Hash associates one thing

to another, no matter what it is. Ta!e a loo!#

'' stu++ K Ona(e K' 6e*F age K' 3F /eig/t K' I1PK' OBna(eBK'B6e*BF B/eig/tBK'<!F BageBK'3P'' puts stu++na(eU6e*

K' nil'' puts stu++ageU3K' nil'' puts stu++/eig/tU<!K' nil'' stu++,ityU K BSan ?ran,is,oBK' BSan ?ran,is,oB'' puts stu++,ityUSan ?ran,is,oK' nil''

+ou will see that instead of ust numbers we're using strings to say what we want from the

stu++ Hash. We can also ut new things into the Hash with strings. It doesn't ha*e to be

strings though, we can also do this#

'' stu++1U K BWo8BK' BWo8B'' stu++U K B0eatoBK' B0eatoB'' puts stu++1UWo8K' nil

'' puts stu++U0eato

DC

Page 66: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 66/128

K' nil'' puts stu++.inspe,t@O1K'BWo8BF Bna(eBK'B6e*BF K'B0eatoBF B,ityBK'BSan ?ran,is,oBF  B/eig/tBK'<!F BageBK'3PK' nil''

In this code I used numbers, and then you can see there's numbers and strings as !eys in the

Hash when I rint it. I could use anything. Well almost but ust retend you can use anything

for now.

?f course, a Hash that you can only ut things in is retty stuid, so here's how you delete

things, with the *elete function#

'' stu++.*elete@,ityK' BSan ?ran,is,oB'' stu++.*elete@1K' BWo8B'' stu++.*elete@K' B0eatoB'' puts stu++.inspe,tOBna(eBK'B6e*BF B/eig/tBK'<!F BageBK'3PK' nil''

We'll now do an e&ercise that you must  study *ery carefully. I want you to tye this e&ercise

in and try to understand what's going on. Ta!e note of when I ut things in a Hash, get from

them, and all the oerations I use here.

 1  3 ! #  < & 91"111131!1#11<1&19"13!#<&9

,reate a (apping o+ state to abbreviationstates K O  Gregon K' G>F  ?lori*a K' ?LF  2ali+ornia K' 2AF  0e8 Eor) K' 0EF  i,/igan K' =P

,reate a basi, set o+ states an* so(e ,ities in t/e(,ities K O  2A K' San ?ran,is,oF  = K' DetroitF  ?L K' Va,)sonvilleP

a** so(e (ore ,ities,ities0EU K 0e8 Eor),itiesG>U K ortlan*

puts out so(e ,itiesputs - I 1"puts B0E State /as: BF ,ities0EUputs BG> State /as: BF ,itiesG>U

puts so(e statesputs - I 1"puts Bi,/igans abbreviation is: BF statesi,/iganUputs B?lori*as abbreviation is: BF states?lori*aU

DD

Page 67: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 67/128

3"313333!3#

33<3&39!"!1!!3!!!#!!<!&

!9#"#1##3#!####<#&#9"1

3!#

*o it by using t/e state t/en ,ities *i,tputs - I 1"puts Bi,/igan /as: BF ,itiesstatesi,/iganUUputs B?lori*a /as: BF ,itiesstates?lori*aUU

puts every state abbreviationputs - I 1"+or stateF abbrev in states  puts BJs is abbreviate* JsB J stateF abbrevUen*

puts every ,ity in stateputs - I 1"+or abbrevF ,ity in ,ities  puts BJs /as t/e ,ity JsB J abbrevF ,ityUen*

no8 *o bot/ at t/e sa(e ti(e

puts - I 1"+or stateF abbrev in states  puts BJs state is abbreviate* Js an* /as ,ity JsB J   stateF abbrevF ,itiesabbrevUUen*

puts - I 1" i+ its not t/ere you get nilstate K statesTexasU

i+ not state  puts BSorryF no Texas.Ben*

get a ,ity 8it/ a *e+ault value,ity K ,itiesTU YY Does 0ot xistputs BT/e ,ity +or t/e state T is: JsB J ,ity

What "o# Sho#ld See----------0E State /as:0e8 Eor)G> State /as:ortlan*----------i,/igans abbreviation is:=?lori*as abbreviation is:?L----------i,/igan /as:Detroit?lori*a /as:Va,)sonville----------i,/igan is abbreviate* =2ali+ornia is abbreviate* 2A0e8 Eor) is abbreviate* 0E?lori*a is abbreviate* ?L

Gregon is abbreviate* G>----------

D

Page 68: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 68/128

G> /as t/e ,ity ortlan*= /as t/e ,ity Detroit?L /as t/e ,ity Va,)sonville0E /as t/e ,ity 0e8 Eor)2A /as t/e ,ity San ?ran,is,o----------

i,/igan state is abbreviate* = an* /as ,ity Detroit2ali+ornia state is abbreviate* 2A an* /as ,ity San ?ran,is,o0e8 Eor) state is abbreviate* 0E an* /as ,ity 0e8 Eor)?lori*a state is abbreviate* ?L an* /as ,ity Va,)sonvilleGregon state is abbreviate* G> an* /as ,ity ortlan*----------SorryF no Texas.T/e ,ity +or t/e state T is: Does 0ot xist

(%tra Credit 

$. o this same !ind of maing with cities and statesAregions in your country, or or

some other country.

. %o find the Ruby documentation for Hashes 5a.!.a. Hash6 and try to do e*en morethings to them.

(. :ind out what you can&t  do with Hashes. - big one is that they do not ha*e order, so

try laying with that.

Exercise (0: 'odu*es/ $*asses/ And =b@ects

Warnin!

This is being rewritten based on the Python *ersion, there may be errors.

Ruby is something called an "?bect ?riented Programming Language". What this means is

there's a construct in Ruby called a class that lets you structure your software in a articular

way. Esing classes you can add consistency to your rograms so that they can be used in a

cleaner way, or at least that's the theory.

I am now going to try to teach you the beginnings of ?bect ?riented Programming, classes,

and obects using what you already !now about hashes and modules. )y roblem though is

that ?bect ?riented Programming 5a!a ??P6 is ust lain weird. +ou ha*e to simly

struggle with this, try to understand what I say here, tye in the code, and then in the ne&t

e&ercise I'll hammer it in.

Here we go.

Mod#les Are Like )ashes

+ou !now how a Hash is created and used, and that it is a way to ma one thing to another.

That means if you ha*e a Hash with a !ey 'ale' and you want to get it then you do this#

(ystu++ K Oapple K' B= A ALSCBPputs (ystu++appleU

D4

Page 69: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 69/128

7ee this idea of "get K from +" in your head, and now thin! about modules. +ou'*e made a

few so far, and used them, and you !now they are#

$. - Ruby file with some functions or *ariables inside a o*ule.

. +ou then re3uire that file.

(. -nd then you can access the functions or *ariables in that module with the '.' 5dot6oerator.

Imagine if I ha*e a module that I decide to name mystu""%rb and I ut a function in it called

apple. Here's the module mystu""%rb#

t/is goes in (ystu++.rb(o*ule yStu++  *e+ yStu++.apple@  puts B= A ALSCB  en*en*

?nce I ha*e that, I can use that module with re'uire and then access the apple function#

reuire (ystu++

yStu++.apple@

I could also ut a *ariable in it named tangerine li!e this#

(o*ule yStu++  *e+ yStu++.apple@  puts B= A ALSCB  en*

  t/is is Rust a variable  TA0X>=0 K BLiving re+le,tion o+ a *rea(Ben*

Then again I can access this *ariable using the (( 5double1colon6 oerator instead of the % 

5dot6#

reuire (ystu++

yStu++.apple@

puts yStu++::TA0X>=0

%o refer bac! to the Hash, and you should start to see how this is similar to using a Hash, but

the synta& is different. Let's comare#

(ystu++appleU get apple +ro( /as/yStu++.apple@ get apple +ro( t/e (o*uleyStu++::TA0X>=0 sa(e t/ingF its Rust a variable

This means we ha*e a very common attern in Ruby of this#

$. Ta!e a !eyS*alue style container.. %et something out of it by the !ey's name.

D>

Page 70: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 70/128

In the case of the Hash, the !ey is a string and the synta& is )key*. In the case of the module,

the !ey is an identifier, and the synta& is %key. ?ther than that they are nearly the same thing.

Classes Are Like Mod#les

- way to thin! about modules is they are a secialiGed Hash that can store Ruby code so youcan get to it with the &%&  oerator. Ruby also has another construct that ser*es a similar

 urose called a class. - class is a way to ta!e a grouing of functions and data and lace

them inside a container so you can access them with the &%&  5dot6 oerator.

If I were to create a class ust li!e the +yStu""  module, I'd do something li!e this#

,lass yStu++

  *e+ initialiZe@  _tangerine K BAn* no8 a t/ousan* years bet8eenB

  en*

  attrNrea*er :tangerine

  *e+ apple@  puts B= A 2LASSE ALSCB  en*en*

That loo!s comlicated comared to modules, and there is definitely a lot going on by

comarison, but you should be able to ma!e out how this is li!e a "mini1module" with

 +yStu""  ha*ing an apple,- function in it. What is robably confusing with this is the initiali.e 

function and the use of /tangerine to set the *ariable.

Here's why classes are used instead of modules# +ou can ta!e the abo*e class, and use it to

craft many of them, millions at a time if you want, and they won't interfere with each other.

With modules, when you re3uire there is only one for the entire rogram unless you do some

monster hac!s.

2efore you can understand this though, you need to !now what an "obect" is and how to

wor! with +yStu""  ust li!e you do with the mystu""%rb module.

O/2ects Are Like Mini 0+ports

If a class is li!e a "mini1module", then there has to be a similar concet to re'uire but for

classes. That concet is called "instantiate" which is ust a fancy obno&ious o*erly smart way

to say "create". When you instantiate a class, what you get is called an ob0ect .

The way you do this is you call the +yStu""%new,-, li!e this#

t/ing K yStu++.ne8@t/ing.apple@puts t/ing.tangerine

8

Page 71: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 71/128

The first line is the "instantiate" oeration, and it's a secial function a*ailable on classes for

ma!ing instances. Howe*er, when you call this there's a se3uence of e*ents that Ruby

coordinates for you. I'll go through them using the abo*e code for +yStu"" #

$. Ruby loo!s for +yStu""  and sees that it is a class you'*e defined.

. Ruby crafts an emty obect with all the functions you'*e secified in the class usingde" .

(. Ruby then loo!s to see if you made a "magic" initiali.e function, and if you ha*e it

calls that function to initialiGe your newly created emty obect.

B. In the +yStu""  function initiali.e I then get this e&tra *ariable sel"  which is that emty

obect Ruby made for me, and I can set *ariables on it ust li!e you would with a

module, dict, or other obect.

C. In this case, I set /tangerine to a song lyric and then I'*e initialiGed this obect.

D. Fow Ruby can ta!e this newly minted obect, and assign it to the thing  *ariable for

me to wor! with.

That's the basics of how Ruby does this "mini1re3uire" when you call a %new,- on a class.Remember that this is not  gi*ing you the class, but instead it is using the class as a blueprint  

for how to build a coy of that tye of thing.

7ee in mind that I'm gi*ing you a slightly inaccurate idea for how these wor! so that you

can start to build u an understanding of classes based on what you !now of modules. The

truth is, classes and obects suddenly di*erge from modules at this oint. If I were being

totally honest, I'd say something more li!e this#

• ;lasses are li!e bluerints or definitions for creating new mini1modules.

Instantiation is how you ma!e one of these mini1modules and  re3uire it at the sametime.

• The resulting created mini1module is called an ob0ect  and you then assign it to a

*ariable to wor! with it.

-fter this though classes and obects become *ery different from modules and this should

only ser*e as a way for you to bridge o*er to understanding classes.

3etting Things &ro+ Things

I now ha*e three ways to "get things from things"#

/as/ style(ystu++applesU

(o*ule style(ystu++.apples@puts (ystu++.tangerine

,lass stylet/ing K yStu++.ne8@t/ing.apples@puts t/ing.tangerine

$

Page 72: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 72/128

 A &irst Class (%a+ple

+ou should start seeing the similarities in these three !eyS*alue container tyes and robably

ha*e a bunch of 3uestions. Hang on with the 3uestions, as the ne&t e&ercise is going to

hammer home your "obect oriented *ocabulary". In this e&ercise, I ust want you to tye in

this code and get it wor!ing so that you ha*e some e&erience before mo*ing on.

 1  3 ! #  < & 91"111131!1#11<1&19"13

,lass Song

  *e+ initialiZe@lyri,s  _lyri,s K lyri,s  en*

  *e+ singN(eNaNsong@  +or line in _lyri,s  puts line  en*  en*en*

/appyNb*ay K Song.ne8@B7appy birt/*ay to youBF  B= *ont 8ant to get sue*BF  BSo =ll stop rig/t t/ereBU

bullsNonNpara*e K Song.ne8@BT/ey rally aroun* t/e +a(ilyBF  BWit/ po,)ets +ull o+ s/ellsBU

/appyNb*ay.singN(eNaNsong@

bullsNonNpara*e.singN(eNaNsong@

What You Should See7appy birt/*ay to you= *ont 8ant to get sue*So =ll stop rig/t t/ereT/ey rally aroun* t/e +a(ilyWit/ po,)ets +ull o+ s/ells

Extra Credit

$. Write some more songs using this, ma!e sure you understand that you're assing a list

of strings as the lyrics.

. Put the lyrics in a searate *ariable, then ass that *ariable to the class to use instead.

(. /ee if you can hac! on this and ma!e it do more things. on't worry if you ha*e no

idea how, ust gi*e it a try, see what haens. 2rea! it, trash it, thrash it, you can't hurt

it.

B. /earch online for "obect oriented rogramming" and try to o*erflow your brain with

what you read. on't worry if it ma!es absolutely no sense to you. Half of that stuff

ma!es no sense to me too.

Exercise (1: Learnin! To Spea2 =b@ect

=riented

Page 73: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 73/128

Warnin!

This is being rewritten based on the Python *ersion, there may be errors.

In this e&ercise I'm going to teach you how to sea! "obect oriented". What I'll do is gi*e

you a small set of words with definitions you need to !now. Then I'll gi*e you a set ofsentences with holes in them that you'll ha*e to understand. :inally, I'm going to gi*e you a

large set of e&ercises that you ha*e to comlete to ma!e these sentences solid in your

*ocabulary.

Word Drills

• class # Tell Ruby to ma!e a new !ind of thing.

• obect # Two meanings# the most basic !ind of thing, and any instance of some thing.

• instance # What you get when you tell Ruby to create a class.

• def # How you define a function inside a class.

U # Inside the functions in a class, U is an oerator for *ariables in theinstanceAobect being accessed.

• inheritance # The concet that one class can inherit traits from another class, much

li!e you and your arents.

• comosition # The concet that a class can be comosed of other classes as arts,

much li!e how a car has wheels.

• attribute # - roerty classes ha*e that are from comosition and are usually

*ariables.

• is1a # - hrase to say that something inherits from another, as in a /almon is1a :ish.

• has1a # - hrase to say that something is comosed of other things or has a trait, as in

a /almon has1a mouth.

-lright, ta!e some time to ma!e flash cards for those and memoriGe them. -s usual this won't

ma!e too much sense until after you're done with this e&ercise, but you need to !now the base

words first.

Phrase Drills

 Fe&t I ha*e a list of Ruby code sniets on the left, and the 0nglish sentences for them#

$. class K5+6 # ")a!e a class named K that is1a +."

. class K5obect6 def initialiGe5<6 # "class K has1a initialiGe that ta!es < arameters."(. class K5obect6 def )5<6 # "class K has1a function named ) that ta!es < arameters."

B. foo S K56 # "/et foo to an instance of class K."

C. foo.)5<6 # ":rom foo get the ) function, and call it with arameters <."

D. foo.7 S # ":rom foo get the 7 attribute and set it to ."

In each of these where you see K, +, ), <, 7, , and foo you can treat those li!e blan! sots.

:or e&amle I can also write these sentences as#

$. ")a!e a class named that is1a +."

. "class has1a initialiGe that ta!es arameters."

(. "class has1a function named that ta!es arameters."B. "/et foo to an instance of class ."

(

Page 74: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 74/128

C. ":rom foo get the function, and call it with arameters ."

D. ":rom foo get the attribute and set it to ."

-gain, write these on some flash cards and drill them. Put the Ruby code sniet on the front

and the sentence on the bac!. +ou have to be able to say the sentence e&actly the same e*ery

time whene*er you see that form. Fot sort of the same, but e&actly the same.

Co+/ined Drills

The final rearation for you is to combine the words drills with the hrase drills. What I

want you to do for this drill is this#

$. Ta!e a hrase card and drill it.

. :li it o*er and read the sentence, and for each word in the sentence that is in your

words drills, get that card.

(. rill those words for that sentence.

B. 7ee going until you are bored then ta!e a brea! and do it again.

 A Reading Test 

I now ha*e a little Ruby hac! that will drill you on these words you !now in an infinite

manner. This is a simle scrit you should be able to figure out, and the only thing it does is

use a library called urllib to download a list of words I ha*e. Here's the scrit, which you

should enter into oop1test%rb to wor! with it#

 1

  3 ! #  < & 91"111131!1#11<1&19"13!#<&93"

reuire open-uri

WG>DN>L K B/ttp:HHlearn,o*et/e/ar*8ay.orgH8or*s.txtBWG>DS K U

7>ASS K O  B,lass 5nen*B K' Ba)e a ,lass na(e* t/at is-a .BF  B,lass 5n5t*e+ initialiZe@___5n5ten*5nen*B K' B,lass /as-ainitialiZe t/at ta)es ___ para(eters.BF  B,lass 5n5t*e+ III@___5n5ten*5nen*B K' B,lass /as-a +un,tionna(e* III t/at ta)es ___ para(eters.BF  BIII K .ne8@B K' BSet III to an instan,e o+ ,lass .BF  BIII.III@___B K' B?ro( III get t/e III +un,tionF an* ,all it 8it/para(eters ___.BF  BIII.III K IIIB K' B?ro( III get t/e III attribute an* set it toIII.BP

7>ASN?=>ST K A>X;"U KK Benglis/B

open@WG>DN>L OY+Y+.ea,/Nline OY8or*Y WG>DS.pus/@8or*.,/o(pP

P

*e+ ,ra+tNna(es@ran*N8or*sF snippetF patternF ,apsK+alse  na(es K snippet.s,an@pattern.(ap *o  8or* K ran*N8or*s.pop@  ,aps M 8or*.,apitaliZe : 8or*  en*

B

Page 75: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 75/128

313333!

3#33<3&39!"!1!!3!!!#!!<

!&!9#"#1##3#!####<#&#9"

13!#<&9<"<1<<3

<!<#<<<<&<9&"&1&

  return na(es I en*

*e+ ,ra+tNpara(s@ran*N8or*sF snippetF pattern  na(es K @"...snippet.s,[email protected]/.(ap *o  para(N,ount K ran*@3 1

  para(s K @"...para(N,ount.(ap OYxY ran*N8or*s.pop@ P  para(s.Roin@F   en*

  return na(es I en*

*e+ ,onvert@snippetF p/rase  ran*N8or*s K WG>DS.sortNby Oran*P  ,lassNna(es K ,ra+tNna(es@ran*N8or*sF snippetF HHF ,apsKtrue  ot/erNna(es K ,ra+tNna(es@ran*N8or*sF snippetF H5I5I5IH  para(Nna(es K ,ra+tNpara(s@ran*N8or*sF snippetF H___H 

results K U

  +or senten,e in snippetF p/raseU  +a)e ,lass na(esF also ,opies senten,e  result K senten,e.gsub@HH OYxY ,lassNna(es.pop P

  +a)e ot/er na(es  result.gsubC@H5I5I5IH OYxY ot/erNna(es.pop P

  +a)e para(eter lists  result.gsubC@H___H OYxY para(Nna(es.pop P

  results.pus/@result

  en*

  return resultsen*

)eep going until t/ey /it 2T>L-Dloop *o  snippets K 7>ASS.)[email protected] Oran*P

  +or snippet in snippets  p/rase K 7>ASSsnippetU  uestionF ans8er K ,onvert@snippetF p/rase

  i+ 7>ASN?=>ST  uestionF ans8er K ans8erF uestion  en*

  print uestionF B5n5n' B

  exit@" unless STD=0.gets

  puts B5nA0SW>: Js5n5nB J ans8er  en*en*

Here's an e&amle of me running this and trying to answer the 3uestions as accurately as

 ossible. +ou can see that I tye in the answer I thin! it is based on the hrases I'*e gi*en

C

Page 76: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 76/128

you, and then the scrit rints out the correct answer. +ou should get your answers as close

as ossible.

$ ruby ex!1.rb,lass ran,/

*e+ initialiZe@bellF *egreeF ar(en*

en*

' ,lass ran,/ /as-a initialiZe t/at ta)es bellF *egreeF an* ar(para(eters.

A0SW>: ,lass ran,/ /as-a initialiZe t/at ta)es bellF *egreeF ar(para(eters.

bat.,ollar@*eat/F arit/(eti,

' ?ro( bat get t/e ,ollar +un,tion ,an ,all it 8it/ *eat/F arit/(eti,para(eters.

A0SW>: ?ro( bat get t/e ,ollar +un,tionF an* ,all it 8it/ para(eters*eat/F arit/(eti,.

,annon.,arpenter K ,orn

' ?ro( ,annon get t/e ,arpenter attribute an* set it to ,orn.

A0SW>: ?ro( ,annon get t/e ,arpenter attribute an* set it to ,orn.

ani(al K or*er.ne8@

' Set ani(al eual to an instan,e o+ ,lass or*er.

A0SW>: Set ani(al to an instan,e o+ ,lass or*er.

,lass at rea)+asten*

' ^D$

Practice (nglish To Code

 Fe&t you should run the scrit with the "english" otion so that you drill the in*erse

oeration. %i*en an 0nglish hrase, write the code for it. Here's me doing that too#

 ruby ex!1.rb englis/a)e a ,lass na(e* rot/er t/at is-a 2ra,)er.

' ,lass rot/er 2ra,)er

A0SW>: ,lass rot/er 2ra,)eren*

?ro( be/avior get t/e ,ent +un,tionF an* ,all it 8it/ para(eters *ressFboar*.

' be/avior.,ent@*erssF boar*

D

Page 77: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 77/128

A0SW>: be/avior.,ent@*ressF boar*

Set bas)et to an instan,e o+ ,lass 2oug/.

' ^D$

Remember that these hrases are using nonsense words. Part of learning to read code well is

to sto lacing so much meaning on the names used for *ariables and classes. Too often

 eole will read a word li!e ";or!" and suddenly get derailed because that word will confuse

them about the meaning. In the abo*e e&amle, ";or!" is ust an arbitrary name chosen for a

class. on't ut any other meaning into it, and instead treat it li!e the atterns I'*e gi*en you.

Reading More Code

+ou are now to go on a new 3uest to read e*en more code and this time, to read the hrases

you ust learned in the code you read. +ou will loo! for all the files with classes, and then do

the following#

$. :or each class gi*e its name and what other classes it inherits from.

. Ender that, list e*ery function it has, and the arameters they ta!e.

(. List all of the attributes it uses on self.

B. :or each attribute, gi*e the class it is.

The goal is to go through real code and start learning to "attern match" the hrases you ust

learned against how they're used. If you drill this enough you should start to see these

 atterns shout at you in the code whereas before they ust seemed li!e *ague blan! sots you

didn't !now.

Exercise (#: IsA/ HasA/ =b@ects/ and

$*asses

Warnin!

This is being rewritten based on the Python *ersion, there may be errors.

-n imortant concet that you ha*e to understand is the difference between a 2lass and anGbRe,t. The roblem is, there is no real "difference" between a class and an obect. They are

actually the same thing at different oints in time. I will demonstrate by a =en !oan#

W/at is t/e *i++eren,e bet8een a ?is/ an* a Sal(onM

id that 3uestion sort of confuse you Really sit down and thin! about it for a minute. I

mean, a :ish and a /almon are different but, wait, they are the same thing right - /almon is

a kind  of :ish, so I mean it's not different. 2ut at the same time, becase a /almon is a

 articular type of :ish and so it's actually different from all other :ish. That's what ma!es it a

/almon and not a Halibut. /o a /almon and a :ish are the same but different. Weird.

Page 78: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 78/128

This 3uestion is confusing because most eole do not thin! about real things this way, but

they intuiti*ely understand them. +ou do not need to thin! about the difference between a

:ish and a /almon because you know how they are related. +ou !now a /almon is a kind  of

:ish and that there are other !inds of :ish without ha*ing to understand that.

Let's ta!e it one ste further, let's say you ha*e a buc!et full of ( /almon and because you area nice erson, you ha*e decided to name them :ran!, <oe, and )ary. Fow, thin! about this

3uestion#

W/at is t/e *i++eren,e bet8een ary an* a Sal(onM

-gain this is a weird 3uestion, but it's a bit easier than the :ish *s. /almon 3uestion. +ou

!now that )ary is a /almon, and so she's not really different. /he's ust a secific "instance"

of a /almon. <oe and :ran! are also instances of /almon. 2ut, what do I mean when I say

instance I mean they were created from some other /almon and now reresent a real thing

that has /almon1li!e attributes.

 Fow for the mind bending idea# :ish is a 2lass, and /almon is a 2lass, and )ary is an

GbRe,t. Thin! about that for a second. -lright let's brea! it down real slow and see if you get

it.

- :ish is a 2lass, meaning it's not a real  thing, but rather a word we attach to instances of

things with similar attributes. %ot fins %ot gills Li*es in water -lright it's robably a :ish.

/omeone with a Ph.. then comes along and says, "Fo my young friend, this :ish is actually

Salmo salar , affectionately !nown as a /almon." This rofessor has ust clarified the :ish

further and made a new 2lass called "/almon" that has more secific attributes. Longer

nose, reddish flesh, big, li*es in the ocean or fresh water, tasty ?!, robably a /almon.

:inally, a coo! comes along and tells the Ph.., "Fo, you see this /almon right here, I'll call

her )ary and I'm going to ma!e a tasty fillet out of her with a nice sauce." Fow you ha*e this

instance of a /almon 5which also is an instance of a :ish6 named )ary turned into something

real that is filling your belly. It has become an GbRe,t.

There you ha*e it# )ary is a !ind of /almon that is a !ind of :ish. GbRe,t is a 2lass is a

2lass.

)o$ This Looks 0n Code

This is a weird concet, but to be *ery honest you only ha*e to worry about it when you ma!e

new classes, and when you use a class. I will show you two tric!s to hel you figure out

whether something is a 2lass or GbRe,t.

:irst, you need to learn two catch hrases "is1a" and "has1a". +ou use the hrase is1a when

you tal! about obects and classes being related to each other by a class relationshi. +ou use

has1a when you tal! about obects and classes that are related only because they re"erence 

each other.

 Fow, go through this iece of code and relace each MM comment with a relacement

comment that says whether the ne&t line reresents an is-a or a /as-a relationshi, and what

4

Page 79: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 79/128

that relationshi is. In the beginning of the code, I'*e laid out a few e&amles, so you ust

ha*e to write the remaining ones.

Remember, is1a is the relationshi between :ish and /almon, while has1a is the relationshi

 between /almon and %ills.

 1  3 ! #  < & 91"111

131!1#11<1&19"13!#

<&93"313333!3#33<3&

39!"!1!!3!!!#!!<!&!9#"#1

##3#!

Ani(al is-a obRe,t loo) at t/e extra ,re*it,lass Ani(alen*

MM,lass Dog Ani(al

  *e+ initialiZe@na(e  MM  _na(e K na(e  en*en*

MM,lass 2at Ani(al

  *e+ initialiZe@na(e  MM  _na(e K na(e  en*en*

MM,lass erson

  *e+ initialiZe@na(e  MM  _na(e K na(e

  erson /as-a pet o+ so(e )in*  _pet K nil  en*

  attrNa,,essor :peten*

MM,lass (ployee erson

  *e+ initialiZe@na(eF salary  MM /(( 8/at is t/is strange (agi,M  super@na(e  MM  _salary K salary  en*

en*

MM,lass ?is/en*

MM,lass Sal(on ?is/

>

Page 80: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 80/128

####<#&#9"

13!#<&9<"<1<<3

<!<#<<<<&<9&"&1&&3&!&#&

&<

en*

MM,lass 7alibut ?is/en*

rover is-a Dogrover K Dog.ne8@B>overB

MMsatan K 2at.ne8@BSatanB

MM(ary K erson.ne8@BaryB

MM(ary.pet K satan

MM+ran) K (ployee.ne8@B?ran)BF 1""""

MM+ran).pet K rover

MM+lipper K ?is/.ne8@

MM,rouse K Sal(on.ne8@

MM

/arry K 7alibut.ne8@

Extra Credit

$. Is it ossible to use a 2lass li!e it's an GbRe,t

. :ill out the animals, fish, and eole in this e&ercise with functions that ma!e them do

things. /ee what haens when functions are in a "base class" li!e -nimal *s. in say

og.

(. :ind other eole's code and wor! out all the is1a and has1a relationshis.

B. )a!e some new relationshis that are lists and dicts so you can also ha*e "has1many"

relationshis.

C. o you thin! there's a such thing as a "is1many" relationshi Read about "multile

inheritance", then a*oid it if you can.

Exercise (%: Gothons Fro" *anet erca*

B#+

Warnin!

This is being rewritten based on the Python *ersion, there may be errors.

Here is a new game, using what you'*e learned so far and some new tric!s.

48

Page 81: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 81/128

  1    3  !  # 

  <  &  9 1" 11 1 13 1! 1# 1 1< 1& 19

 " 1  3 ! #  < & 9 3" 31 3

 33 3! 3# 3 3< 3& 39 !" !1 ! !3 !! !#

 ! !< !& !9 #" #1 # #3 #! ## # #< #& #9 " 1

,lass Xa(e

  *e+ initialiZe@start  _uips K   BEou *ie*. Eou )in*a su,) at t/is.BF  B0i,e RobF you *ie* ...Ra,)ass.BF

  BSu,/ a luser.BF  B= /ave a s(all puppy t/ats better at t/is.B  U  _start K start  en*

  *e+ pro(pt@  print B' B  en*

  *e+ play@  nextNroo( K _start

  8/ile true  puts B5n--------B  roo( K (et/o*@nextNroo(  nextNroo( K roo(.,all@  en*  en*

  *e+ *eat/@  puts _uipsran*@_uips.lengt/@U  ro,ess.exit@1  en*

  *e+ ,entralN,orri*or@

  puts BT/e Xot/ons o+ lanet er,al # /ave inva*e* your s/ip an**estroye*B  puts Byour entire ,re8. Eou are t/e last surviving (e(ber an* yourlastB  puts B(ission is to get t/e neutron *estru,t bo(b +ro( t/e WeaponsAr(oryFB  puts Bput it in t/e bri*geF an* blo8 t/e s/ip up a+ter getting intoan B  puts Bes,ape po*.B  puts B5nB  puts BEoure running *o8n t/e ,entral ,orri*or to t/e Weapons Ar(ory8/enB  puts Ba Xot/on Ru(ps outF re* s,aly s)inF *ar) gri(y teet/F an* evil

,lo8n ,ostu(eB  puts B+lo8ing aroun* /is /ate +ille* bo*y. 7es blo,)ing t/e *oorto t/eB  puts BAr(ory an* about to pull a 8eapon to blast you.B

  pro(pt@  a,tion K gets.,/o(p@

  i+ a,tion KK Bs/ootCB  puts B4ui,) on t/e *ra8 you yan) out your blaster an* +ire it att/e Xot/on.B  puts B7is ,lo8n ,ostu(e is +lo8ing an* (oving aroun* /is bo*yF8/i,/ t/ro8sB  puts Bo++ your ai(. Eour laser /its /is ,ostu(e but (isses /i(entirely. T/isB  puts B,o(pletely ruins /is bran* ne8 ,ostu(e /is (ot/er boug/t

4$

Page 82: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 82/128

  3 ! #  <

 & 9 <" <1 < <3 <! <# < << <& <9 &"

 &1 & &3 &! &# & &< && &9 9" 91 9 93

 9! 9# 9 9< 9& 991""1"11"1"31"!1"#1"

1"<1"&1"911"1111111311!11#1111<11&1191"111

/i(F 8/i,/B  puts B(a)es /i( +ly into an insane rage an* blast you repeate*lyin t/e +a,e untilB  puts Byou are *ea*. T/en /e eats you.B  return :*eat/

  elsi+ a,tion KK B*o*geCB  puts BLi)e a 8orl* ,lass boxer you *o*geF 8eaveF slip an* sli*erig/tB  puts Bas t/e Xot/ons blaster ,ran)s a laser past your /ea*.B  puts B=n t/e (i**le o+ your art+ul *o*ge your +oot slips an* youB  puts Bbang your /ea* on t/e (etal 8all an* pass out.B  puts BEou 8a)e up s/ortly a+ter only to *ie as t/e Xot/on sto(psonB  puts Byour /ea* an* eats you.B  return :*eat/

  elsi+ a,tion KK Btell a Ro)eB  puts BLu,)y +or you t/ey (a*e you learn Xot/on insults in t/e

a,a*e(y.B  puts BEou tell t/e one Xot/on Ro)e you )no8:B  puts BLb/e Zbgure v+ +b sngF Rura +ur +vg+ neb/a gur ub/+rF +ur+vg+ neb/a gur ub/+r.B  puts BT/e Xot/on stopsF tries not to laug/F t/en busts outlaug/ing an* ,ant (ove.B  puts BW/ile /es laug/ing you run up an* s/oot /i( suare in t/e/ea*B  puts Bputting /i( *o8nF t/en Ru(p t/roug/ t/e Weapon Ar(ory *oor.B  return :laserN8eaponNar(ory

  else  puts BDGS 0GT 2GTCB

  return :,entralN,orri*or  en*  en*

  *e+ laserN8eaponNar(ory@  puts BEou *o a *ive roll into t/e Weapon Ar(oryF ,rou,/ an* s,an t/eroo(B  puts B+or (ore Xot/ons t/at (ig/t be /i*ing. =ts *ea* uietF toouiet.B  puts BEou stan* up an* run to t/e +ar si*e o+ t/e roo( an* +in* t/eB  puts Bneutron bo(b in its ,ontainer. T/eres a )eypa* lo,) on t/eboxB  puts Ban* you nee* t/e ,o*e to get t/e bo(b out. =+ you get t/e

,o*eB  puts B8rong 1" ti(es t/en t/e lo,) ,loses +orever an* you ,antB  puts Bget t/e bo(b. T/e ,o*e is 3 *igits.B  ,o*e K BJsJsJsB J ran*@91F ran*@91F ran*@91U  print B)eypa*U' B  guess K gets.,/o(p@  guesses K "

  8/ile guess CK ,o*e an* guesses 1"  puts B6666DDDCB  guesses K 1  print B)eypa*U' B  guess K gets.,/o(p@  en*

4

Page 83: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 83/128

131!1#11<1&

1913"1311313313!13#1313<13&1391!"1!1

1!1!31!!1!#1!1!<1!&1!91#"1#11#1#31#!

1##1#1#<1#&1#91"111131!1#11<

1&191<"1<11<1<31<!1<#1<1<<1<&1<91&"1&11&1&3

  i+ guess KK ,o*e  puts BT/e ,ontainer ,li,)s open an* t/e seal brea)sF letting gasout.B  puts BEou grab t/e neutron bo(b an* run as +ast as you ,an to t/eB  puts Bbri*ge 8/ere you (ust pla,e it in t/e rig/t spot.B  return :t/eNbri*ge

  else  puts BT/e lo,) buZZes one last ti(e an* t/en you /ear a si,)eningB  puts B(elting soun* as t/e (e,/anis( is +use* toget/er.B  puts BEou *e,i*e to sit t/ereF an* +inally t/e Xot/ons blo8 upt/eB  puts Bs/ip +ro( t/eir s/ip an* you *ie.B  return :*eat/  en*  en*

  *e+ t/eNbri*ge@  puts BEou burst onto t/e ri*ge 8it/ t/e neutron *estru,t bo(bB  puts Bun*er your ar( an* surprise # Xot/ons 8/o are trying toB

  puts Bta)e ,ontrol o+ t/e s/ip. a,/ o+ t/e( /as an even uglierB  puts B,lo8n ,ostu(e t/an t/e last. T/ey /avent pulle* t/eirB  puts B8eapons out yetF as t/ey see t/e a,tive bo(b un*er yourB  puts Bar( an* *ont 8ant to set it o++.B

  pro(pt@  a,tion K gets.,/o(p@

  i+ a,tion KK Bt/ro8 t/e bo(bB  puts B=n a pani, you t/ro8 t/e bo(b at t/e group o+ Xot/onsB  puts Ban* (a)e a leap +or t/e *oor. >ig/t as you *rop it aB  puts BXot/on s/oots you rig/t in t/e ba,) )illing you.B  puts BAs you *ie you see anot/er Xot/on +ranti,ally try to *isar(B

  puts Bt/e bo(b. Eou *ie )no8ing t/ey 8ill probably blo8 up 8/enB  puts Bit goes o++.B  return :*eat/

  elsi+ a,tion KK Bslo8ly pla,e t/e bo(bB  puts BEou point your blaster at t/e bo(b un*er your ar(B  puts Ban* t/e Xot/ons put t/eir /an*s up an* start to s8eat.B  puts BEou in,/ ba,)8ar* to t/e *oorF open itF an* t/en ,are+ullyB  puts Bpla,e t/e bo(b on t/e +loorF pointing your blaster at it.B  puts BEou t/en Ru(p ba,) t/roug/ t/e *oorF pun,/ t/e ,lose buttonB  puts Ban* blast t/e lo,) so t/e Xot/ons ,ant get out.B  puts B0o8 t/at t/e bo(b is pla,e* you run to t/e es,ape po* toB  puts Bget o++ t/is tin ,an.B

  return :es,apeNpo*  else  puts BDGS 0GT 2GTCB  return :t/eNbri*ge  en*  en*

  *e+ es,apeNpo*@  puts BEou rus/ t/roug/ t/e s/ip *esperately trying to (a)e it toB  puts Bt/e es,ape po* be+ore t/e 8/ole s/ip explo*es. =t see(s li)eB  puts B/ar*ly any Xot/ons are on t/e s/ipF so your run is ,lear o+B  puts Binter+eren,e. Eou get to t/e ,/a(ber 8it/ t/e es,ape po*sFan*B  puts Bno8 nee* to pi,) one to ta)e. So(e o+ t/e( ,oul* be *a(age*B  puts Bbut you *ont /ave ti(e to loo). T/eres # po*sF 8/i,/ oneB  puts B*o you ta)eMB

4(

Page 84: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 84/128

  goo*Npo* K ran*@#1print Bpo* U'B

  guess K gets.,/o(p@

  i+ guess.toNi CK goo*Npo*

  puts BEou Ru(p into po* Js an* /it t/e eRe,t button.B J guess  puts BT/e po* es,apes out into t/e voi* o+ spa,eF t/enB  puts Bi(plo*es as t/e /ull rupturesF ,rus/ing your bo*yB  puts Binto Ra( Relly.B  return :*eat/  else  puts BEou Ru(p into po* Js an* /it t/e eRe,t button.B J guess  puts BT/e po* easily sli*es out into spa,e /ea*ing toB  puts Bt/e planet belo8. As it +lies to t/e planetF you loo)B  puts Bba,) an* see your s/ip i(plo*e t/en explo*e li)e aB  puts Bbrig/t starF ta)ing out t/e Xot/on s/ip at t/e sa(eB  puts Bti(e. Eou 8onCB  ro,ess.exit@"

  en*  en*en*

aNga(e K Xa(e.ne8@:,entralN,orri*oraNga(e.play@

It's a lot of code, but go through it, ma!e sure it wor!s, lay it.

What "o# Sho#ld See

Here's me laying the game.

$ ruby exHex!3.rb--------T/e Xot/ons o+ lanet er,al # /ave inva*e* your s/ip an* *estroye*your entire ,re8. Eou are t/e last surviving (e(ber an* your last(ission is to get t/e neutron *estru,t bo(b +ro( t/e Weapons Ar(oryFput it in t/e bri*geF an* blo8 t/e s/ip up a+ter getting into anes,ape po*.

Eoure running *o8n t/e ,entral ,orri*or to t/e Weapons Ar(ory 8/ena Xot/on Ru(ps outF re* s,aly s)inF *ar) gri(y teet/F an* evil ,lo8n,ostu(e+lo8ing aroun* /is /ate +ille* bo*y. 7es blo,)ing t/e *oor to t/eAr(ory an* about to pull a 8eapon to blast you.' tell a Ro)eLu,)y +or you t/ey (a*e you learn Xot/on insults in t/e a,a*e(y.Eou tell t/e one Xot/on Ro)e you )no8:Lb/e Zbgure v+ +b sngF Rura +ur +vg+ neb/a gur ub/+rF +ur +vg+ neb/a gurub/+r.T/e Xot/on stopsF tries not to laug/F t/en busts out laug/ing an* ,ant(ove.W/ile /es laug/ing you run up an* s/oot /i( suare in t/e /ea*putting /i( *o8nF t/en Ru(p t/roug/ t/e Weapon Ar(ory *oor.

--------Eou *o a *ive roll into t/e Weapon Ar(oryF ,rou,/ an* s,an t/e roo(+or (ore Xot/ons t/at (ig/t be /i*ing. =ts *ea* uietF too uiet.Eou stan* up an* run to t/e +ar si*e o+ t/e roo( an* +in* t/e

4B

Page 85: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 85/128

neutron bo(b in its ,ontainer. T/eres a )eypa* lo,) on t/e boxan* you nee* t/e ,o*e to get t/e bo(b out. =+ you get t/e ,o*e8rong 1" ti(es t/en t/e lo,) ,loses +orever an* you ,antget t/e bo(b. T/e ,o*e is 3 *igits.)eypa*U' 6666DDDC

)eypa*U' !#6666DDDC)eypa*U' 39#T/e ,ontainer ,li,)s open an* t/e seal brea)sF letting gas out.Eou grab t/e neutron bo(b an* run as +ast as you ,an to t/ebri*ge 8/ere you (ust pla,e it in t/e rig/t spot.

--------Eou burst onto t/e ri*ge 8it/ t/e neutron *estru,t bo(bun*er your ar( an* surprise # Xot/ons 8/o are trying tota)e ,ontrol o+ t/e s/ip. a,/ o+ t/e( /as an even uglier,lo8n ,ostu(e t/an t/e last. T/ey /avent pulle* t/eir8eapons out yetF as t/ey see t/e a,tive bo(b un*er your

ar( an* *ont 8ant to set it o++.' t/ro8 t/e bo(b=n a pani, you t/ro8 t/e bo(b at t/e group o+ Xot/onsan* (a)e a leap +or t/e *oor. >ig/t as you *rop it aXot/on s/oots you rig/t in t/e ba,) )illing you.As you *ie you see anot/er Xot/on +ranti,ally try to *isar(t/e bo(b. Eou *ie )no8ing t/ey 8ill probably blo8 up 8/enit goes o++.

--------= /ave a s(all puppy t/ats better at t/is.

(%tra Credit 

$. 0&lain how returning the ne&t room wor!s.

. -dd cheat codes to the game so you can get ast the more difficult rooms. I can do

this with two words on one line.

(. Instead of ha*ing each function rint itself, learn about "doc string" style comments.

Write the room descrition as doc comments, and change the runner to rint them.

B. ?nce you ha*e doc comments as the room descrition, do you need to ha*e the

function romt e*en Ha*e the runner romt the user, and ass that in to each

function. +our functions should ust be if1statements rinting the result and returning

the ne&t room.

C. This is actually a small *ersion of something called a "finite state machine". Read

about them. They might not ma!e sense but try anyway.D. I ha*e a bug in this code. Why is the door loc! guessing $$ times

Exercise ((: Inheritance )sC $o"position

Warning

This is being rewritten based on the Python *ersion, there may be errors.

In the fairy tales about heroes defeating e*il *illains there's always a dar! forest of some !ind.

It could be a ca*e, a forest, another lanet, ust some lace that e*eryone !nows the heroshouldn't go. ?f course, shortly after the *illain is introduced you find out, yes, the hero has

4C

Page 86: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 86/128

to go to that stuid forest to !ill the bad guy. It seems the hero ust !ees getting into

situations that re3uire him to ris! his life in this e*il forest.

+ou rarely read fairy tales about the heroes who are smart enough to ust a*oid the whole

situation entirely. +ou ne*er hear a hero say, "Wait a minute, if I lea*e to ma!e my fortunes

on the high seas lea*ing 2uttercu behind I could die and then she'd ha*e to marry some ugly rince named Humerdin!. Humerdin!O I thin! I'll stay here and start a :arm 2oy :or Rent

 business." If he did that there'd be no fire swam, dying, reanimation, sword fights, giants, or

any !ind of story really. 2ecause of this, the forest in these stories seems to e&ist li!e a blac!

hole that drags the hero in no matter what they do.

In obect oriented rogramming, Inheritance is the e*il forest. 0&erienced rogrammers

!now to a*oid this e*il because they !now that dee inside the ar! :orest Inheritance is the

0*il ueen )eta1Programming. /he li!es to eat software and rogrammers with her massi*e

comle&ity teeth, chewing on the flesh of the fallen. 2ut, the forest is so owerful and so

temting that nearly e*ery rogrammer has to go into it, and try to ma!e it out ali*e with the

0*il ueen's head before they can call themsel*es real rogrammers. +ou ust can't resist theInheritance :orest's ull, so you go in. -fter the ad*enture you learn to ust stay out of that

stuid forest and bring and army if you are e*er forced to go in again.

This is basically a funny way to say that I'm going to teach you something you should a*oid

called Inheritance. Programmers who are currently in the forest battling the ueen will

 robably tell you that you ha*e to go in. They say this because they need your hel since

what they'*e created is robably too much for them to handle. 2ut, you should always

remember this#

)ost of the uses of inheritance can be simlified or relaced with comosition, and meta1

 rogramming should be used saringly.

What 0s 0nheritance4 

Inheritance is used to indicate that one class will get most or all of its features from a arent

class. This haens imlicitly whene*er you write ,lass ?oo ar which says ")a!e a

class :oo that inherits from 2ar." When you do this, the language ma!es any action that you

do on instances of !oo also wor! as if they were done to an instance of  Bar . oing this lets

you ut common functionality in the Bar  class, then secialiGe that functionality in the !oo 

class as needed.

When you are doing this !ind of secialiGation, there's three ways that the arent and child

classes can interact#

$. -ctions on the child imly an action on the arent.

. -ctions on the child o*erride the action on the arent.

(. -ctions on the child alter the action on the arent.

I will now demonstrate each of these in order and show you code for them.

4D

Page 87: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 87/128

Implicit Inheritance

:irst I will show you the imlicit actions that haen when you define a function in the

 arent, but not  in the child.

 1  3 ! #  < & 91"11113

1!1#

,lass arent

  *e+ i(pli,it@  puts BA>0T i(pli,it@B  en*en*

,lass 2/il* arenten*

*a* K arent.ne8@son K 2/il*.ne8@

*a*.i(pli,[email protected](pli,it@

This creates a class named 2hild  but says that there's nothing new to define in it. Instead it

will inherit all of its beha*ior from Parent . When you run this code you get the following#

A>0T i(pli,it@A>0T i(pli,it@

 Fotice how e*en though I'm calling son.i(pli,it@ on line $D, and e*en though 2hild  does

not  ha*e a implicit  function defined, it still wor!s and it calls the one defined in  Parent . This

shows you that, if you ut functions in a base class 5i.e.  Parent 6 then all subclasses 5i.e.2hild 6 will automatically get those features. @ery handy for reetiti*e code you need in many

classes.

Override Explicitly

The roblem with imlicitly ha*ing functions called is sometimes you want the child to

 beha*e differently. In this case you want to o*erride the function in the child, effecti*ely

relacing the functionality. To do this ust define a function with the same name in 2hild .

Here's an e&amle#

 1  3 ! #  < & 91"11113

1!1#

,lass arent

  *e+ overri*e@  puts BA>0T overri*e@B  en*en*

,lass 2/il* arent 

*e+ overri*e@  puts B27=LD overri*e@B  en*en*

*a* K arent.ne8@

4

Page 88: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 88/128

11<1&19

son K 2/il*.ne8@

*a*.overri*[email protected]*e@

In this e&amle e&amle I ha*e a function named override in both classes, so let's see what

haens when you run it.

A>0T overri*e@27=LD overri*e@

-s you can see, when line $B runs, it runs the Parent%override function because that *ariabe

5dad 6 is a Parent . 2ut, when line $C runs it rints out the 2hild%override messages because

 son is an instance of 2hild  and child o*errides that function by defining it's own *ersion.

Ta!e a brea! right now and try laying with these two concets before continuing.

Alter Before Or After 

The third way to use inheritance is a secial case of o*erriding where you want to alter the

 beha*ior before or after you the arent class's *ersion runs. +ou first o*erride the function

 ust li!e in the last e&amle, but then you use a Ruby built1in function named super  to get the

 Parent  *ersion to call. Here's the e&amle of doing that so you can ma!e sense of this

descrition#

 1  3

 ! #  < & 91"111131!1#1

1<1&19"13

,lass arent

  *e+ altere*@

  puts BA>0T altere*@B  en*

en*

,lass 2/il* arent

  *e+ altere*@  puts B27=LDF ?G> A>0T altere*@B  super@  puts B27=LDF A?T> A>0T altere*@B  en*

en*

*a* K arent.ne8@son K 2/il*.ne8@

*a*.altere*@son.altere*@

The imortant lines here are >1$$, where in the child I do the following when

son.altere*@ is called#

$. 2ecause I'*e o*erridden Parent%altered  the 2hild%altered  *ersion runs, and line >

e&ecutes li!e you'd e&ect.

44

Page 89: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 89/128

. In this case I want to do a before and after so after line >, I want to use super  to get

the Parent%altered  *ersion.

(. ?n line $8 I call super@, which reaeats this function call on the arent class.

B. -t this oint, the Parent%altered  *ersion of the function runs, and that rints out the

 arent message.

C. :inally, this returns from the Parent%altered  and the 2hild%altered  function continuesto rint out the after message.

If you then run this you should see this#

A>0T altere*@27=LDF ?G> A>0T altere*@A>0T altere*@27=LDF A?T> A>0T altere*@

All Three Combined

To demonstrate all of these, I ha*e a final *ersion that shows each !ind of interaction from

inheritance in one file#

 1  3 ! #  < & 9

1"111131!1#11<1&19"1

3!#<&93"313333!3#

33<

,lass arent

  *e+ overri*e@  puts BA>0T overri*e@B  en*

  *e+ i(pli,it@  puts BA>0T i(pli,it@B  en*

  *e+ altere*@  puts BA>0T altere*@B  en*en*

,lass 2/il* arent 

*e+ overri*e@  puts B27=LD overri*e@B  en*

  *e+ altere*@

  puts B27=LDF ?G> A>0T altere*@B  super@  puts B27=LDF A?T> A>0T altere*@B  en*en*

*a* K arent.ne8@son K 2/il*.ne8@

*a*.i(pli,[email protected](pli,it@

*a*.overri*e@

son.overri*e@

4>

Page 90: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 90/128

3&39

*a*.altere*@son.altere*@

%o through each line of this code, and write a comment e&laining what that line does and

whether it's an o*erride or not. Then, run it and see that you get what you e&ected#

A>0T i(pli,it@A>0T i(pli,it@A>0T overri*e@27=LD overri*e@A>0T altere*@27=LDF ?G> A>0T altere*@A>0T altere*@27=LDF A?T> A>0T altere*@

The Reason &or s#per56

In the 2hild%altered,- function I used a secial function named super,-. This isn't a functionyou define, but instead one Ruby gi*es you. This function figures out how to call the same

function, but in a arent class. The reason you need a secial function is that what is "the

 arent class" is a bit comle&. It relies on Ruby !nowing the full inheritance structure of the

current class, and any ossible modules you'*e added to it with mi&ins 5which I'll show you

soon6. 2y using super,- you don't need to worry about figuring this out and can ust let Ruby

do it.

+ou use super,- by assing it the right number of arguments for the arent class's argument

count. In the e&amle abo*e, neither *ersion of altered,- had arguments, so I ust called

 super,-. If the class Parent  had arguments, then I'd add them to the super,- call.

Uin! uper"# With initiali$e

The most common use of super,- is actually in initiali.e functions in base classes. This is

usually the only lace where you need to do some things in a child, then comlete the

initialiGation in the arent. Here's a 3uic! e&amle of doing that in the 2hild  from these

e&amles#

,lass 2/il* arent  *e+ initialiZe@sel+F stu++:  sel+.stu++ K stu++  super@  en*en*

This is retty much the same as the 2hild%altered  e&amle abo*e, e&cet I'm setting some

*ariables in the initiali.e before ha*ing the Parent  initialiGe with its Parent%initiali.e.

Co+position

Inheritance is useful, but another way to do the e&act same thing is ust to use other classes

and modules, rather than rely on imlicit inheritance. If you loo! at the three ways to e&loit

inheritance, two of the three in*ol*e writing new code to relace or alter functionality. This

>8

Page 91: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 91/128

can easily be relicated by ust calling functions on another class or from a module. Here's an

e&amle of doing this#

 1  3 ! #  < & 91"111131!1#11<1&19"13!#<&93"313333!3#33<3&39!"!1

,lass Gt/er

  *e+ overri*e@  puts BGT7> overri*e@B  en*

  *e+ i(pli,it@  puts BGT7> i(pli,it@B  en*

  *e+ altere*@  puts BGT7> altere*@B  en*en*

,lass 2/il*

  *e+ initialiZe@  _ot/er K Gt/er.ne8@  en*

  *e+ i(pli,it@  _ot/er.i(pli,it@  en* 

*e+ overri*e@  puts B27=LD overri*e@B  en*

  *e+ altere*@  puts B27=LDF ?G> GT7> altere*@B  _ot/er.altere*@  puts B27=LDF A?T> GT7> altere*@B  en*en*

son K 2/il*.ne8@

son.i(pli,[email protected]*[email protected]*@

In this code I'm not using the name Parent , since there is not  a arent1child is1a relationshi.

This is a has1a relationshi, where 2hild  has1a 3ther  that it uses to get its wor! done. When I

run this I get the following outut#

GT7> i(pli,it@27=LD overri*e@27=LDF ?G> GT7> altere*@GT7> altere*@27=LDF A?T> GT7> altere*@

+ou can see that most of the code in 2hild  and 3ther  is the same to accomlish the same

thing. The only difference is that I had to define a 2hild%implicit  function to do that one

>$

Page 92: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 92/128

action. I could then as! myself if I need this 3ther  to be a class, and could I ust ma!e it into

a module named 3ther . I totally could ma!e this into a module instead#

 1  3 ! #  < & 91"111131!1#11<1&19"13!#<&93"313333!3#33<

(o*ule Gt/er

  *e+ Gt/er.overri*e@  puts BGT7> overri*e@B  en*

  *e+ Gt/er.i(pli,it@  puts BGT7> i(pli,it@B  en*

  *e+ Gt/er.altere*@  puts BGT7> altere*@B  en*en*

,lass 2/il*

  *e+ i(pli,it@  Gt/er.i(pli,it@  en* 

*e+ overri*e@  puts B27=LD overri*e@B  en*

  *e+ altere*@  puts B27=LDF ?G> GT7> altere*@B  Gt/er.altere*@  puts B27=LDF A?T> GT7> altere*@B  en*en*

son K 2/il*.ne8@

son.i(pli,[email protected]*[email protected]*@

 Fearly the e&act same thing ust using a module. The choice of which is better in the abo*e

code 5class 3ther  *s. module 3ther 6 deends on if you need to maintain state in each

function call in 3ther . If each function can stand on its own, and they're mostly utilities then

use a module. If howe*er the set of functions ma!e u a cohesi*e "thing" that !ees state thenuse a class.

When To ,se 0nheritance Or Co+position

The 3uestion of "inheritance *s. comosition" comes down to an attemt to sol*e the roblem

of reusable code. +ou don't want to ha*e dulicated code all o*er your code, since that's not

clean and efficient. Inheritance sol*es this roblem by creating a mechanism for you to ha*e

imlied features in base classes. ;omosition sol*es this by gi*ing you modules and the

ability to simly call functions in other classes.

>

Page 93: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 93/128

If both solutions sol*e the roblem of reuse, then which one is aroriate in which

situations The answer is incredibly subecti*e, but I'll gi*e you my three guidelines for when

to do which#

$. -*oid meta1rogramming at all costs, as it's too comle& to be useful reliably. If

you're stuc! with it, then be reared to send time finding where e*erything iscoming from.

. Ese comosition to ac!age u code into modules that is used in many different

unrelated laces and situations.

(. Ese inheritance only when there are clearly related reusable ieces of code that fit

under a single common concet, or if you ha*e to because of something you're using.

Howe*er, do not be a sla*e to these rules. The thing to remember about obect oriented

 rogramming is that it is entirely a social con*ention rogrammers ha*e created to ac!age

and share code. 2ecause it's a social con*ention, but one that's codified in Ruby, you may be

forced to a*oid these rules because of the eole you wor! with. In that case, find out how

they use things and then ust adat to the situation.

(%tra Credit 

There is only one e&tra credit for this e&ercise because it is a big e&ercise. %o and read this

htts#AAgithub.comAstyleguideAruby and start trying to use it in your code. +ou'll notice that

some of it is different from what you'*e been learning in this boo!, but now you should be

able to understand their recommendations and use them in your own code. The rest of the

code in this boo! may or may not follow these guidelines deending on if it ma!es the code

more confusing. I suggest you also do this, as comrehension is more imortant than

imressing e*eryone with you !nowledge of esoteric style rules.

Exercise (+: 7ou 'a2e A Ga"e

+ou need to start learning to feed yourself. Hoefully as you ha*e wor!ed through this boo!,

you ha*e learned that all the information you need is on the internet, you ust ha*e to go

search for it. The only thing you ha*e been missing are the right words and what to loo! for

when you search. Fow you should ha*e a sense of it, so it's about time you struggled through

a big roect and tried to get it wor!ing.

Here are your re3uirements#

$. )a!e a different game from the one I made.

. Ese more than one file, and use reuire to use them. )a!e sure you !now what that

is.

(. Ese one class er room and gi*e the classes names that fit their urose. Li!e

Xol*>oo(, \oion*>oo(.

B. +our runner will need to !now about these rooms, so ma!e a class that runs them and

!nows about them. There's lenty of ways to do this, but consider ha*ing each room

return what room is ne&t or setting a *ariable of what room is ne&t.

>(

Page 94: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 94/128

?ther than that I lea*e it to you. /end a whole wee! on this and ma!e it the best game you

can. Ese classes, functions, dicts, lists anything you can to ma!e it nice. The urose of this

lesson is to teach you how to structure classes that need other classes inside other files.

Remember, I'm not telling you e&actly how to do this because you ha*e to do this yourself.

%o figure it out. Programming is roblem sol*ing, and that means trying things,e&erimenting, failing, scraing your wor!, and trying again. When you get stuc!, as! for

hel and show eole your code. If they are mean to you, ignore them, focus on the eole

who are not mean and offer to hel. 7ee wor!ing it and cleaning it until it's good, then show

it some more.

%ood luc!, and see you in a wee! with your game.

Exercise (,: A ro@ect S2e*eton

This will be where you start learning how to setu a good roect "s!eleton" directory. Thiss!eleton directory will ha*e all the basics you need to get a new roect u and running. It

will ha*e your roect layout, automated tests, modules, and install scrits.

Skeleton Contents! Lin#%7OS 

:irst, create the structure of your s!eleton directory with these commands#

$ ()*ir -p proRe,ts$ ,* proRe,tsH$ ()*ir s)eleton

$ ,* s)eleton$ ()*ir bin lib libH0A test

I use a directory named roects to store all the *arious things I'm wor!ing on. Inside that

directory I ha*e my s!eleton directory that I ut the basis of my roects into. The directory

 F-)0 will be renamed to whate*er you are calling your roect's main module when you

use the s!eleton.

 Fe&t we need to setu some initial files#

$ tou,/ libH0A.rb

$ tou,/ libH0AHversion.rb

Then we can create a 0A.ge(spe, file in our roect's root directory which we can use to

install our roect later if we want#

 1  3 ! #  <

 & 91"

-I- en,o*ing: ut+-& -I-$:.pus/ ?ile.expan*Npat/@B..HlibBF NN?=LNNreuire B0AHversionB

Xe(::Spe,i+i,ation.ne8 *o YsY  s.na(e K B0AB  s.version K 0A::;>S=G0

  s.aut/ors K B>ob SobersBU  s.e(ail K Brsobers_g(ail.,o(BU  s./o(epage K BB

>B

Page 95: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 95/128

111131!1#11<1&19"

  s.su((ary K JOTGDG: Write a ge( su((aryP  s.*es,ription K JOTGDG: Write a ge( *es,riptionP

  s.ruby+orgeNproRe,t K B0AB

  s.+iles K Qgit ls-+ilesQ.split@B5nB

  s.testN+iles K Qgit ls-+iles -- OtestFspe,F+eaturesPHIQ.split@B5nB  s.exe,utables K Qgit ls-+iles -- binHIQ.split@B5nB.(apO Y+Y?ile.basena(e@+ P  s.reuireNpat/s K BlibBUen*

0dit this file so that it has your contact information and is ready to go for when you coy it.

:inally you will want a simle s!eleton file for unit tests 5which will tal! about more in the

ne&t lesson6 named testHtestN0A.rb#

 1

  3 ! #  < & 91"111131!

1#11<

reuire testHunit

,lass ynitTests Test::nit::Test2ase

  *e+ setup  puts BsetupCB  en*

  *e+ tear*o8n  puts Btear*o8nCB  en*

  *e+ testNbasi,  puts B= >A0CB

  en*

en*

0nstalling 3e+s

%ems are ac!ages of Ruby code that hel you get things done, so you will need to !now

how to install them and use them. Here's the roblem though. +ou are at a oint where it's

difficult for me to hel you do that and !ee this boo! sane and clean. There are so many

ways to install software on so many comuters that I'd ha*e to send $8 ages wal!ing you

through e*ery ste, and let me tell you I am a laGy guy.

Rather than tell you how to do it e&actly, I'm going to tell you what you should install, and

then tell you to figure it out and get it wor!ing. This will be really good for you since it will

oen a whole world of software you can use that other eole ha*e released to the world.

 Fe&t, install the following software ac!ages#

• git 1 htt#AAgit1scm.comA

• ra!e 1 htt#AAra!e.rubyforge.orgA

• r*m 1 htts#AAr*m.beginrescueend.comA

• rubygems 1 htt#AArubygems.orgAagesAdownload

•  bundler 1 htt#AAgembundler.comA

>C

Page 96: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 96/128

o not ust download these ac!ages and install them by hand. Instead see how other eole

recommend you install these ac!ages and use them for your articular system. The rocess

will be different for most *ersions of Linu&, ?/K, and definitely different for Windows.

I am warning you, this will be frustrating. In the business we call this "ya! sha*ing". +a!

sha*ing is any acti*ity that is mind numblingly irritatingly boring and tedious that you ha*eto do before you can do something else that's more fun. +ou want to create cool Ruby

 roects, but you can't do that until you setu a s!eleton directory, but you can't setu a

s!eleton directory until you install some ac!ages, but you can't install ac!ages until you

install ac!age installers, and you can't install ac!age installers until you figure out how

your system installs software in general, and so on.

/truggle through this anyway. ;onsider it your trial1by1annoyance to get into the rogrammer

club. 0*ery rogrammer has to do these annoying tedious tas!s before they can do something

cool.

,sing The Skeleton

+ou are now done with most of your ya! sha*ing. Whene*er you want to start a new roect,

 ust do this#

$. )a!e a coy of your s!eleton directory. Fame it after your new roect.

. Rename 5mo*e6 the F-)0 directory and 0A.rb file to be the name of your roect.

(. 0dit your 0A.ge(spe, file to ha*e all the information for your roect.

B. Rename testHtestN0A.rb  to also ha*e your roect name.

C. /tart coding.

Re8#ired 9#i: 

This e&ercise doesn't ha*e e&tra credit but a 3uiG you should comlete#

$. Read about how to use all of the things you installed.

. Read about the 0A.ge(spe, file and all it has to offer.

(. )a!e a roect and start writing some code in the 0A.rb scrit.

B. Put a scrit in the bin directory that you can run. Read about how you can ma!e a

Ruby scrit that's runnable for your system.

C. )a!e sure the bin scrit you created is referenced in your 0A.ge(spe, so that it

gets installed.

D. Ese your 0A.ge(spe, and ge( buil* ge( install to install your own library and

ma!e sure it wor!s, then use ge( uninstall to uninstall it.

. :igure out how you can use 2undler to generate a s!eleton directory automatically.

Exercise (-: Auto"ated Testin!

Ha*ing to tye commands into your game o*er and o*er to ma!e sure it's wor!ing is

annoying. Wouldn't it be better to write little ieces of code that test your code Then when

you ma!e a change, or add a new thing to your rogram, you ust "run your tests" and the

>D

Page 97: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 97/128

tests ma!e sure things are still wor!ing. These automated tests won't catch all your bugs, but

they will cut down on the time you send reeatedly tying and running your code.

0*ery e&ercise after this one will not ha*e a W/at Eou S/oul* See se,tion, but instead it

will ha*e a W/at Eou S/oul* Test se,tion. +ou will be writing automated tests for all of

your code starting now, and this will hoefully ma!e you an e*en better rogrammer.

I won't try to e&lain why you should write automated tests. I will only say that, you are

trying to be a rogrammer, and rogrammers automate boring and tedious tas!s. Testing a

 iece of software is definitely boring and tedious, so you might as well write a little bit of

code to do it for you.

That should be all the e&lanation you need because your reason for writing unit tests is to

ma!e your brain stronger. +ou ha*e gone through this boo! writing code to do things. Fow

you are going to ta!e the ne&t lea and write code that !nows about other code you ha*e

written. This rocess of writing a test that runs some code you ha*e written forces you to

understand clearly what you ha*e ust written. It solidifies in your brain e&actly what it does

and why it wor!s and gi*es you a new le*el of attention to detail.

Writing A Test Case

We're going to ta!e a *ery simle iece of code and write one simle test. We're going to

 base this little test on a new roect from your roect s!eleton.

:irst, ma!e a ex!< roect from your roect s!eleton. )a!e sure you do it right and rename

the library and get that first ex!<HtestHtestNex!<.rb  test file going right.

 Fe&t, create a simle file ex!<HlibHex!<.rb where you can ut the code to test. This will be

a *ery silly little class that we want to test with this code in it#

 1  3 ! #  < &

 91"111131!1#11<1&19

,lass >oo(

  attrNa,,essor :na(eF :*es,riptionF :pat/s

  *e+ initialiZe@na(eF *es,ription  _na(e K na(e  _*es,ription K *es,ription  _pat/s K OP

  en*

  *e+ go@*ire,tion  _pat/s*ire,tionU  en*

  *e+ a**Npat/s@pat/s  _pat/s.up*ate@pat/s  en*

en*

?nce you ha*e that file, change unit test s!eleton to this#

 1 reuire testHunit

>

Page 98: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 98/128

  3 ! #  <

 & 91"111131!1#11<1&19"

13!#<&93"31333

3!3#33<3&

reuireNrelative ..HlibHex!<

,lass ynitTests Test::nit::Test2ase

  *e+ testNroo(@  gol* K >oo(.ne8@BXol*>oo(BF

BBBT/is roo( /as gol* in it you ,an grab. T/eres a  *oor to t/e nort/.BBB  assertNeual@gol*.na(eF BXol*>oo(B  assertNeual@gol*.pat/sF OP  en*

  *e+ testNroo(Npat/s@  ,enter K >oo(.ne8@B2enterBF BTest roo( in t/e ,enter.B  nort/ K >oo(.ne8@B0ort/BF BTest roo( in t/e nort/.B  sout/ K >oo(.ne8@BSout/BF BTest roo( in t/e sout/.B

  ,enter.a**Npat/s@O:nort/ K' nort/F :sout/ K' sout/P  assertNeual@,enter.go@:nort/F nort/

  assertNeual@,enter.go@:sout/F sout/  en*

  *e+ testN(ap@  start K >oo(.ne8@BStartBF BEou ,an go 8est an* *o8n a /ole.B  8est K >oo(.ne8@BTreesBF BT/ere are trees /ereF you ,an go east.B  *o8n K >oo(.ne8@BDungeonBF B=ts *ar) *o8n /ereF you ,an go up.B

  start.a**Npat/s@O:8est K' 8estF :*o8n K' *o8nP  8est.a**Npat/s@O:east K' startP  *o8n.a**Npat/s@O:up K' startP

  [email protected]@:8estF 8est

  [email protected]@:8est.go@:eastF start  [email protected]@:*o8n.go@:upF start  en*

en*

This file re3uires the >oo( class you made in the libHex!<.rb file so that you can do tests on

it. There are then a set of tests that are functions starting with testN. Inside each test case

there's a bit of code that ma!es a >oo( or a set of >oo(s, and then ma!es sure the rooms wor!

the way you e&ect them to wor!. It tests out the basic room features, then the aths, then

tries out a whole ma.

The imortant functions here are assertNeual which ma!es sure that *ariables you ha*e

set or aths you ha*e built in a >oo( are actually what you thin! they are. If you get the

wrong result, then Ruby's Test::nit module will rint out an error message so you can go

figure it out.

Testing 3#idelines

:ollow these general loose set of guidelines when ma!ing your tests#

$. Test files go in testH and are named testN0A.rb. This !ees your tests from

clashing with your other code.. Write one test file for each module or class you ma!e.

>4

Page 99: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 99/128

(. 7ee your test cases 5functions6 short, but do not worry if they are a bit messy. Test

cases are usually !ind of messy.

B. 0*en though test cases are messy, try to !ee them clean and remo*e any reetiti*e

code you can. ;reate heler functions that get rid of dulicate code. +ou will than!

me later when you ma!e a change and then ha*e to change your tests. ulicated

code will ma!e changing your tests more difficult.C. :inally, do not get too attached to your tests. /ometimes, the best way to redesign

something is to ust delete it, the tests, and start o*er.

What "o# Sho#ld See$ ruby testNex!<.rbLoa*e* suite testNex!<Starte*...?inis/e* in "."""3#3 se,on*s.

3 testsF < assertionsF " +ailuresF " errorsF " s)ips

Test run options: --see* 3#3<

That's what you should see if e*erything is wor!ing right. Try causing an error to see what

that loo!s li!e and then fi& it.

(%tra Credit 

$. %o read about Test::nit more, and also read about alternati*es.

. Learn about >spe, and see if you li!e it better.

(. )a!e your Room more ad*anced, and then use it to rebuild your game yet again but

this time, unit test as you go.

Exercise (.: Adanced 4ser Input

+our game robably was coming along great, but I bet how you handled what the user tyed

was becoming tedious. 0ach room needed its own *ery e&act set of hrases that only wor!ed

if your layer tyed them erfectly. What you'd rather ha*e is a de*ice that lets users tye

 hrases in *arious ways. :or e&amle, we'd li!e to ha*e all of these hrases wor! the same#

• oen door 

• oen the door • go THR?E%H the door 

•  unch bear 

• Punch The 2ear in the :-;0

It should be alright for a user to write something a lot li!e 0nglish for your game, and ha*e

your game figure out what it means. To do this, we're going to write a library that does ust

that. This module will ha*e a few classes that wor! together to handle use inut and con*ert it

into something your game can wor! with reliably.

In a simle *ersion of 0nglish the following elements#

• Words searated by saces.

>>

Page 100: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 100/128

• /entences comosed of the words.

• %rammar that structures the sentences into meaning.

That means the best lace to start is figuring out how to get words from the user and what

!inds of words those are.

O#r 3a+e Le%icon

In our game we ha*e to create a Le&icon of words#

• irection words# north, south, east, west, down, u, left, right, bac!.

• @erbs# go, sto, !ill, eat.

• /to words# the, in, of, from, at, it

•  Founs# door, bear, rincess, cabinet.

•  Fumbers# any string of 8 through > characters.

When we get to nouns, we ha*e a slight roblem since each room could ha*e a different set

of Founs, but let's ust ic! this small set to wor! with for now and imro*e it later.

'reaking ,p A Sentence

?nce we ha*e our le&icon of words we need a way to brea! u sentences so that we can

figure out what they are. In our case, we'*e defined a sentence as "words searated by

saces", so we really ust need to do this#

stu++ K gets.,/o(p@

8or*s K stu++.split@

That's really all we'll worry about for now, but this will wor! really well for 3uite a while.

Le%icon Str#cts

?nce we !now how to brea! u a sentence into words, we ust ha*e to go through the list of

words and figure out what "tye" they are. To do that we're going to use a handy little Ruby

structure called a "struct". - struct is a con*enient way to bundle a number of attributes

together, using accessor methods, without ha*ing to write an e&licit class. It's created li!e

this#

air K Stru,t.ne8@:to)enF :8or*+irstN8or* K air.ne8@B*ire,tionBF Bnort/Bse,on*N8or* K air.ne8@BverbBF BgoBsenten,e K +irstN8or*F se,on*N8or*U

This creates a air of 5T?70F, W?R6 that lets you loo! at the word and do things with it.

This is ust an e&amle, but that's basically the end result. +ou want to ta!e inut from the

user, car*e it into words with slit, then analyGe those words to identify their tye, and finally

ma!e a sentence out of them.

$88

Page 101: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 101/128

Scanning 0np#t 

 Fow you are ready to write your scanner. This scanner will ta!e a string of inut from a user

and return a sentence that's comosed of a list of structs with the 5T?70F, W?R6 airings.

If a word isn't art of the le&icon then it should still return the W?R, but set the T?70F to

an error to!en. These error to!ens will tell the user they messed u.

Here's where it gets fun. I'm not going to tell you how to do this. Instead I'm going to write a

unit test und you are going to write the scanner so that the unit test wor!s.

(%ceptions And N#+/ers

There is one tiny thing I will hel you with first, and that's con*erting numbers. In order to do

this though, we're going to cheat and use e&cetions. -n e&cetion is an error that you get

from some function you may ha*e run. What haens is your function "raises" an e&cetion

when it encounters an error, then you ha*e to handle that e&cetion. :or e&amle, if you tyethis into IR2#

ruby-1.9.-p1&" :""1 ' =nteger@B/ellBArgu(entrror: invali* value +or =nteger@: B/ellB  +ro( @irb:1:in Q=nteger  +ro( @irb:1  +ro( H/o(eHrobH.rv(HrubiesHruby-1.9.-p1&"HbinHirb:1:in Q(ain'

That Argu(entrror is an e&cetion that the =nteger@ function threw because what you

handed =nteger@ is not a number. The =nteger@ function could ha*e returned a *alue to

tell you it had an error, but since it only returns numbers, it'd ha*e a hard time doing that. It

can't return 1$ since that's a number. Instead of trying to figure out what to return when there'san error, the =nteger@ function raises the Typerror e&cetion and you deal with it.

+ou deal with an e&cetion by using the begin and res,ue !eywords#

*e+ ,onvertNnu(ber@s  begin  =nteger@s  res,ue Argu(entrror  nil  en*en*

+ou ut the code you want to "begin" inside the begin bloc!, and then you ut the code to

run for the error inside the res,ue. In this case, we want to call =nteger@ on something that

might be a number. If that has an error, then we "rescue" it and return nil instead.

In your scanner that you write, you should use this function to test if something is a number.

+ou should also do it as the last thing you chec! for before declaring that word an error word.

What "o# Sho#ld Test 

Here are the files testHtestNlexi,on.rb  that you should use#

$8$

Page 102: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 102/128

 1  3 ! #

  < & 91"111131!1#11<1&

19"13!#<&93"31

3333!3#33<3&39!"!1!!3!!

!#!!<!&!9#"#1##3#!##

reuire testHunitreuireNrelative B..HlibHlexi,onB

,lass Lexi,onTests Test::nit::Test2ase

  air K Lexi,on::air

  __lexi,on K Lexi,on.ne8@

  *e+ testN*ire,tions@  [email protected]@:*ire,tionF nort/UF__lexi,on.s,an@Bnort/B  result K __lexi,on.s,an@Bnort/ sout/ eastB  assertNeual@resultF air.ne8@:*ire,tionF nort/F  air.ne8@:*ire,tionF sout/F  air.ne8@:*ire,tionF eastU  en*

  *e+ testNverbs@  assertNeual@__lexi,on.s,an@BgoBF air.ne8@:verbF goU

  result K __lexi,on.s,an@Bgo )ill eatB  assertNeual@resultF air.ne8@:verbF goF  air.ne8@:verbF )illF  air.ne8@:verbF eatU  en*

  *e+ testNstops@  assertNeual@__lexi,on.s,an@Bt/eBF air.ne8@:stopF t/eU  result K __lexi,on.s,an@Bt/e in o+B  assertNeual@resultF air.ne8@:stopF t/eF  air.ne8@:stopF inF  air.ne8@:stopF o+U  en*

  *e+ testNnouns@  assertNeual@__lexi,on.s,an@BbearBF air.ne8@:nounF bearU  result K __lexi,on.s,an@Bbear prin,essB  assertNeual@resultF air.ne8@:nounF bearF  air.ne8@:nounF prin,essU  en*

  *e+ testNnu(bers@  assertNeual@__lexi,on.s,an@B13!BF air.ne8@:nu(berF 13!U  result K __lexi,on.s,an@B3 913!B  assertNeual@resultF air.ne8@:nu(berF 3F  air.ne8@:nu(berF 913!U

  en*

  *e+ testNerrors@  assertNeual@__lexi,on.s,an@BASD?AD?ASD?BF air.ne8@:errorFASD?AD?ASD?U  result K __lexi,on.s,an@Bbear =AS prin,essB  assertNeual@resultF air.ne8@:nounF bearF  air.ne8@:errorF =ASF  air.ne8@:nounF prin,essU  en*

en*

$8

Page 103: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 103/128

Remember that you will want to ma!e a new roect with your s!eleton, tye in this test case

5do not coy1asteO6 and write your scanner so that the test runs. :ocus on the details and

ma!e sure e*erything wor!s right.

Design )ints

:ocus on getting one test wor!ing at a time. 7ee this simle and ust ut all the words in

your le&icon in lists that are in your lexi,on.rb file. o not modify the inut list of words,

 but instead ma!e your own new list with your le&icon airs in it. -lso, use the in,lu*eM 

method with these le&icon arrays to chec! if a word is in the le&icon.

(%tra Credit 

$. Imro*e the unit test to ma!e sure you co*er more of the le&icon.

. -dd to the le&icon and then udate the unit test.

(. )a!e your scanner handles user inut in any caitaliGation and case. Edate the test

to ma!e sure this actually wor!s.B. :ind another way to con*ert the number.

C. )y solution was ( lines long. Is yours longer /horter

Exercise (: 'a2in! Sentences

What we should be able to get from our little game le&icon scanner is a list that loo!s li!e this

5yours will be formatted differently6#

ruby-1.9.-p1&" :""3 ' print Lexi,on.s,an@Bgo nort/B

stru,t Lexi,on::air to)enK:verbF 8or*KBgoB'F  stru,t Lexi,on::air to)enK:*ire,tionF 8or*KBnort/B'U K' nilruby-1.9.-p1&" :""! ' print Lexi,on.s,an@B)ill t/e prin,essBstru,t Lexi,on::air to)enK:verbF 8or*KB)illB'F  stru,t Lexi,on::air to)enK:stopF 8or*KBt/eB'F  stru,t Lexi,on::air to)enK:nounF 8or*KBprin,essB'U K' nilruby-1.9.-p1&" :""# ' print Lexi,on.s,an@Beat t/e bearBstru,t Lexi,on::air to)enK:verbF 8or*KBeatB'F  stru,t Lexi,on::air to)enK:stopF 8or*KBt/eB'F  stru,t Lexi,on::air to)enK:nounF 8or*KBbearB'U K' nilruby-1.9.-p1&" :"" ' print Lexi,on.s,an@Bopen t/e *oor an* s(a,) t/e bearin t/e noseBstru,t Lexi,on::air to)enK:errorF 8or*KBopenB'F

  stru,t Lexi,on::air to)enK:stopF 8or*KBt/eB'F  stru,t Lexi,on::air to)enK:nounF 8or*KB*oorB'F  stru,t Lexi,on::air to)enK:errorF 8or*KBan*B'F  stru,t Lexi,on::air to)enK:errorF 8or*KBs(a,)B'F  stru,t Lexi,on::air to)enK:stopF 8or*KBt/eB'F  stru,t Lexi,on::air to)enK:nounF 8or*KBbearB'F  stru,t Lexi,on::air to)enK:stopF 8or*KBinB'F  stru,t Lexi,on::air to)enK:stopF 8or*KBt/eB'F  stru,t Lexi,on::air to)enK:errorF 8or*KBnoseB'U K' nilruby-1.9.-p1&" :""< '

 Fow let us turn this into something the game can wor! with, which would be some !ind of

/entence class.

If you remember grade school, a sentence can be a simle structure li!e#

$8(

Page 104: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 104/128

/ubect @erb ?bect

?b*iously it gets more comle& than that, and you robably did many days of annoying

sentence grahs for 0nglish class. What we want is to turn the abo*e lists of structs into a

nice /entence obect that has subect, *erb, and obect.

Match And Peek 

To do this we need four tools#

$. - way to loo through the list of structs. That's easy.

. - way to "match" different tyes of structs that we e&ect in our /ubect @erb ?bect

setu.

(. - way to "ee!" at a otential struct so we can ma!e some decisions.

B. - way to "s!i" things we do not care about, li!e sto words.

C. We use the ee! function to say loo! at the ne&t element in our struct array, and then

match to ta!e one off and wor! with it. Let's ta!e a loo! at a first ee! function#

*e+ pee)@8or*Nlist  begin  8or*Nlist.+irst.to)en  res,ue  nil  en*en*

@ery easy. Fow for the match function#

*e+ (at,/@8or*NlistF expe,ting  begin  8or* K 8or*Nlist.s/i+t

  i+ 8or*.to)en KK expe,ting  8or*  else  nil  en*  res,ue  nil  en*en*

-gain, *ery easy, and finally our s!i function#

*e+ s)ip@8or*NlistF 8or*Ntype  8/ile pee)@8or*Nlist KK 8or*Ntype  (at,/@8or*NlistF 8or*Ntype  en*en*

2y now you should be able to figure out what these do. )a!e sure you understand them.

$8B

Page 105: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 105/128

The Sentence 3ra++ar 

With our tools we can now begin to build /entence obects from our array of structs. What

we do is a rocess of#

$. Identify the ne&t word with pee).. If that word fits in our grammar, we call a function to handle that art of the grammar,

say parseNsubRe,t.

(. If it doesn't, we raise an error, which you will learn about in this lesson.

B. When we're all done, we should ha*e a /entence obect to wor! with in our game.

The best way to demonstrate this is to gi*e you the code to read, but here's where this

e&ercise is different from the re*ious one# +ou will write the test for the arser code I gi*e

you. Rather than gi*ing you the test so you can write the code, I will gi*e you the code, and

you ha*e to write the test.

Here's the code that I wrote for arsing simle sentences using the ex!& Le&icon class#

 1  3 ! #  < & 91"

111131!1#11<1&19"13

!#<&93"313333!3#3

3<3&39

,lass arserrror x,eption

en*

,lass Senten,e

  *e+ initialiZe@subRe,tF verbF obRe,t  re(e(ber 8e ta)e air.ne8@:nounF Bprin,essB stru,ts an* ,onvertt/e(  _subRe,t K subRe,t.8or*

  _verb K verb.8or*  _obRe,t K obRe,t.8or*  en*

en*

(o*ule arser

  *e+ sel+.pee)@8or*Nlist  begin  8or*Nlist.+irst.to)en  res,ue  nil

  en*  en* *e+ sel+.(at,/@8or*NlistF expe,ting

  begin  8or* K 8or*Nlist.s/i+t  i+ 8or*.to)en KK expe,ting  8or*  else  nil  en*  res,ue  nil

  en*  en* 

$8C

Page 106: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 106/128

!"!1!!3!!

!#!!<!&!9#"#1##3#!####<

#&#9"13!#<&9<"

<1<<3<!<#<<<<&<9&"&1&&3

&!&#&&<&&&99"919

  *e+ sel+.s)ip@8or*NlistF to)en  8/ile pee)@8or*Nlist KK to)en  (at,/@8or*NlistF to)en  en*  en* 

*e+ sel+.parseNverb@8or*Nlist  s)ip@8or*NlistF :stop 

i+ pee)@8or*Nlist KK :verb  return (at,/@8or*NlistF :verb  else  raise arserrror.ne8@Bxpe,te* a verb next.B  en*  en* *e+ sel+.parseNobRe,t@8or*Nlist

  s)ip@8or*NlistF :stop  nextN8or* K pee)@8or*Nlist

  i+ nextN8or* KK :noun  return (at,/@8or*NlistF :noun  en*  i+ nextN8or* KK :*ire,tion  return (at,/@8or*NlistF :*ire,tion  else  raise arserrror.ne8@Bxpe,te* a noun or *ire,tion next.B  en*  en* *e+ sel+.parseNsubRe,t@8or*NlistF subR

  verb K parseNverb@8or*Nlist

  obR K parseNobRe,t@8or*Nlist return Senten,e.ne8@subRF verbF obR

  en* *e+ sel+.parseNsenten,e@8or*Nlist

  s)ip@8or*NlistF :stop 

start K pee)@8or*Nlist 

i+ start KK :noun  subR K (at,/@8or*NlistF :noun  return parseNsubRe,t@8or*NlistF subR

  elsi+ start KK :verb  assu(e t/e subRe,t is t/e player t/en  return parseNsubRe,t@8or*NlistF air.ne8@:nounF BplayerB  else  raise arserrror.ne8@Bust start 8it/ subRe,tF obRe,tF or verbnot: OstartPB  en*  en*

en*

 A Word On Mod#les

This code uses something in Ruby called a "module" named arser. - module 5created with

(o*ule arser6 is a way to ac!age u the functions so that they don't conflict with other

$8D

Page 107: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 107/128

 arts of Ruby. In Ruby $.> there was a change to the testing system that created a s)ip 

method which conflicted with the arser.s)ip method. The solution was to do what you see

here and wra all the functions in this module.

+ou use a module by simly calling functions on it with the . oerator, similar to an obect

you'*e made. In this case if you wanted to call the parseNverb@ function you'd writearser.parseNverb@. +ou'll see a demonstration of this when I gi*e you a samle unit

test.

 A Word On (%ceptions

+ou briefly learned about e&cetions, but not how to raise them. This code demonstrates how

to do that with the arserrror at the to. Fotice that it uses classes to gi*e it the tye of

x,eption. -lso notice the use of raise !eyword to raise the e&cetion.

In your tests, you will want to wor! with these e&cetions, which I'll show you how to do.

What "o# Sho#ld Test 

:or 0&ercise B> is write a comlete test that confirms e*erything in this code is wor!ing. That

includes ma!ing e&cetions haen by gi*ing it bad sentences. Here is a starter samle so

you can see how you would call a function in a module#

 1  3 ! #  < & 91"11

reuire testHunitreuireNrelative ..HlibHex!9

,lass arserTests Test::nit::Test2ase

  *e+ testNparseNverb@  WA>0=0X: T7=S ?A=LS G0 >GS S T7 GG\  arser.parseNverb@+alseU  en*

en*

+ou can see I ma!e the basic test class, then create a testNparseNverb to test out the

arser.parseNverb function. I don't want to do the wor! for you, so I'*e made this fail on

 purpose. This shows you how to use the arser module and call functions on it, and you

should wor! on ma!ing this test actually test all the code.

;hec! for an e&cetion by using the function assertNraise from the Test##Enit

documentation. Learn how to use this so you can write a test that is e&ected to fail, which is

*ery imortant in testing. Learn about this function 5and others6 by reading the Test##Enit

documentation.

When you are done, you should !now how this bit of code wor!s, and how to write a test for

other eole's code e*en if they do not want you to. Trust me, it's a *ery handy s!ill to ha*e.

(%tra Credit 

$. ;hange the parseN methods and try to ut them into a class rather than be ustmethods. Which design do you li!e better

$8

Page 108: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 108/128

. )a!e the arser more error resistant so that you can a*oid annoying your users if they

tye words your le&icon doesn't understand.

(. Imro*e the grammar by handling more things li!e numbers.

B. Thin! about how you might use this /entence class in your game to do more fun

things with a user's inut.

Exercise +0: 7our First Website

These final three e&ercises will be *ery hard and you should ta!e your time with them. In this

first one you'll build a simle web *ersion of one of your games. 2efore you attemt this

e&ercise you must ha*e comleted 0&ercise BD successfully and ha*e a wor!ing RubyGe"s 

installed such that you can install ac!ages and !now how to ma!e a s!eleton roect

directory. If you don't remember how to do this, go bac! to 0&ercise BD and do it all o*er

again.

0nstalling Sinatra

2efore creating your first web alication, you'll first need to install the "web framewor!"

called Sinatra. The term "framewor!" generally means "some ac!age that ma!es it easier

for me to do something". In the world of web alications, eole create "web framewor!s"

to comensate for the difficult roblems they'*e encountered when ma!ing their own sites.

They share these common solutions in the form of a ac!age you can download to bootstra

your own roects.

In our case, we'll be using the /inatra framewor!, but there are many, many, many others you

can choose from. :or now, learn /inatra then branch out to another one when you're ready 5or ust !ee using /inatra since it's good enough6.

Esing ge( install /inatra#

$ ge( install sinatra?et,/ing: tilt-1.3..ge( @1""J?et,/ing: sinatra-1...ge( @1""JSu,,ess+ully installe* tilt-1.3.Su,,ess+ully installe* sinatra-1.. ge(s installe*=nstalling ri *o,u(entation +or tilt-1.3....

=nstalling ri *o,u(entation +or sinatra-1.....=nstalling >Do, *o,u(entation +or tilt-1.3....=nstalling >Do, *o,u(entation +or sinatra-1.....

Make A Si+ple ;)ello World; Pro2ect 

 Fow you're going to ma!e an initial *ery simle "Hello World" web alication and roect

directory using /inatra. :irst, ma!e your roect directory#

$ ,* proRe,ts$ bun*le ge( got/on8eb

$84

Page 109: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 109/128

+ou'll be ta!ing the game from 0&ercise B and ma!ing it into a web alication, so that's

why you're calling it got/on8eb. 2efore you do that, we need to create the most basic /inatra

alication ossible. Put the following code into libHgot/on8eb.rb#

1

3!#<&9

reuireNrelative Bgot/on8ebHversionB

reuire BsinatraB

(o*ule Xot/on8eb  get H *o  greeting K B7elloF Worl*CB  return greeting  en*en*

Then run the alication li!e this#

$ ruby libHgot/on8eb.rbKK SinatraH1.. /as ta)en t/e stage on !#< +or *evelop(ent 8it/ ba,)up+ro( Wri,)"11-"<-1& 11:<:"<U =0?G Wri,) 1.3.1"11-"<-1& 11:<:"<U =0?G ruby 1.9. @"11-"-1& x&N!-linuxU"11-"<-1& 11:<:"<U =0?G Wri,)::7TTServerstart: pi*K#99 portK!#<

:inally, use your web browser and go to the ERL /ttp:HHlo,al/ost:!#<H  and you should

see two things. :irst, in your browser you'll see 7elloF Worl*C. /econd, you'll see your

terminal with new outut li!e this#

1<.".".1 - - 1&HVulH"11 11:9:1"U BXT H 7TTH1.1B "" 1 ".""1#lo,al/ost - - 1&HVulH"11:11:9:1" DTU BXT H 7TTH1.1B "" 1

- -' H1<.".".1 - - 1&HVulH"11 11:9:1"U BXT H+avi,on.i,o 7TTH1.1B !"! !!<"."""&lo,al/ost - - 1&HVulH"11:11:9:1" DTU BXT H+avi,on.i,o 7TTH1.1B !"!!!<- -' H+avi,on.i,o

Those are log messages that /inatra rints out so you can see that the ser*er is wor!ing, and

what the browser is doing behind the scenes. The log messages hel you debug and figure out

when you ha*e roblems. :or e&amle, it's saying that your browser tried to get

H+avi,on.i,o but that file didn't e&ist so it returned !"! 0ot ?oun* status code.

I ha*en't e&lained the way any of this web stuff wor!s yet, because I want to get you setuand ready to roll so that I can e&lain it better in the ne&t two e&ercises. To accomlish this,

I'll ha*e you brea! your /inatra alication in *arious ways and then restructure it so that you

!now how it's setu.

What*s 3oing On4 

Here's what's haening when your browser hits your alication#

$. +our browser ma!es a networ! connection to your own comuter, which is called

lo,al/ost and is a standard way of saying "whate*er my own comuter is called on

the networ!". It also uses port !#<.

$8>

Page 110: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 110/128

. ?nce it connects, it ma!es an HTTP re3uest to the libHgot/on8eb.rb alication

and as!s for the H ERL, which is commonly the first ERL on any website.

(. Inside libHgot/on8eb.rb you'*e got bloc!s of code that ma to ERLs. The only one

we ha*e is the H maing. This means that whene*er someone goes to H with a

 browser, /inatra will find the code bloc! to handle the re3uest.

B. /inatra calls the matching bloc!, which simly returns a string for what /inatra shouldsend to the browser.

C. :inally, /inatra has handled the re3uest and sends this resonse to the browser which

is what you are seeing.

)a!e sure you really understand this. raw u a diagram of how this information flows from

your browser, to /inatra, then to the H bloc! and bac! to your browser.

&i%ing (rrors

:irst, delete line D where you assign the greeting *ariable, then hit refresh in your browser.+ou should see an error age now that gi*es you lots of information on how your alication

 ust e&loded. +ou !now that the *ariable greeting is now missing, but /inatra gi*es you

this nice error age to trac! down e&actly where. o each of the following with this age#

$. Loo! at the sinatra.error *ariable.

. Loo! at the >4STN *ariables and see if they match anything you're already familiar

with. This is information that your web browser is sending to your gothonweb

alication. +ou normally don't e*en !now that it's sending this stuff, so now you get

to see what it does.

Create 'asic Te+plates

+ou can brea! your /inatra alication, but did you notice that "Hello World" isn't a *ery

good HT)L age This is a web alication, and as such it needs a roer HT)L resonse.

To do that you will create a simle temlate that says "Hello World" in a big green font.

The first ste is to create a libHvie8sHin*ex.erb file that loo!s li!e this#

 1  3

 ! #  < & 91"111131!

/t(l'  /ea*'  title'Xot/ons G+ lanet er,al #Htitle'

  H/ea*'  bo*y'

  J i+ greeting J'  p'= Rust 8ante* to say e( styleKB,olor: green[ +ont-siZe: e([B'JK greeting J'He('.  J else J'  e('7elloHe('F 8orl*C  J en* J'

  Hbo*y'H/t(l'

What is a .erb file 0R2 stands for 0mbedded Ruby. .erb files are HT)L with bits of Rubycode embedded within. If you !now what HT)L is then this should loo! fairly familiar. If

$$8

Page 111: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 111/128

not, research HT)L and try writing a few web ages by hand so you !now how it wor!s.

/ince this is an erb temlate, /inatra will fill in "holes" in the te&t deending on *ariables

you ass in to the temlate. 0*ery lace you see JK greeting J' will be a *ariable you'll

 ass to the temlate that alters its contents.

To ma!e your libHgot/on8eb.rb  scrit do this, you need to add some code to tell /inatrawhere to load the temlate and to render it. Ta!e that file and change it li!e this#

 1  3 ! #  < & 9

1"

reuireNrelative Bgot/on8ebHversionBreuire BsinatraBreuire BerbB

(o*ule Xot/on8eb  get H *o  greeting K B7elloF Worl*CB  erb :in*exF :lo,als K' O:greeting K' greetingPen*

en*

Pay close attention to how I changed the last line of the H bloc! so it calls erb assing in your

greeting *ariable.

?nce you ha*e that in lace, reload the web age in your browser and you should see a

different message in green. +ou should also be able to do a @iew /ource on the age in your

 browser to see that it is *alid HT)L.

This may ha*e flown by you *ery fast, so let me e&lain how a temlate wor!s#

$. In your libHgot/on8eb.rb  you'*e added a new erb method call.. The erb method !nows how to load .erb files out of the libHvie8sH directory. It

!nows which file to grab 5in*ex.erb in this case6 because you ass it as a arameter

5erb :in*ex ...6.

(. Fow, when the browser hits H and libHgot/on8eb.rb matches and e&ecutes the get

H *o bloc!, instead of ust returning the string greeting, it calls erb and ass

greeting to it as a *ariable.

B. :inally, you ha*e the HT)L in libHvie8sHin*ex.erb that contains a bit of Ruby

code that tests the greeting variable, and if it's there, rints one message using the

greeting, or a default message.

To get deeer into this, change the greeting *ariable and the HT)L to see what effect it

has. -lso create another temlate named libHvie8sH+oo.lib  and render that using erb

:+oo instead of erb :in*ex li!e before. This will show you how the first arameter you ass

to erb is ust matched to a .erb file in libHvie8sH.

(%tra Credit 

$. Read the documentation at htt#AAwww.sinatrarb.com.

. 0&eriment with e*erything you can find there, including their e&amle code.

(. Read about HT)LC and ;//( and ma!e some ./t(l and .,ss files for ractice.

B. If you ha*e a friend who !nows Rai*s and is willing to hel you, then consider doing

0& C8, C$, and C in Rails instead to see what that's li!e.

$$$

Page 112: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 112/128

Exercise +1: Gettin! Input Fro" A ?ro9ser

While it's e&citing to see the browser dislay "Hello World", it's e*en more e&citing to let the

user submit te&t to your alication from a form. In this e&ercise we'll imro*e our starter

web alication using forms and figure out how to do automated testing for a webalication.

)o$ The We/ Works

Time for some boring stuff. +ou need to understand a bit more about how the web wor!s

 before you can ma!e a form. This descrition isn't comlete, but it's accurate and will hel

you figure out what might be going wrong with your alication. -lso, creating forms will be

easier if you !now what they do.

I'll start with a simle diagram that shows you the different arts of a web re3uest and how

the information flows#

htt re3uest diagram

I'*e labeled the lines with letters so I can wal! you through a regular re3uest rocess#

$. +ou tye in the url htt#AAlearnythonthehardway.orgA into your browser and it sends

the re3uest out on line @A to your comuter's networ! interface.

. +our re3uest goes out o*er the internet on line @ and then to the remote comuter

on line @2 where my ser*er accets the re3uest.

(. ?nce my comuter accets it, my web alication gets it on line @D, and my webalication code runs the H 5inde&6 handler.

B. The resonse comes out of my web ser*er when I return it, and goes bac! to your

 browser o*er line @D again.

C. The ser*er running this site ta!es the resonse off line @D then sends it bac! o*er

the internet on line @2.

D. The resonse from the ser*er then comes off the internet on line @, and your

comuter's networ! interface hands it to your browser on line @A.

. :inally, your browser then dislays the resonse.

In this descrition there are a few terms you should !now so that you ha*e a common*ocabulary to wor! with when tal!ing about your web alication#

$$

Page 113: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 113/128

Bro%er 

The software that you're robably using e*ery day. )ost eole don't !now what it really

does, they ust call it "the internet". Its ob is to ta!e addresses 5li!e

htt#AAlearnythonthehardway.org6 you tye into the ERL bar, then use that information to

ma!e re3uests to the ser*er at that address.

Addre

This is normally a ERL 5Eniform Resource Locator6 li!e htt#AAlearnythonthehardway.orgA 

and indicates where a browser should go. The first art /ttp indicates the rotocol you want

to use, in this case "Hyer1Te&t Transort Protocol". +ou can also try ft#AAibiblio.orgA to see

how ":ile Transort Protocol" wor!s. The learnpyt/ont/e/ar*8ay.org  art is the

"hostname", or a human readable address you can remember and which mas to a number

called an IP address, similar to a telehone number for a comuter on the Internet. :inally,

ERLs can ha*e a trailing pat/ li!e the Hboo)H art of

htt#AAlearnythonthehardway.orgAboo!A which indicates a file or some resource on the ser*er

to retrie*e with a re3uest. There are many other arts, but those are the main ones.

Connection

?nce a browser !nows what rotocol you want to use 5htt6, what ser*er you want to tal! to

5learnythonthehardway.org6, and what resource on that ser*er to get, it must ma!e a

connection. The browser simly as!s your ?erating /ystem 5?/6 to oen a "ort" to the

comuter, usually ort 48. When it wor!s the ?/ hands bac! to your rogram something that

wor!s li!e a file, but is actually sending and recei*ing bytes o*er the networ! wires between

your comuter and the other comuter at "learnythonthehardway.org". This is also the samething that haens with htt#AAlocalhost#4848A but in this case you're telling the browser to

connect to your own comuter 5localhost6 and use ort BCD rather than the default of 48.

+ou could also do htt#AAlearnythonthehardway.org#48A and get the same result, e&cet

you're e&licitly saying to use ort 48 instead of letting it be that by default.

&e'uet

+our browser is connected using the address you ga*e. Fow it needs to as! for the resource it

wants 5or you want6 on the remote ser*er. If you ga*e Hboo)H at the end of the ERL, then

you want the file 5resource6 at Hboo)H, and most ser*ers will use the real file

Hboo)Hin*ex./t(l  but retend it doesn't e&ist. What the browser does to get this resource issend a re3uest to the ser*er. I won't get into e&actly how it does this, but ust understand that

it has to send something to 3uery the ser*er for the re3uest. The interesting thing is that these

"resources" don't ha*e to be files. :or instance, when the browser in your alication as!s for

something, the ser*er is returning something your code generated.

Server 

The ser*er is the comuter at the end of a browser's connection that !nows how to answer

your browser's re3uests for filesAresources. )ost web ser*ers ust send files, and that's

actually the maority of traffic. 2ut you're actually building a ser*er in Ruby that !nows howto ta!e re3uests for resources, and then return strings that you craft using Ruby. When you do

$$(

Page 114: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 114/128

this crafting, you are retending to be a file to the browser, but really it's ust code. -s you

can see from 0&. C8, it also doesn't ta!e much code to create a resonse.

&epone

This is the HT)L 5css, a*ascrit, or images6 your ser*er wants to send bac! to the browseras the answer to the browser's re3uest. In the case of files, it ust reads them off the dis! and

sends them to the browser, but it wras the contents of the dis! in a secial "header" so the

 browser !nows what it's getting. In the case of your alication, you're still sending the same

thing, including the header, but you generate that data on the fly with your Ruby code.

That is the fastest crash course in how a web browser accesses information on ser*ers on the

internet. It should wor! well enough for you to understand this e&ercise, but if not, read about

it as much as you can until you get it. - really good way to do that is to ta!e the diagram, and

 brea! different arts of the web alication you did in 0&ercise C8. If you can brea! your web

alication in redictable ways using the diagram, you'll start to understand how it wor!s.

)o$ &or+s Work 

The best way to lay with forms is to write some code that accets form data, and then see

what you can do. Ta!e your libHgot/on8eb.rb file and ma!e it loo! li!e this#

 1  3 ! #

  < & 91"111131!1#1

reuireNrelative Bgot/on8ebHversionBreuire BsinatraBreuire BerbB

(o*ule Xot/on8eb

  get H *o  greeting K B7elloF Worl*CB  erb :in*exF :lo,als K' O:greeting K' greetingP  en* get H/ello *o

  na(e K para(s:na(eU YY B0obo*yB  greeting K B7elloF Ona(ePB  erb :in*exF :lo,als K' O:greeting K' greetingP  en*en*

Restart /inatra 5hit ;TRL1; and then run it again6 to ma!e sure it loads again, then with your

 browser go to /ttp:HHlo,al/ost:!#<H/ello  which should dislay, "I ust wanted to say

Hello, Fobody." Fe&t, change the ERL in your browser to

/ttp:HHlo,al/ost:!#<H/elloMna(eK?ran)  and you'll see it say "Hello, :ran!." :inally,

change the na(eK?ran) art to be your name. Fow it's saying hello to you.

Let's brea! down the changes I made to your scrit.

$. Instead of ust a string for greeting I'm now using the para(s hash to get data from

the browser. /inatra ta!es all of the !eyA*alue airs after the M art of the ERL and

adds them to the para(s hash for you to wor! with.

. I then construct the greeting from the na(e *alue we e&tracted *ia thepara(s:na(eU hash loo!u, which should be *ery familiar to you by now.

$$B

Page 115: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 115/128

(. 0*erything else about the file is the same as before.

+ou're also not restricted to ust one arameter on the ERL. ;hange this e&amle to gi*e two

*ariables li!e this# /ttp:HHlo,al/ost:!#<H/elloMna(eK?ran)]greetK7ola . Then

change the code to get para(s:na(eU and para(s:greetU li!e this#

greeting K BOgreetPF Ona(ePB

Creating )TML &or+s

Passing the arameters on the ERL wor!s, but it's !ind of ugly and not easy to use for regular

 eole. What you really want is a "P?/T form", which is a secial HT)L file that has a

+or(' tag in it. This form will collect information from the user, then send it to your web

alication ust li!e you did abo*e.

Let's ma!e a 3uic! one so you can see how it wor!s. Here's the new HT)L file you need to

create, in libHvie8sH/elloN+or(.erb #

 1  3 ! #  < & 91"

111131!1#11<1&

/t(l'  /ea*'  title'Sa(ple Web ?or(Htitle'  H/ea*'bo*y'

/1'?ill Gut T/is ?or(H/1'

+or( a,tionKBH/elloB (et/o*KBGSTB'  A Xreeting: input typeKBtextB na(eKBgreetB'

  brH'  Eour 0a(e: input typeKBtextB na(eKBna(eB'  brH'  input typeKBsub(itB'H+or('

Hbo*y'H/t(l'

+ou should then change libHgot/on8eb.rb  to loo! li!e this#

 1  3 ! #  < & 91"111131!1#

11<

reuireNrelative Bgot/on8ebHversionBreuire BsinatraBreuire BerbB

(o*ule Xot/on8eb

  get H *o  greeting K B7elloF Worl*CB  erb :in*exF :lo,als K' O:greeting K' greetingP  en* get H/ello *o

  erb :/elloN+or(  en*

  post H/ello *o  greeting K BOpara(s:greetU YY B7elloBPF Opara(s:na(eU YY

$$C

Page 116: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 116/128

1&19"1

B0obo*yBPB  erb :in*exF :lo,als K' O:greeting K' greetingPen*

en*

?nce you'*e got those written u, simly restart the web alication again and hit it with your browser li!e before.

This time you'll get a form as!ing you for "- %reeting" and "+our Fame". When you hit the

/ubmit button on the form, it will gi*e you the same greeting you normally get, but this time

loo! at the ERL in your browser. /ee how it's /ttp:HHlo,al/ost:!#<H/ello  e*en though

you sent in arameters.

The art of the /elloN+or(.erb file that ma!es this wor! is the line with +or(

a,tionKBH/elloB (et/o*KBGSTB'. This tells your browser to#

$. ;ollect data from the user using the form fields inside the form.

. /end them to the ser*er using a P?/T tye of re3uest, which is ust another browser

re3uest that "hides" the form fields.

(. /end that to the H/ello ERL 5as shown in the a,tionKBH/elloB art6.

B. +ou can then see how the two input' tags match the names of the *ariables in your

new code. -lso notice that instead of ust a %0T method inside class inde&, I ha*e

another method P?/T.

How this new alication wor!s is#

$. The browser first hits the web alication at H/ello but it sends a %0T, so our getH/elloH bloc! runs and returns the /elloN+or(.

. +ou fill out the form in the browser, and the browser does what the +or(' says and

sends the data as a P?/T.

(. The web alication then runs the post H/ello bloc! rather than the get

H/ello bloc! to handle this re3uest.

B. This post H/ello bloc! then does what it normally does to send bac! the /ello 

 age li!e before. There's really nothing new in here, it's ust mo*ed into a new bloc!.

-s an e&ercise, go into the libHvie8sHin*ex.erb  file and add a lin! bac! to ust H/ello so

that you can !ee filling out the form and seeing the results. )a!e sure you can e&lain how

this lin! wor!s and how it's letting you cycle between libHvie8sHin*ex.erb  and

libHvie8sH/elloN+or(.erb  and what's being run inside this latest Ruby code.

Creating A Layo#t Te+plate

When you wor! on your game in the ne&t 0&ercise, you'll need to ma!e a bunch of little

HT)L ages. Writing a full web age each time will 3uic!ly become tedious. Luc!ily you

can create a "layout" temlate, or a !ind of shell that will wra all your other ages with

common headers and footers. %ood rogrammers try to reduce reetition, so layouts are

essential for being a good rogrammer.

;hange libHvie8sHin*ex.erb to be li!e this#

$$D

Page 117: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 117/128

13!#

J i+ greeting J'  p'= Rust 8ante* to say e( styleKB,olor: green[ +ont-siZe: e([B'JKgreeting J'He('.J else J'  e('7elloHe('F 8orl*CJ en* J''

;hange libHvie8sH/elloN+or(.erb  to be li!e this#

13!#<&9

/1'?ill Gut T/is ?or(H/1'

+or( a,tionKBH/elloB (et/o*KBGSTB'  A Xreeting: input typeKBtextB na(eKBgreetB'  brH'  Eour 0a(e: input typeKBtextB na(eKBna(eB'  brH'  input typeKBsub(itB'H+or('

-ll we're doing is striing out the "boilerlate" at the to and the bottom which is always on

e*ery age. We'll ut that bac! into a single libHvie8sHlayout.erb  file that handles it for

us from now on.

?nce you ha*e those changes, create a libHvie8sHlayout.erb  file with this in it#

13!#

<&

/t(l'  /ea*'  title'Xot/ons ?ro( lanet er,al #Htitle'  H/ea*'  bo*y'

  JK yiel* J'  Hbo*y'H/t(l'

/inatra automatically loo!s for a layout temlate called layout by default to use as the base 

temlate for all other temlates. +ou can customiGe which temlate is used as the base for

any gi*en age, too. Restart your alication and then try to change the layout in interesting

ways, but without changing the other temlates.

Writing A#to+ated Tests &or &or+s

It's easy to test a web alication with your browser by ust hitting refresh, but come on,

we're rogrammers here. Why do some reetiti*e tas! when we can write some code to test

our alication What you're going to do ne&t is write a little test for your web alication

form based on what you learned in 0&ercise B. If you don't remember 0&ercise B, read it

again.

I'*e created a simle little function for that lets you assert things about your web alication's

resonse, atly named assertNresponse. ;reate the file testHtestNgot/on8eb.rb  with

these contents#

 1  3

reuireNrelative ..HlibHgot/on8eb.rbreuire testHunitreuire ra,)Htest

$$

Page 118: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 118/128

 ! #  < & 91"111131!1#11<1&19"1

3!#<&93"313333!

3#33<3&39!"!1!!3!!!#!!<

!&!9#"#1##3

0;>A2\N0;U K test

,lass Xot/on8ebTest Test::nit::Test2ase  in,lu*e >a,)::Test::et/o*s 

*e+ app  Sinatra::Appli,ation  en*

  *e+ assertNresponse@respF ,ontainsKnilF (at,/esKnilF /ea*ersKnilFstatusK""  [email protected] statusF Bxpe,te* response OstatusP not inOrespPB

  i+ status KK ""  [email protected]*yF B>esponse *ata is e(pty.B  en*

  i+ ,ontains  assert@@resp.bo*y.in,lu*eM ,ontainsF B>esponse *oes not ,ontainO,ontainsPB  en*

  i+ (at,/es  reg K >egexp.ne8@(at,/es  assert reg.(at,/@,ontainsF B>esponse *oes not (at,/ O(at,/esPB  en*

  i+ /ea*ers  assertNeual@resp./ea*ersF /ea*ers  en*

  en*

  *e+ testNin*ex  ,/e,) t/at 8e get a !"! on t/e H >L  get@BH+ooB  assertNresponse@lastNresponseF nilF nilF nilF !"!

  test our +irst XT reuest to H/ello  get@BH/elloB  assertNresponse@lastNresponse

  (a)e sure *e+ault values 8or) +or t/e +or(  post@BH/elloB

  assertNresponse@lastNresponseF B0obo*yB

  test t/at 8e get expe,te* values  post@BH/elloBF :na(e K' 6e*F :greet K' 7ola  assertNresponse@lastNresponseF B6e*B  assertNresponse@lastNresponseF B7olaB  en*en*

:inally, run testHtestNgot/on8eb.rb  to test your web alication#

$ ruby testHtestNgot/on8eb.rbLoa*e* suite testHtestNgot/on8eb

Starte*.

$$4

Page 119: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 119/128

?inis/e* in "."3&39 se,on*s.

1 testsF 9 assertionsF " +ailuresF " errorsF " s)ips

Test run options: --see* #<!1!

What I'm doing here is I'm actually imorting the whole alication from thelibHgot/on8eb.rb  library, then running it manually.

The ra,)Htest library we ha*e included has a *ery simle -PI for rocessing re3uests. Its

get, put, post, *elete, and /ea* methods simulate the resecti*e tye of re3uest on the

alication.

-ll moc! re3uest methods ha*e the same argument signature#

get Hpat/F para(sKOPF ra,)NenvKOP

• Hpat/ is the re3uest ath and may otionally include a 3uery string.

• para(s is a Hash of 3ueryAost arameters, a /tring re3uest body, or nil.

• ra,)Nenv is a Hash of Rac! en*ironment *alues. This can be used to set re3uest

headers and other re3uest related information, such as session data.

This wor!s without running an actual web ser*er so you can do tests with automated tests and

also use your browser to test a running ser*er.

To *alidate resonses from this function, use the assertNresponse function from

testHtestNgot/on8eb.rb  which has#

assertNresponse@respF ,ontainsKnilF (at,/esKnilF /ea*ersKnilF statusK""

Pass in the resonse you get from calling get or post then add things you want chec!ed. Ese

the ,ontains arameter to ma!e sure that the resonse contains certain *alues. Ese the

status arameter to chec! for certain resonses. There's actually 3uite a lot of information in

this little function so it would be good for you to study it.

In the testHtestNgot/on8eb.rb  automated test I'm first ma!ing sure the H+oo ERL returns

a "B8B Fot :ound" resonse, since it actually doesn't e&ist. Then I'm chec!ing that H/ello 

wor!s with both a %0T and P?/T form. :ollowing the test should be fairly simle, e*en if

you might not totally !now what's going on.

Ta!e some time studying this latest alication, esecially how the automated testing wor!s.

(%tra Credit 

$. Read e*en more about HT)L, and gi*e the simle form a better layout. It hels to

draw what you want to do on aer and then imlement it with HT)L.

. This one is hard, but try to figure out how you'd do a file uload form so that you can

uload an image and sa*e it to the dis!.

(. This is e*en more mind1numbing, but go find the HTTP R:; 5which is the document

that describes how HTTP wor!s6 and read as much of it as you can. It is really boring,

 but comes in handy once in a while.

$$>

Page 120: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 120/128

B. This will also be really difficult, but see if you can find someone to hel you setu a

web ser*er li!e -ache, Fgin&, or thttd. Try to ser*e a coule of your .html and .css

files with it ust to see if you can. on't worry if you can't, web ser*ers !ind of suc!.

C. Ta!e a brea! after this and ust try ma!ing as many different web alications as you

can. +ou should definitely read about sessions in /inatra so you can understand how

to !ee state for a user.

Exercise +#: The Start =5 7our Web Ga"e

We're coming to the end of the boo!, and in this e&ercise I'm going to really challenge you.

When you're done, you'll be a reasonably cometent Ruby beginner. +ou'll still need to go

through a few more boo!s and write a coule more roects, but you'll ha*e the s!ills to

comlete them. The only thing in your way will be time, moti*ation, and resources.

In this e&ercise, we won't ma!e a comlete game, but instead we'll ma!e an "engine" that can

run the game from 0&ercise B in the browser. This will in*ol*e refactoring 0&ercise B,mi&ing in the structure from 0&ercise B, adding automated tests, and finally creating a web

engine that can run the games.

This e&ercise will be huge, and I redict you could send anywhere from a wee! to months

on it before mo*ing on. It's best to attac! it in little chun!s and do a bit a night, ta!ing your

time to ma!e e*erything wor! before mo*ing on.

Refactoring The (%ercise <= 3a+e

+ou'*e been altering the got/on8eb roect for two e&ercises and you'll do it one more timein this e&ercise. The s!ill you're learning is called "refactoring", or as I li!e to call it, "fi&ing

stuff". Refactoring is a term rogrammers use to describe the rocess of ta!ing old code, and

changing it to ha*e new features or ust to clean it u. +ou'*e been doing this without e*en

!nowing it, as it's second nature to building software.

What you'll do in this art is ta!e the ideas from 0&ercise B of a testable "ma" of Rooms,

and the game from 0&ercise B, and combine them together to create a new game structure. It

will ha*e the same content, ust "refactored" to ha*e a better structure.

:irst ste is to grab the code from ex!<.rb and coy it to got/on8ebHlibH(ap.rb and coy

ex!<Ntests.rb file to got/on8ebHtestHtestN(ap.rb  and run the test suite again to ma!esure it !ees wor!ing.

 Fote

:rom now on I won't show you the outut of a test run, ust assume that you should be doing

it and it'll loo! li!e the abo*e unless you ha*e an error.

?nce you ha*e the code from 0&ercise B coied o*er, it's time to refactor it to ha*e the

0&ercise B ma in it. I'm going to start off by laying down the basic structure, and then

you'll ha*e an assignment to ma!e the (ap.rb file and the (apNtests.rb file comlete.

:irst thing to do is lay out the basic structure of the ma using the >oo( class as it is now#

$8

Page 121: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 121/128

  1    3  !  # 

  <  &  9 1" 11 1 13 1! 1# 1 1< 1& 19

 " 1  3 ! #  < & 9 3" 31 3

 33 3! 3# 3 3< 3& 39 !" !1 ! !3 !! !#

 ! !< !& !9 #" #1 # #3 #! ## # #< #& #9 " 1

,lass >oo(

  attrNa,,essor :na(eF :*es,riptionF :pat/s

  *e+ initialiZe@na(eF *es,ription  _na(e K na(e

  _*es,ription K *es,ription  _pat/s K OP  en*

  *e+ go@*ire,tion  _pat/s*ire,tionU  en*

  *e+ a**Npat/s@pat/s  _pat/s.up*ate@pat/s  en*

en*

,entralN,orri*or K >oo(.ne8@B2entral 2orri*orBFJOT/e Xot/ons o+ lanet er,al # /ave inva*e* your s/ip an* *estroye*your entire ,re8. Eou are t/e last surviving (e(ber an* your last(ission is to get t/e neutron *estru,t bo(b +ro( t/e Weapons Ar(oryFput it in t/e bri*geF an* blo8 t/e s/ip up a+ter getting into anes,ape po*.

Eoure running *o8n t/e ,entral ,orri*or to t/e Weapons Ar(ory 8/ena Xot/on Ru(ps outF re* s,aly s)inF *ar) gri(y teet/F an* evil ,lo8n,ostu(e+lo8ing aroun* /is /ate +ille* bo*y. 7es blo,)ing t/e *oor to t/e

Ar(ory an* about to pull a 8eapon to blast you.P

laserN8eaponNar(ory K >oo(.ne8@BLaser Weapon Ar(oryBFJOLu,)y +or you t/ey (a*e you learn Xot/on insults in t/e a,a*e(y.Eou tell t/e one Xot/on Ro)e you )no8:Lb/e Zbgure v+ +b sngF Rura +ur +vg+ neb/a gur ub/+rF +ur +vg+ neb/agur ub/+r.T/e Xot/on stopsF tries not to laug/F t/en busts out laug/ing an* ,ant(ove.W/ile /es laug/ing you run up an* s/oot /i( suare in t/e /ea*

putting /i( *o8nF t/en Ru(p t/roug/ t/e Weapon Ar(ory *oor.

Eou *o a *ive roll into t/e Weapon Ar(oryF ,rou,/ an* s,an t/e roo(+or (ore Xot/ons t/at (ig/t be /i*ing. =ts *ea* uietF too uiet.Eou stan* up an* run to t/e +ar si*e o+ t/e roo( an* +in* t/eneutron bo(b in its ,ontainer. T/eres a )eypa* lo,) on t/e boxan* you nee* t/e ,o*e to get t/e bo(b out. =+ you get t/e ,o*e8rong 1" ti(es t/en t/e lo,) ,loses +orever an* you ,antget t/e bo(b. T/e ,o*e is 3 *igits.P

t/eNbri*ge K >oo(.ne8@BT/e ri*geBFJOT/e ,ontainer ,li,)s open an* t/e seal brea)sF letting gas out.Eou grab t/e neutron bo(b an* run as +ast as you ,an to t/e

$$

Page 122: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 122/128

  3 ! #  <

 & 9 <" <1 < <3 <! <# < << <& <9 &"

 &1 & &3 &! &# & &< && &9 9" 91 9 93

 9! 9# 9 9< 9& 991""1"11"1"31"!1"#1"

1"<1"&1"911"1111111311!11#1111<11&1191"111

bri*ge 8/ere you (ust pla,e it in t/e rig/t spot.

Eou burst onto t/e ri*ge 8it/ t/e netron *estru,t bo(bun*er your ar( an* surprise # Xot/ons 8/o are trying tota)e ,ontrol o+ t/e s/ip. a,/ o+ t/e( /as an even uglier,lo8n ,ostu(e t/an t/e last. T/ey /avent pulle* t/eir

8eapons out yetF as t/ey see t/e a,tive bo(b un*er yourar( an* *ont 8ant to set it o++.P

es,apeNpo* K >oo(.ne8@Bs,ape o*BFJOEou point your blaster at t/e bo(b un*er your ar(an* t/e Xot/ons put t/eir /an*s up an* start to s8eat.Eou in,/ ba,)8ar* to t/e *oorF open itF an* t/en ,are+ullypla,e t/e bo(b on t/e +loorF pointing your blaster at it.Eou t/en Ru(p ba,) t/roug/ t/e *oorF pun,/ t/e ,lose buttonan* blast t/e lo,) so t/e Xot/ons ,ant get out.

0o8 t/at t/e bo(b is pla,e* you run to t/e es,ape po* toget o++ t/is tin ,an.

Eou rus/ t/roug/ t/e s/ip *esperately trying to (a)e it tot/e es,ape po* be+ore t/e 8/ole s/ip explo*es. =t see(s li)e/ar*ly any Xot/ons are on t/e s/ipF so your run is ,lear o+inter+eren,e. Eou get to t/e ,/a(ber 8it/ t/e es,ape po*sF an*no8 nee* to pi,) one to ta)e. So(e o+ t/e( ,oul* be *a(age*but you *ont /ave ti(e to loo). T/eres # po*sF 8/i,/ one*o you ta)eMP

t/eNen*N8inner K >oo(.ne8@BT/e n*BFJOEou Ru(p into po* an* /it t/e eRe,t button.T/e po* easily sli*es out into spa,e /ea*ing tot/e planet belo8. As it +lies to t/e planetF you loo)ba,) an* see your s/ip i(plo*e t/en explo*e li)e abrig/t starF ta)ing out t/e Xot/on s/ip at t/e sa(eti(e. Eou 8onCP

t/eNen*Nloser K >oo(.ne8@BT/e n*BFJO

Eou Ru(p into a ran*o( po* an* /it t/e eRe,t button.T/e po* es,apes out into t/e voi* o+ spa,eF t/eni(plo*es as t/e /ull rupturesF ,rus/ing your bo*yinto Ra( Relly.P

es,apeNpo*.a**Npat/s@O  K' t/eNen*N8innerF  I K' t/eNen*NloserP

generi,N*eat/ K >oo(.ne8@B*eat/BF BEou *ie*.B

t/eNbri*ge.a**Npat/s@O  t/ro8 t/e bo(b K' generi,N*eat/F  slo8ly pla,e t/e bo(b K' es,apeNpo*

$

Page 123: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 123/128

131!1#11<1&1913"13113133

P

laserN8eaponNar(ory.a**Npat/s@O  "13 K' t/eNbri*geF  I K' generi,N*eat/P

,entralN,orri*or.a**Npat/s@O  s/ootC K' generi,N*eat/F  *o*geCK' generi,N*eat/F  tell a Ro)e K' laserN8eaponNar(oryP

STA>T K ,entralN,orri*or

+ou'll notice that there are a coule of roblems with our Room class and this ma#

$. We ha*e to ut the te&t that was in the i+-else clauses that got rinted before

entering a room as art of each room. This means you can't shuffle the ma aroundwhich would be nice. +ou'll be fi&ing that u in this e&ercise.

. There are arts in the original game where we ran code that determined things li!e the

 bomb's !eyad code, or the right od. In this game we ust ic! some defaults and go

with it, but later you'll be gi*en e&tra credit to ma!e this wor! again.

(. I'*e ust made a generi,N*eat/ ending for all of the bad decisions, which you'll ha*e

to finish for me. +ou'll need to go bac! through and add in all the original endings

and ma!e sure they wor!.

B. I'*e got a new !ind of transition labeled BIB that will be used for a "catch1all" action

in the engine.

?nce you'*e got that basically written out, here's the new automated test testHtestN(ap.rb  that you should ha*e to get yourself started#

 1  3 ! #  < & 9

1"111131!1#11<1&19"1

3!#

reuire testHunitreuireNrelative ..HlibH(ap

,lass apTests Test::nit::Test2ase

  *e+ testNroo(@  gol* K >oo(.ne8@BXol*>oo(BF

JOT/is roo( /as gol* in it you ,an grab. T/eres a  *oor to t/e nort/.P

  assertNeual@gol*.na(eF BXol*>oo(B  assertNeual@gol*.pat/sF OP  en*

  *e+ testNroo(Npat/s@  ,enter K >oo(.ne8@B2enterBF BTest roo( in t/e ,enter.B  nort/ K >oo(.ne8@B0ort/BF BTest roo( in t/e nort/.B  sout/ K >oo(.ne8@BSout/BF BTest roo( in t/e sout/.B

  ,enter.a**Npat/s@Onort/ K' nort/F sout/ K' sout/P  assertNeual@,enter.go@nort/F nort/  assertNeual@,enter.go@sout/F sout/  en*

  *e+ testN(ap@  start K >oo(.ne8@BStartBF BEou ,an go 8est an* *o8n a /ole.B

$(

Page 124: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 124/128

<&93"31

3333!3#33<3&39!"!1!!3!!

!#!

  8est K >oo(.ne8@BTreesBF BT/ere are trees /ereF you ,an go east.B  *o8n K >oo(.ne8@BDungeonBF B=ts *ar) *o8n /ereF you ,an go up.B

  start.a**Npat/s@O8est K' 8estF *o8n K' *o8nP  8est.a**Npat/s@Oeast K' startP  *o8n.a**Npat/s@Oup K' startP

  [email protected]@8estF 8est  [email protected]@8est.go@eastF start  [email protected]@*o8n.go@upF start  en*

  *e+ testNgot/onNga(eN(ap@  assertNeual@STA>T.go@s/ootCF generi,N*eat/  assertNeual@STA>T.go@*o*geCF generi,N*eat/

  roo( K STA>T.go@tell a Ro)e  assertNeual@roo(F laserN8eaponNar(ory  en*

en*

+our tas! in this art of the e&ercise is to comlete the ma, and ma!e the automated test

comletely *alidate the whole ma. This includes fi&ing all the generi,N*eat/ obects to be

real endings. )a!e sure this wor!s really well and that your test is as comlete as ossible

 because we'll be changing this ma later and you'll use the tests to ma!e sure it !ees

wor!ing.

Sessions And Tracking ,sers

-t a certain oint in your web alication you'll need to !ee trac! of some information andassociate it with the user's browser. The web 5because of HTTP6 is what we li!e to call

"stateless", which means each re3uest you ma!e is indeendent of any other re3uests being

made. If you re3uest age -, ut in some data, and clic! a lin! to age 2, all the data you

sent to age - ust disaears.

The solution to this is to create a little data store 5usually in a database, on dis!, or in coo!ies6

that uses a number uni3ue to each browser to !ee trac! of what that browser was doing. In

/inatra it's fairly easy, and here's an e&amle showing how it's done using Rac! middleware#

reuire rubyge(s

reuire sinatra

use >a,)::Session::ool

get H,ount *o  session:,ountU YYK "  session:,ountU K1  B2ount: Osession:,ountUPBen*

get Hreset *o  session.,lear  B2ount reset to ".B

en*

$B

Page 125: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 125/128

Creating An (ngine

+ou should ha*e your game ma wor!ing and a good unit test for it. I now want to ma!e a

simle little game engine that will run the rooms, collect inut from the layer, and !ee

trac! of where a lay is in the game. We'll be using the sessions you ust learned to ma!e a

simle game engine that will#

$. /tart a new game for new users.

. Present the room to the user.

(. Ta!e inut from the user.

B. Run their inut through the game.

C. islay the results and !ee going until they die.

To do this, you're going to ta!e the trusty libHgot/on8eb.rb  you'*e been hac!ing on and

create a fully wor!ing, session based, game engine. The catch is I'm going to ma!e a *ery

simle one with basic HT)L files, and it'll be u to you to comlete it. Here's the base

engine#

 1  3 ! #  < & 91"

111131!1#11<1&19"13

!#<&93"313333!3#

reuireNrelative Bgot/on8ebHversionBreuireNrelative B(apBreuire BsinatraBreuire BerbB

(o*ule Xot/on8eb

  use >a,)::Session::ool

  get H *o

  t/is is use* to BsetupB t/e session 8it/ starting values  p STA>T  session:roo(U K STA>T  re*ire,t@BHga(eB  en*

  get Hga(e *o  i+ session:roo(U  erb :s/o8Nroo(F :lo,als K' O:roo( K' session:roo(UP  else  8/y is t/is /ereM *o you nee* itM  erb :youN*ie*  en*

  en*

  post Hga(e *o  a,tion K BOpara(s:a,tionU YY nilPB  t/ere is a bug /ereF ,an you +ix itM  i+ session:roo(U  session:roo(U K session:roo(U.go@para(s:a,tionU  en*  re*ire,t@BHga(eB  en*

en*

$C

Page 126: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 126/128

+ou should ne&t delete libHvie8sH/elloN+or(.erb  and libHvie8sHin*ex.erb and create

the two temlates mentioned in the abo*e code. Here's a *ery simle

libHvie8sHs/o8Nroo(.erb#

 1

  3 ! #  < & 91"111131!

1#11<

/1'JK roo(.na(e J'H/1'

pre'JK roo(.*es,ription J'Hpre'

J i+ roo(.na(e KK B*eat/B J'  p'  a /re+KBHB'lay AgainMHa'  Hp'J else J'  p'  +or( a,tionKBHga(eB (et/o*KBGSTB'  - input typeKBtextB na(eKBa,tionB' input typeKBS=TB'

  H+or('  Hp'J en* J'

That is the temlate to show a room as you tra*el through the game. Fe&t you need one to tell

someone they died in the case that they got to the end of the ma on accident, which is

libHvie8sHyouN*ie*.erb #

13!

/1'Eou Die*CH/1'

p'Loo)s li)e you bit t/e *ust.Hp'p'a /re+KBHB'lay AgainHa'Hp'

With those in lace, you should now be able to do the following#

$. %et the test testHtestNgot/on8eb.rb  wor!ing again so that you are testing the

game. +ou won't be able to do much more than a few clic!s in the game because of

sessions, but you should be able to do some basics.

. Run the libHgot/on8eb.rb scrit and test out the game.

(. +ou should be able to refresh and fi& the game li!e normal, and wor! with the game

HT)L and engine until it does all the things you want it to do.

"o#r &inal (%a+o you feel li!e this was a huge amount of information thrown at you all at once %ood, I

want you to ha*e something to tin!er with while you build your s!ills. To comlete this

e&ercise, I'm going to gi*e you a final set of e&ercises for you to comlete on your own.

+ou'll notice that what you'*e written so far isn't *ery well built, it is ust a first *ersion of the

code. +our tas! now is to ma!e the game more comlete by doing these things#

$. :i& all the bugs I mention in the code, and any that I didn't mention. If you find new

 bugs, let me !now.

. Imro*e all of the automated tests so that you test more of the alication and get to a

 oint where you use a test rather than your browser to chec! the alication while youwor!.

$D

Page 127: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 127/128

(. )a!e the HT)L loo! better.

B. Research logins and create a signu system for the alication, so eole can ha*e

logins and high scores.

C. ;omlete the game ma, ma!ing it as large and feature comlete as ossible.

D. %i*e eole a "hel" system that lets them as! what they can do at each room in the

game.. -dd any other features you can thin! of to the game.

4. ;reate se*eral "mas" and let eole choose a game they want to run. +our

libHgot/on8eb.rb  engine should be able to run any ma of rooms you gi*e it, so

you can suort multile games.

>. :inally, use what you learned in 0&ercises B4 and B> to create a better inut

 rocessor. +ou ha*e most of the code necessary, you ust need to imro*e the

grammar and hoo! it u to your inut form and the %ame0ngine.

%ood luc!O

&ext Steps

+ou're not a rogrammer 3uite yet. I li!e to thin! of this boo! as gi*ing you your

"rogramming brown belt". +ou !now enough to start another boo! on rogramming and

handle it ust fine. This boo! should ha*e gi*en you the mental tools and attitude you need to

go through most Ruby boo!s and actually learn something. It might e*en ma!e it easy.

Rob says: :or fun, I recommend you chec! out Why's 5Poignant6 %uide to Ruby#

htt#AAmisla*.uni3ath.comAoignant1guide )ost of the actual rogramming content will be

re*iew by now, but Why is a brilliant mind and his boo! is a wor! of art. ;hec! out some ofhis oen source roects, which are still floating around. +ou can learn a lot by reading his

code.

+ou could robably start hac!ing away at some rograms right now, and if you ha*e that

itch, go ahead. <ust understand anything you write will robably suc!. That's alright though, I

suc! at e*ery rogramming language I first start using. Fobody writes ure erfect gold when

they're a beginner, and anyone who tells you they did is a huge liar.

:inally, remember that this is something you ha*e to do at least a coule hours a night for a

while before you can get good. If it hels, while you're struggling to learn Ruby e*ery night,

I'm hard at wor! learning to lay guitar. I wor! at it about or B hours a day and still racticescales.

0*eryone is a beginner at something.

Adice Fro" An =*d ro!ra""er

+ou'*e finished this boo! and ha*e decided to continue with rogramming. )aybe it will be

a career for you, or maybe it will be a hobby. +ou'll need some ad*ice to ma!e sure you

continue on the right ath, and get the most enoyment out of your newly chosen acti*ity.

$

Page 128: Learn Ruby - The Hard Way

8/13/2019 Learn Ruby - The Hard Way

http://slidepdf.com/reader/full/learn-ruby-the-hard-way 128/128

I'*e been rogramming for a *ery long time. /o long that it's incredibly boring to me. -t the

time that I wrote this boo!, I !new about 8 rogramming languages and could learn new

ones in about a day to a wee! deending on how weird they were. 0*entually though this ust

 became boring and couldn't hold my interest anymore. This doesn't mean I thin!

 rogramming is boring, or that you will thin! it's boring, only that I find it uninteresting at

this oint in my ourney.

What I disco*ered after this ourney of learning is that it's not the languages that matter but

what you do with them. -ctually, I always !new that, but I'd get distracted by the languages

and forget it eriodically. Fow I ne*er forget it, and neither should you.

Which rogramming language you learn and use doesn't matter. o not  get suc!ed into the

religion surrounding rogramming languages as that will only blind you to their true urose

of being your tool for doing interesting things.

Programming as an intellectual acti*ity is the only art form that allows you to create

interacti*e art. +ou can create roects that other eole can lay with, and you can tal! tothem indirectly. Fo other art form is 3uite this interacti*e. )o*ies flow to the audience in one

direction. Paintings do not mo*e. ;ode goes both ways.

Programming as a rofession is only moderately interesting. It can be a good ob, but you

could ma!e about the same money and be haier running a fast food oint. +ou're much

 better off using code as your secret weaon in another rofession.

Peole who can code in the world of technology comanies are a dime a doGen and get no

resect. Peole who can code in biology, medicine, go*ernment, sociology, hysics, history,

and mathematics are resected and can do amaGing things to ad*ance those discilines.

?f course, all of this ad*ice is ointless. If you li!ed learning to write software with this

 boo!, you should try to use it to imro*e your life any way you can. %o out and e&lore this

weird wonderful new intellectual ursuit that barely anyone in the last C8 years has been able

to e&lore )ight as well enoy it while you can