Download as pdf or txt
Download as pdf or txt
You are on page 1of 213

I Love Ruby 2015 Beta

1
I Love Ruby 2015 Beta
Contents
I love Ruby....................................................4
Copyright.......................................................5
I....................................................................6
Kannan Doss.................................................6
Iain McNulty.................................................7
etting this boo!..........................................."
etting e#a$ple progra$s......................."
%he boo!s source......................................"
Installing Ruby..............................................&
Installing Ruby on Debian 'lavor
N()*inu#...............................................&
Installing Ruby Natively +Debian 'lavor
nu *inu#,.............................................1-
Installing on .in/o0s an/ Mac.............1-
Installing ID1.........................................1-
2nline Resources.........................................11
Ruby .ebsite..........................................11
Ruby 3oru$............................................11
%0itter.....................................................11
etting 4tarte/............................................15
Interactive Ruby.....................................15
Doing so$e Math...................................16
4pace /oesn7t $atter..........................15
Deci$als............................................15
8ariables.................................................15
Na$ing Convention...........................17
%he un/erscore 9 a special variable...17
Constants................................................1"
4trings.....................................................1&
4tring 3unctions.................................5-
1scape se:uence................................51
(sing %e#t 1/itor...................................55
;rinting 4o$ething.................................56
etting Input...........................................54
Co$$ents...............................................55
Co$parison an/ *ogic................................57
*ogical 2perators...................................57
true <= >true?......................................5"
i'..............................................................5&
i' else......................................................5&
elsi'.........................................................6-
unless......................................................61
unless else...............................................65
case 0hen...............................................66
@ A............................................................65
Bssigning logic state$ent to variables...66
*oops...........................................................6&
/o0nto....................................................4-
ti$es.......................................................4-
upto.........................................................41
step..........................................................45
0hile.......................................................46
until.........................................................44
brea!.......................................................45
ne#t.........................................................45
re/o.........................................................46
loop.........................................................46
Brrays..........................................................4&
More on Brray........................................51
4et operations.........................................54
Cashes an/ 4y$bols...................................56
De'ault values in Cash...........................57
*ooping hashes.......................................57
More 0ay o' hash creation.....................5"
(sing sy$bols........................................5&
Ranges.........................................................66
Ranges use/ in case .. 0hen...................64
Chec!ing Intervals..................................65
(sing triple /ots D................................66
3unctions.....................................................67
Brgu$ent ;assing...................................6"
De'ault Brgu$ent...................................6&
Returning 8alues....................................7-
Recursive 'unction..................................71
8ariable nu$ber o' argu$ents................76
Cashes to 'unctions................................74
8ariable 4cope.............................................76
lobal 8ariables.....................................7"
Classes E 2bFects......................................."5
Creating a 4:uare..................................."5
3unctions in Class.................................."6
InitialiGers or Constructors....................."4
;rivate Metho/s......................................"6
Class variables an/ $etho/s..................."7
Inheritance..............................................&-
2verri/ing Metho/s...............................&1
%he super 'unction..................................&4
1#ten/ing class.......................................&5
Re'lection...............................................&6
1ncapsulation.......................................1--
;oly$orphis$......................................1-1
Class Constants.....................................1-6
5
I Love Ruby 2015 Beta
4truct an/ 2pen4truct...............................1-6
R/oc..........................................................11-
Rea/ing Ruby Docu$entation..............11-
Creating Docu$entation.......................111
Mo/ules an/ Mi#ins..................................114
Calling 'unctions 0ithout inclu/e.........116
Classes in $o/ules...............................15-
Mi#ins...................................................155
4hebang.....................................................155
Date an/ %i$e...........................................156
Days bet0een t0o /ays........................15"
Co0 $any /ays have you live/@..........15&
3iles...........................................................165
4toring output into 'iles........................165
%a!ing 'ile as input...............................165
3ile copy 9 a !in/ o'.............................166
Displaying a 'ile...................................164
Rea/ing 'ile line by line.......................165
2pen an/ ne0 9 the /i''erence.............165
De'ining our o0n line en/ings.............167
Rea/ing byte by byte............................16"
Rea/ing single character at a ti$e........16"
Rena$ing 'iles......................................14-
3in/ing out position in a 'ile................14-
.riting into 'iles...................................145
Bppen/ing content into 'iles................144
4toring obFects into 'iles.......................145
;store...............................................145
HBM*..............................................14&
;rocI *a$b/as an/ Jloc!s........................155
;assing para$eters...............................156
;assing ;roc to $etho/s.......................156
Returning ;roc 'ro$ 'unction...............154
;roc an/ Brrays....................................155
*a$b/a.................................................156
;assing Brgu$ent to *a$b/a...............156
;roc an/ *a$b/as 0ith 3unctions.......157
*a$b/a an/ Brrays..............................15"
Jloc!s an/ 3unctions...........................15&
Multi %hrea/ing........................................161
4cope o' threa/ variables.....................164
%hrea/ 1#clusion..................................165
Dea/loc!s.............................................16"
%hrea/ 1#ception.................................17-
%hrea/ Class Metho/s..........................175
%hrea/ Instance Metho/s.....................176
1#ception Can/ling...................................175
1#ception an/ %hrea/s.........................17"
Raising 1#pceptions.............................17&
Regular 1#pressions..................................1"1
Creating a e$pty rege#p.......................1"1
Detecting ;atterns.................................1"1
%hings to re$e$ber..............................1"5
%he /ot..................................................1"6
Character classes..................................1"6
4canning...............................................1"5
Captures................................................1"7
MatchData class...................................1&-
Bnchors an/ Bssertions........................1&1
Bnchors............................................1&1
Bssertions........................................1&5
Ignoring Cases......................................1&4
Ignore 4paces.......................................1&4
e$s.........................................................1&6
4earching a ge$...................................1&6
Installing ge$.......................................1&7
8ie0ing Docu$entation.......................1&7
(sing ge$.............................................1&"
Creating a ge$......................................1&"
(ninstalling a e$...............................5--
Meta ;rogra$$ing....................................5-5
4en/......................................................5-5
Metho/ Missing....................................5-6
De'ine Metho/......................................5-6
3inal .or/.................................................5-"
3or 5-15 1/ition...................................5-"
3or 5-14 1/ition...................................5-"
3or 5-16 1/ition...................................5-"
3or 5-15 1/ition...................................5-"
3or 5-1- 1/ition...................................5-&
(n/erscore................................................511
Bn i$portant Math Discovery..................515
6
I Love Ruby 2015 Beta
I love Ruby
Ruby is an easy to learn progra$$ing languageI it 0as invente/ by a guy na$e/ MatG in Kapan.
Ruby is a 'ree
1
so't0are an/ can be use/ by any one 'or Gero cost. Ruby7s popularity 0as initially
con'ine/ to KapanI later it slo0ly tric!le/ out to rest o' the 0orl/. %hings change/ 0ith the
e$ergence o' Ruby on Rails
5
0hich is a popular 0ebL/evelop$ent 'ra$e0or! 0ritten 0ith Ruby.
I 0as thrille/ 0hen I starte/ to progra$ in Ruby. 2ne o' $y 'irst application 0as a stu/ent ran!ing
so't0are 'or $y $o$ 0ho 0as a teacher. I 0as able to 0rite the console base/ application in Fust 65
lines. %his opene/ $y eyes an/ $a/e $e realiGe the po0er o' Ruby. %he language 0as si$pleI easy
to learn an/ nearly per'ect. Currently I a$ an pro'essional Ruby on Rails progra$$er 0or!ing in
%echBrt(s
6
.
%his boo! is 0ritten 'or N()*inu# +Debian /istro, usersI thats because I thin! N()*inu# 0ill
con:uer /es!tops o' progra$$ers in near 'uture. Bl$ost all 0ho have Debian N()*inu# base/
/istro shoul/ 'eel at ho$e 0hile trying to learn Ruby using this boo!. I' you are using other
operating syste$s li!e 4olarisI 24M or .in/o0s please contact your 2perating 4yste$ help
channels to learn ho0 to install or get starte/ 0ith Ruby. Hou can also visit httpA))rubyLlang.org to
learn ho0 get starte/ 0ith Ruby.
1 3ree here /oes not $ean Gero cost. 8isit httpA))'s'.org to !no0 $ore
5 httpA))rubyonrails.org
6 httpA))techartus.co$
4
I Love Ruby 2015 Beta
Copyright
Copyright (c) 2009 - 2013 Bigbang to Infinite !arthi"eyan # !
;er$ission is grante/ to copyI /istribute an/)or $o/i'y this /ocu$ent un/e r the ter$s o' the N(
3ree Docu$entation *icenseI 8ersion 1.6 or any later version publishe/ by the 3ree 4o't0are
3oun/ationN 0ith no Invariant 4ectionsI no 3rontLCover %e#tsI an/ no Jac!LCover %e#ts. B copy o'
the license can be 'oun/ in httpA))000.gnu.org)copyle't)'/l.ht$l
5
I Love Ruby 2015 Beta
I
CiI I a$ Karthi!eyan B KI the author o' this boo!. I ca$e
across Ruby an/ 'oun/ that the language 0as /aGGling. I
thought 0hy not 0rite a boo! 'or sel' stu/y an/ so 0as
create/ this boo!.
Currently I a$ an 0eb /eveloperI I use Ruby on Rails /ue to
its great innovative 'eatures. Hou can contact $e at
77$in/sOg$ail.co$ or t0eet to O!arthi!Pa!
%his boo! is no $atch to other Ruby best sellersI this is Fust
an atte$pt to have a personaliGe/ Ruby stu/y $aterial.
Kannan Doss
I a$ very $uch grate'ul Kannan Doss 0ho once 0or!e/ in
Min/ Bs *ab as a apprentice 0eb /eveloper an/ 0as also a
Ruby on Rails gee!. I than! hi$ 'or putting sincere e''orts to
i$prove the :uality o' this boo!. Ce has proo' rea/ the entire
boo!I spotte/ $ista!es he coul/ 'in/I cataloge/ the$ an/
correcte/ the$.
.ithout hi$ this boo! 0ont be as goo/ :uality as it is no0. I
a$ not saying that this boo! is superbI but his e''orts truly
playe/ a /ecisive role to $a!e this boo! 0hat it is.
Hou can contact Kannan at /oss.!annanOg$ail.co$
6
I Love Ruby 2015 Beta
Iain McNulty
I /on7t !no0 0ho Iain isI he proo' rea/ so$e o' the pages in
this boo! very 0ell. Ce is an Irish$an an/ possibly loves
'ree/o$ o' in'or$ation. I a$ very great'ul that he has
contribute/ to this boo! an/ hope he 0ill contribute $ore.
%his is his 'aceboo! page
httpsA))000.'aceboo!.co$)iain.$cnulty.6
7
I Love Ruby 2015 Beta
Getting this book
%his boo! is hoste/ at httpA))goo.gl)1:rM(N . Bll announce$ents about this boo! are available on
'aceboo! in this (R*A httpsA))000.'aceboo!.co$)pages)ILloveLruby)17556&54&4517-5 an/ you /o
not nee/ to be a $e$ber o' 'aceboo!.co$ to access this page.
Getting example programs
%he e#a$ple progra$s in this boo! are hoste/ in ithub in the 'ollo0ing (R*A
httpsA))github.co$)$in/aslab)ilr# . I realiGe $any 0ho rea/ this boo! are startersI 0ho have Fust
plunge/ into progra$$ing. Cence you can /o0nloa/ all e#a$ples by clic!ing this lin!A
httpsA))github.co$)$in/aslab)ilr#)Gipball)$aster
The books source
et the boo!7s source here httpsA))000./ropbo#.co$)s)oF7!y&6i't0h4#v)IQ5-*oveQ5-Ruby
Q5-5-15.o/t
"
I Love Ruby 2015 Beta
Installing Ruby
Installing Ruby on Debian flavor GNU/Linux
Hou nee/ to install so$ething calle/ R8M +ruby version $anager, 0hich 0ill $anage $ultiple ruby
versions. .hy@ It7s because Ruby7s version changes so 'ast.. Je'ore you ha/ 1."I no0 1.& an/ soon
Ruby 5 0ill be out. Bpart 'ro$ Fust using Ruby aloneI you 0ill also use it 'or other stu'' li!e 0eb
/evelop$ent 0ith pac!ages such as 4inatra an/ Ruby on Rails
%M
. Hou $ight nee/ to change 'ro$
one version to other 0ithout uninstalling an/ reinstalling ruby again an/ again. R8M $anages this
'or you. .ith si$ple co$$an/s 0e can s0itch bet0een Ruby versions easily.
Installing RVM :
2KI to install R8MI you nee/ to have curl +a progra$ that can /o0nloa/ things,. %o get curlI Fust
type
$ sudo apt-get install curl
No0 install R8M using the 'ollo0ing co$$an/
$ \curl -sSL https://get.rvm.io | bash -s stable --ruby
2nce /one give these co$$an/s into ter$inal. %hese 0ill tell (buntu N( ) *inu# 0here to 'in/
the ruby interpreter.
$ echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" #
Load RVM into a shell session *as a function*' >> ~/.bashrc
$ source ~/.bashrc
2nce this is /oneI you $ay nee/ to restart your co$puter. 2pen the ter$inal an/ type the 'ollo0ingA
$ ruby -v
It 0ill spit an output so$ething li!e thisA
ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-linux]
%hen all is 2K<
&
I Love Ruby 2015 Beta
Installing Ruby Natively Debian flavor Gnu Linux!
rv$ is a version $anager 'r ruby. Hou can install $any versions o' Ruby interpreter li!e ruby 1.".7 I
ruby 1.&.6I ruby 5.-.- an/ so onI on a sa$e syste$ an/ s0itch bet0een the$ sea$lessly. 3or $ore
in'or$ation visit httpA))rv$.io
Jut so$e 0ish to install Ruby supporte/ natively on their *inu# plat'or$. 3or that all you nee/ to
/o is type the 'ollo0ing thing in your ter$inal +leave out the initial R signI as it sy$boliGes the
pro$pt
$ sudo apt-get install ruby
%he above thing 0ill install Ruby on your syste$.
Installing on "in#o$s an# %ac
I /on7t use .in/o0s or MacI so please as! respective help channels on ho0 to install Ruby in the$.
Installing ID&
Hou nee/ a goo/ ID1 +Integrate/ /evelop$ent environ$ent, to get starte/ 0ith Ruby. I reco$$en/
si$ple an/ light 0eight ID1 eany
4
. I%o install the ID1 in (buntu Fust type +0ithout that R,A
$ sudo apt-get install geany
I' the syste$ as!s 'or a/$inistrator pass0or/I provi/e it.
Clic! the /ash button an/ type in geany. Clic! on the geany iconI you 0ill get it AL,
4 .in/o0s users goto httpA))000.geany.org) to /o0nloa/ the installer
1-
I Love Ruby 2015 Beta
Online Resources
Ruby has got an e#cellent online co$$unity o' hac!ers 0ho are rea/y to help al$ost any one 0ho
has any /oubt about Ruby. %hey love the progra$$ing language an/ 0ant others to love an/
e#perience it. Ruby is a great progra$$ing language that 0ill put so$ething goo/ in your heart.
2nce you have learne/ it an/ start to interact 0ith 'ello0 hac!ersI you 0ill naturally ten/ to help
others. 4o /o visit the 0ebsites reco$$en/e/ in this section. %hey $ight be o' great use to you.
Ruby "ebsite
(R*A httpA))rubyLlang.org
Ruby 0ebsite is a great place to start 0ith Ruby. It provi/es you 0ith the installers to install Ruby
on your operating syste$. It has cool lin!s li!e 7%ry Ruby< in your bro0ser7I 0hich lets you try out
Ruby right 'ro$ your 0eb bro0ser an/ a lin! calle/ 7Ruby in %0enty Minutes7 teaches you the
basics o' Ruby progra$$ing. Ruby is such a si$ple language that you Fust nee/ 5- $inutes to
grasp it< %rust $e it7s true<
Ruby 'orum
(R*A httpA))000.rubyL'oru$.co$)
4o 0here to go i' you have /oubts 0ith Ruby@ Hou can visit httpA))000.rubyL'oru$.co$) 0hich is
a 0ebsite that is nothing but collection o' Ruby 'oru$s an/ contains lot o' :uestions an/ ans0ers
about Ruby. No $atter ho0 stupi/ you thin! it $ay beI you can post your :uestion. B !in/ enough
gentle$an +or a la/y i' you are luc!y, 0ill ans0er it. 3or heaven7s sa!eII never 'ail to as! :uestions.
%he /i''erence bet0een a goo/ an/ great progra$$er coul/ be Fust a :uestion you as!.
T$itter
(R*A httpA))t0itter.co$
%0itter is a socialiGing 0ebsite. %hen 0hy on 1arth a$ I putting it here@ .ell lots o' Ruby
progra$$ers use t0itterI possibly because it 0as 0ritten 0ith Ruby. %o get the latest ne0s about
>Ruby ;rogra$$ing?I type it in the search bar an/ press search. Hou 0ill get latest tren/ing topics
about Ruby language. %ry searches li!e >Ruby language? an/ blah blah....
11
I Love Ruby 2015 Beta
Getting Started
Caving installe/ the nee/e/ so't0areI lets gets starte/.
Interactive Ruby
Ruby provi/es us a easy 0ay to interact 0ith itI this 'eature is calle/ interactive ruby or irb. .ith irb
you can type s$all bits o' ruby co/e in your console an/ see it get e#ecute/. irb is a great tool to
chec! out s$all pieces o' Ruby co/e. In your ter$inal type irb or irb -simple-prompt I you
0ill be getting pro$pt as sho0n
irb(main):001:0>
%he above pro$pt 0ill be got i' you ha/ type/ irb
>>
%he above pro$pt 0ill be got i' you ha/ type/ irb -simple-promptI in e#a$ples 'ro$ no0 on I
0ill be using the si$ple pro$pt as its si$ple 'or $e to 0rite in this boo!. *ets 0rite our 'irst hello
0orl/ progra$I in the pro$pt type the 'ollo0ing +/on7t type those >>,
>> puts 'Hello World!'
.hen you press enterI you 0ill get output as 'ollo0s. In Ruby puts is use/ 'or printing so$e thing
onto the console.
Hello World !
=> nil
8ery 0ellI 0e have co$plete/ our hello 0orl/ progra$ un/er a $inute. *ets chec! 0hat is 56 to the
po0er o' 61
>> 56**31
=> 1562531701075863192779448904272185314811647640213651456
22;4< Hou never thought it 0oul/ be such a large nu$berI /i/ you@ Bny 0ayI the ** is use/ to 'in/
a nu$ber raise/ to the po0er o' another nu$ber.
%o :uit irb an/ return to nor$al console or ter$inal pro$pt type quit
15
I Love Ruby 2015 Beta
Doing some %ath
Co$puter is a /evice that co$putesI or /oes so$e $ath. .ith irb 0e can /o easy $ath. I' you
/on7t li!e to 0or! 0ith nu$bersI ruby can /o it 'or you. 4oI 'irstI lets a// these nu$bers A 1I 45I 67I
"&6I 75I 56 an/ L15". %o /o so in your irb pro$pt Fust type these nu$bers separate/ by a plus 7S7
sign an/ you 0ill get the result
>> 1 + 45 + 67 + 893 + 72 + 56 + -128
=> 1006
Cere are so$e co$$on $ath operators that you 0ill 'in/ use'ul
2perator .hat they /o
+
B//s nu$bers
-
4ubtracts a nu$ber 'ro$ another nu$ber
/
Divi/es a nu$ber 0ith another nu$ber
*
Multiplies t0o nu$bers
**
3in/s a nu$ber raise/ to the po0er o' another
%
3in/s the re$ain/er
+=
B//s an/ assigns a value to a variable
-=
4ubtracts an/ assigns a value to a variable
*=
Multiply an/ assigns a value to a variable
/=
Divi/es an/ assigns a value to a variable
%=
3in/s the re$ain/er an/ assigns it to a variable
Addition Example: *ets say that I 0ant to a// 56 an/ 75 an/ 'in/ its resultI I can /o it as sho0nA
>> 56+72
=> 128
Subtraction Example: In this e#a$ple I a$ subtracting 64 'ro$ 115
>> 112-64
=> 48
Division Example: *ets say I 0ant to /ivi/e 117 by15 an/ 'in/ the :uotientI I can /o in Ruby li!e
this
>> 117/12
=> 9
Power Example: *ets say I 0ant to 'in/ 0hat 0e 0ill get by cubing 'ive +'ive raise/ to the po0er
o' three,I I can /o it in Ruby as sho0n
>> 5**3
16
I Love Ruby 2015 Beta
=> 125
Modulus or Remainder Example: I 0ant to !no0 0hat 0e 0ill get as re$ain/er 0hen 0e /ivi/e
51 by 4I I can /o it as sho0n
>> 21%4
=> 1
Addition with assignment Example: *ets /eclare a variable iI set it to Gero an/ a// 54 to it. In
ruby you can /o it as sho0n
>> i = 0
=> 0
>> i+=24
=> 24
>> i
=> 24
Bt the en/ 0hen 0e type i an/ see 0e get 54. %his $eans i hol/s the value 54 in it.
Subtraction with assignment Example: *ets /eclare a variable j I assign it 0ith a value 5- an/
ta!e a0ay 17 'ro$ it
>> j = 50
=> 50
>> j -= 17
=> 33
>> j
=> 33
Bt the en/ 0hen 0e type j an/ see 0e get 66. %his $eans j hol/s the value 66 in it.
Multiplication with assignment Example: *ets /eclare a variable kI set it to 6 an/ $ultiply it by
nine
>> k = 3
=> 3
>> k *= 9
=> 27
>> k
=> 27
Bt the en/ 0hen 0e type k an/ see 0e get 57. %his $eans k hol/s the value 57 in it.
Division with assignment Example: *ets /eclare a variable sI set it to 55 an/ /ivi/e it by 5
>> s = 25
=> 25
>> s /= 5
=> 5
>> s
=> 5
Bt the en/ 0hen 0e type s an/ see 0e get 5. %his $eans s hol/s the value 5 in it.
14
I Love Ruby 2015 Beta
%ry other operators on your o0nI I7$ running out o' patience.
$pace %oe&n't (atter
*ets say that I 0ant to a// 54 0ith 65I ho0 can I co$$an/ irb to /o it. 4houl/ it be 54+62 or can I
leave spaces so that co/e coul/ be neatly 0ritten li!e 54 + 62 . .ellI 'ortunately in Ruby leaving
spaces /oesn7t really $atter you can give it in any nu$ber o' 0ays as sho0n belo0 an/ still get the
sa$e result.
>> 54+62
=> 116
>> 54 +62
=> 116
>> 54+ 62
=> 116
>> 54 + 62
=> 116
>> 54 + 62
=> 116
Notice that the plus 0eather it stic!s 0ith 54 or 65 or has space bet0een the$I no $atter ho0 long
the space isI it prints out the right result.
)eci(a*&
.hen you /ivi/e 5 by 6 in ruby you get result as 'ollo0s
>> 5/3
=> 1
In other 0or/s it gives the :uotient. In reality 5 /ivi/e/ by 6 is al$ost 1.666666666666666667I so
ho0 to get this ans0er@ %he truth is 5 an/ 6 are integersI or nu$bers that /on7t have /eci$al part. I'
you 0ant a 'airly accurate ans0er you can rephrase your co$$an/ to Ruby as 'ollo0s
>> 5.0/3
=> 1.66666666666667
In the above 0ayI 0e are speci'ying 5.- instea/ o' 5I in other 0or/s 0e are 'orcing Ruby to $a!e a
'loating point or /eci$al calculation instea/ o' integer calculation. %his $a!es Ruby to give an
'airly accurate ans0er.
(ariables
8ariables are so$ething that stores value in it. Hou can i$agine the$ as a bo# 0hich can hol/
pebbles. I' a bo# na$e/ a hol/s 'ive pebbles then its value is 5I i' another bo# b hol/s 6 pebblesI
15
I Love Ruby 2015 Beta
then its value is three. *et say you get an ne0 bo# calle/ c an/ you 0ant its value to be the su$ o'
bo# a an/ bo# bI then you si$ply a// nu$ber o' pebbles in a an/ bI it totals to "I you put " pebbles
in c to $a!e c = a+b. I hope you have got a hint 0hat a variable is. *ets progra$ it in Ruby
>> a = 5
=> 5
>> b = 3
=> 3
>> c = a+b
=> 8
*ets try another proble$I I buy 5- $angoes 'ro$ a 'ar$er at Rs 1-)L an/ bring it to the $ar!et an/
sell it at Rs 15)L eachI 0hat is $y pro'it.
Bns0erA
2K 'irst I have 5- $angoes so in irb I type as 'ollo0sA
>> mangoes = 50
=> 50
4o I have assigne/ the value o' 50 to a variable mangoes. Ne#t I /eclare an/ assign a value o' 10 to
a variable buy_price as sho0nA
>> buy_price = 10
=> 10
In a si$ilar 'ashion I assign 15 to a variable na$e/ sell_price
>> sell_price = 15
=> 15
No0 pro'it per $ango is the /i''erence bet0een sell an/ buy priceI hence I can calculate it as sho0n
>> profit = sell_price - buy_price
=> 5
Jy selling a $ango I get a pro'it o' Rs 5)LI 0hat 0ill I get by selling 5- $angoes@ Its a $ultiple o'
profit 0ith mangoes an/ 0e get it as sho0n
>> total_profit = profit * mangoes
=> 250
4o by selling 5- $angoes 0e can earn a pro'it o' Rs 55-)L. *ets say that 0e have bought 75
$angoesI no0 0e 0ant to !no0 0hat pro'it 0oul/ beI this can be easily /one by changing or
varying the value mangoes 'ro$ 5- to 75 an/ recalculating the total_profit as sho0n belo0
>> mangoes = 72
>> total_profit = profit * mangoes
=> 360
No0 you $ay !no0 0hy 0e call these things are variablesI a variable is a bo# that can contain any
value it 0ants. Kust li!e you can a// or ta!e a0ay pebbles 'ro$ a bo#I you can /o the sa$e to
16
I Love Ruby 2015 Beta
variables.
+a(ing Convention
In the $ango e#a$pleI you 0oul/ have notice/ that I have given the na$es o' variables as
buy_priceI sell_priceI total_profit an/ not as buy priceI sell priceI total profitI 0hy
so@ It turns out that one $ust 'ollo0 a certain na$ing convention or rules 0hen na$ing a variable.
%he rules o' na$ing a variable are as 'ollo0s
%here $ust be no space in bet0een variable na$es
%here $ust be no special character e#cept un/erscore P in a variable na$e
B variable na$e can have nu$bers
B variable na$e $ust not start 0ith a nu$ber
B variable $ust either start 0ith a character or an un/erscore
Capital character shoul/ not appear at the start o' variable
Jelo0 given are e#a$ples o' vali/ variable na$es
mango
total_price
mango_
_mango
buyPrice
boeing747
boeing_747
iam23yrsold
Jelo0 are given e#a$ples o' invali/ variable na$es
34signals
Mango
total cost
,he un%er&core - a &pecia* variab*e
4uppose 0e 0ant to 'in/ 0hats "7 raise/ to the po0er 15I 0e can /o as 'ollo0s
>> 87**12
=> 188031682201497672618081
No0 0e 0ant to $ultiply the result 0ith 5 an/ see the ans0erI no0 the above result is a 0hopy 54
5
/igit nu$ber an/ 0e $ust type all o' it an/ put a star 'ive to get an ans0erI thats a lot o' 0or!< I'
5 %o 'in/ nu$ber o' /igits type his in irbA +"7TT15,.toPs.length
17
I Love Ruby 2015 Beta
you are a progra$$erI laGiness shoul/ 'lo0 in your veins other0ise 'in/ another pro'ession. 2ne
0ay is to assign this value to a variable an/ $ultiply it by 5 as sho0n belo0
>> a = 87 ** 12
=> 188031682201497672618081
>> a*5
=> 940158411007488363090405
.o/ever there i& another ea&y /ay a& &ho/n be*o/
>> 87**12
=> 188031682201497672618081
>> _*5
=> 940158411007488363090405
I /i/ 'in/ out "7 raise/ to the po0er o' 15I an/ a'ter that I $ultiplies un/erscore P 0ith 'ive< Jut
ho0 co$e@ (n/erscore is a special !in/ o' variableI in it the result o' last e#ecution gets store/
auto$atically. I' you 0ant to use the last obtaine/ output you can /o so by using un/erscore P as a
variable
6
.
)onstants
(nli!e variablesI so$e values $ust be constantI 'or e#a$ple the ra/ius o' the 1arth is constantI the
spee/ o' light is constant. In proble$s that /eal 0ith these !in/ o' issuesI or in situations 0here you
are absolutely certain that so$e values 0ont changeI you can use constants.
B constant can be thought as a variable 0ho7s value /oesn7t change. Constants in Ruby starts 0ith a
capital letterI it coul/ then be 'ollo0e/ by alphabetsI nu$bers an/ un/erscore. *ets no0 have a
constant calle/ ;i 0ho value 0ill be e:ual to $athe$atical pi I to /o so Fust type the 'ollo0ing
in irb pro$pt
>> Pi = 3.1428
=> 3.1428
Caving assigne/ the value o' to a constant na$e/ PiI 0e 0ill no0 try to 'in/ area a circle
0hose ra/ius is 7 unitsI so lets use our 'aith'ul calculator the irb. .e !no0 that ra/ius o' a circle is
r
5 7
I 0here r is the circles ra/ius. In your irb pro$pt 0e can /o the calculation as 'ollo0s
>> r = 7
=> 7
>> Pi*r**2
=> 153.9972
4o 0e 'in/ area o' circle is roughly 156.&&75 s:uare unitsI 0hich is very near to the e#act value o'
6 %his un/erscore as a variable 0or!s only in interactive ruby +irb,. .hen you are e#ecuting a ruby progra$ type/ in
a 'ile this 0on! 0or!. 4ee section (n/erscore in Bppen/i#
7 .ell I !ne0 it because Blbert 1instien is $y 'rien/. I Fust tal!e/ to hi$ an/ he tol/ $e the 'or$ula 'or area o' circle
1"
I Love Ruby 2015 Beta
154 s:uare units.
2ne can as! 0eather can 0e change value o' constant@ I /on7t say its i$possibleI but i' 0e change
ruby gives us 0arning that 0e are changing the value o' a constantI a'ter the 0arning the constant
gets change/ any0ay.
>> Pi=5
(irb):35: warning: already initialized constant Pi
=> 5
In the above e#a$ple I have re assigne/ the value o' ;i to 5I as you can see in the secon/ lineI Ruby
interpreter /oes thro0s out a 0arning that ;i is alrea/y initialiGe/ constantI but any 0ay the value o'
;i gets change/ to 5. It is strongly /iscourage/ not to change values o' constants in pro'essional
progra$$ing.
*trings
%ill no0 0e have seen about nu$bersI no0 lets see so$ething about te#t. In co$puters te#t are
calle/ as string
"
. 2K lets see about strings in Ruby. *ets start 0ith an hello 0orl/. In your irb type
hello 0orl/ as sho0n
>> "hello world"
=> "hello world"
Bs a response you get an hello world. In shortI string is any stu'' thats surroun/e/ by > or by 7
No0 lets try the above e#a$ple by surroun/ing the above hello 0orl/ 0ith single :uotes
>> 'hello world'
=> "hello world"
.ell you /o get the sa$e response. 4o 0hats the /i''erence bet0een single an/ /ouble :uotes@ %a!e
a loo! at the 'ollo0ing e#a$ple
>> time_now = Time.new # Get the current time into a variable
=> Fri Jan 15 16:43:31 +0530 2010
>> "Hello world, the time is now #{time_now}"
=> "Hello world, the time is now Fri Jan 15 16:43:31 +0530 2010"
>> 'Hello world, the time is now #{time_now}'
=> "Hello world, the time is now \#{time_now}"
Bt 'irst 0e /eclare a variable calle/ time_now an/ store the current ti$e into it. %he current ti$e in
Ruby is got by Time.new co$$an/. No0 0e have a variable an/ 0e can e$be/ it into a string by
putting it li!e #{put_your_variable_here}. 4o 0e 0ant to tell the 0orl/ the ti$e no0 is
so$ethingI so 0e give a co$$an/ as sho0n
" ;ossibly because they are string o' characters
1&
I Love Ruby 2015 Beta
>> "Hello world, the time is now #{time_now}"
=> "Hello world, the time is now Fri Jan 15 16:43:31 +0530 2010"
an/ 0e get a proper result. Note that you have enclose/ the string 0ith a /ouble :uotes. No0 lets
try the sa$e thing 0ith single :uotes
>> 'Hello world, the time is now #{time_now}'
=> "Hello world, the time is now \#{time_now}"
.e see that in this case the 0orl/ is not able to see 0hat ti$e it isI rather its able to see a ugly string
as sho0n
"Hello world, the time is now \#{time_now}"
.hat ever thats put bet0een single :uotes gets printe/ as it is. Hou $ight as! 0hy # is printe/
as \#I 0ell 0e 0ill see it in escape se:uence soon.
$tring 0unction&
%here are certain cool things you can /o 0ith a string 0ith the built in 'unctions an/ routines pac!e/
into Ruby. 3or e#a$ple i' I 0ant to 'in/ the length o' a string I can use the length 'unction as sho0n
>> "my name is billa".length
=> 16
%here are $any 'unctionsI so$e o' 0hich are given in the table sho0n. I $ust 0arn you that this
table is not co$prehensiveI you $ust chec! the Ruby /ocu$entation
&
'or a co$prehensive
coverage.
Input +utput Notes
"my name is billa".length 16
%he length 'unction 'in/s the
length o' a string
"my name is billa".reverse allib si eman ym
%he reverse 'unction
reverses a string
"my name is billa".capitalize My name is billa
CapitaliGes the given string
"my name is billa".upcase MY NAME IS BILLA
Converts lo0er case
characters to uppercase
"MY NAME IS BILLA".downcase my name is billa
Converts uppercase
characters to lo0er case
"my name is billa".next my name is billb
%his is :uiet illogical 'unction
that prints the ne#t logical
4tring
& httpA))000.rubyL/oc.org)coreL1.&.6)4tring.ht$l
5-
I Love Ruby 2015 Beta
"my name is billa".empty? false
Returns true i' string is
e$ptyI else returns false
"".empty? TRUE
Returns true i' string is
e$ptyI else returns false
2KI so 0e have seen so$e 'unctionsI lets no0 see 0hat operations can be per'or$e/ on string. %he
'irst one is concatenation in 0hich t0o or $ore strings can be Foine/ togetherI ta!e a loo! at
e#a$ple belo0
>> "Hello"+" "+"World!"
=> "Hello World!"
In the co/e aboveI I have Foine/ three strings >Cello7 a +space, > >an/ >.orl/<? using a plus signI
the sa$e operation can be /one 0ith string variables too as sho0n belo0
>> string_1 = "Hello"
=> "Hello"
>> string_2 = "World!"
=> "World!"
>> string_1+" "+string_2
=> "Hello World!"
2K no0I 0e have stu/ie/ a lotI a bit o' $e/itation 0ill helpI lets chant 2M
1-
to cleanse an/ reset
our $in/. Hou !no0 Ruby can $e/itate 'or you@ In your irb type the 'ollo0ing
>> "OM "*10
3or heaven sa!e /on7t type >> < Bn/ here is your result
=> "OM OM OM OM OM OM OM OM OM OM "
%he $ultiplication operator 'ollo0e/ by a nu$ber prints a string N nu$ber o' ti$esI 0here N is the
nu$ber given a'ter T.
1&cape &e2uence
.henever you type a state$ent li!e puts Hello World! the Ruby interpreter prints Hello
World!. %hat is every thing bet0een > an/ > gets printe/. .ell not al0ays. %here are so$e things
that you can put bet0een > an/ > that 0ill escape the nor$al printing se:uence. *aunch your irb an/
type the e#a$ple given belo0A
>> puts "Hello \r World!"
World!
=> nil
4urpriseI you see only World! getting printe/. .hat happene/ to the Cello@ .ell the \r character
1- B $agical 0or/ uttere/ by saints in In/ia
51
I Love Ruby 2015 Beta
stan/s 'or carriage returnI 0hich $eans the Cello /oes get printe/. %hen the carriage)cursor returns
to the beginning o' the line an/ .orl/< gets over 0ritten on it. *i!e \r stan/s 'or carriage returnI \n
stan/s 'or ne0line. %ype the e#a$ple belo0 in irb
>> puts "Hello \n World!"
Hello
World!
=> nil
Bs you can see Hello gets printe/ in 'irst line an/ World! gets printe/ in ne#t. %his is because 0e
have place/ a ne0 line character \n in bet0een the$.
.ell no0 lets ta!e a scenarioI 0e no0 !no0 that \rI \n an/ possibly others are non printing
characters. No0 ho0 to print \n or \r in our output. Bs it turns out that putting a /ouble bac!0ar/
slash 0oul/ print a bac!0ar/ slash in output as /e$onstrate/ by e#a$ple belo0.
>> puts "Hello \\n World! => Hello \n World!"
Hello \n World! => Hello
World!
=> nil
In a si$ilar 'ashion \t puts tab spacesI 0here ever they are place/. %ry the e#a$ple belo0
>> puts "Tabs \t leave\tlong spaces"
Tabs leave long spaces
=> nil
I hope you have un/erstoo/ so$ething about 4tringsI lets $ove on......
Using Text &#itor
%ill no0 you have !eye/ in s$all progra$s into your irbI 0hen you are /eveloping large so't0are
you can7t e#pect the en/ user or your clients to !eep !eying in into the console the state$ents you
have /evelope/ 'or hi$ ) herI instea/ you 0ill be han/ing over a type/ Ruby progra$ 0hich they
can run it to acco$plish certain tas!. *ets see ho0 to use a te#t e/itor to 0rite progra$s.
1arlier in Installing ID1 section I have type/ about ho0 to install a si$ple Integrate/ Develop$ent
1nviron$ent +ID1, calle/ eany. I' you are using (buntuI press super !eyI type in eanyI clic! on
the eany icon an/ you 0ill get it.
55
I Love Ruby 2015 Beta
Hou can use other ID17s tooI i' 0ant other ID1I re'er to their /ocu$entation 'or installation
instructions. In the ID1 type the 'ollo0ing progra$
puts "Hello World!"
puts "This time I used text editor"
No0 save the 'ile as hello_world.rb in a /irectoryI note that Ruby 'iles en/s 0ith .rb +/ot rb,
e#tension. *aunch your ter$inal ) consoleI $igrate to the /irectory 0here progra$ is store/ an/
type the 'ollo0ing in it
ruby hello_world.rb
an/ here7s ho0 you 0ill get the output.
Hello World!
This time I used text editor
.on/er'ul< Hou have learne/ to progra$ 0ith a te#t e/itorI you are getting pro'essional aye<
,rinting *omething
4tu/y the co/e hello_world.rb I 0e have use/ a Ruby co$$an/ calle/ puts I this co$$an/s
puts so$ething to the outputI in this case your ter$inal 0in/o0.
puts "Hello World!"
puts "This time I used text editor"
%he 'irst line prints Hello World! an/ the secon/ one prints This time I used a text
editor . .hat i' you 0ant to print t0o things in the very sa$e line@ 3or it (se the print
co$$an/I lets type a ne0 progra$ hello_world_1.rb 'or itI in your te#t e/itor type the 'ollo0ing
co/e
print "Hello World! "
print "Once again I used a text editor"
56
I Love Ruby 2015 Beta
%his gives the outputA
Hello World! Once again I used a text editor
4o you have learne/ to print so$ething<
Getting Input
B progra$ is $ore use'ul 0hen it interacts 0ith the userI lets 0rite a progra$ that as!s us our na$e
an/ says hello to us. %ype the 'ollo0ing co/e +I save/ it as say_hello.rb,
puts "Hello I am Zigor, a automated Robot that says Hello"
print "Please enter your name:"
name = gets()
puts "Hello #{name}"
No0 run itI this is ho0 the output 0ill loo! li!e
Hello I am Zigor, a automated Robot that says Hello
Please enter your name:Karthik
Hello Karthik
*ets 0al!thru the progra$
%he 'irst line
puts "Hello I am Zigor, a automated Robot that says Hello"
;rints that the progra$ na$e is Uigor an/ its a auto$ate/ robot that 0ishes you Cello. %hen it
prints a line 'ee/I hence the content thats printe/ then on goes to the ne#t line
%he secon/ line
print "Please enter your name:"
prints out Please enter your name: I note that 0e have use/ print hereI not puts because
0e 0ant to get the user7s na$e right a'ter name:I I 'eel it 0ill be a0!0ar/ i' 0e let the$ type na$e
in the ne#t lineI so to avoi/ the line 'ee/ I a$ using print instea/ o' puts.
.hen the user enters na$e an/ presses enterI it is caught by the gets() 'unction an/ the thing you
type/ is store/ in the variable calle/ na$e because o' this piece o' co/e
name = gets()
No0 all our Uigor nee/s to /o is to 0ish helloI 'or 0hich 0e use this co/e
puts "Hello #{name}"
Notice ho0 0e are e$be//ing the variable na$e into string by putting it bet0een #{ an/ }. %he
sa$e e''ect can be achieve/ by using co/e li!e this
54
I Love Ruby 2015 Beta
puts "Hello "+name
Jut /oesn7t the 'or$er piece o' co/e loo! better@ Its all your choice. Ruby lets you /o the sa$e
thing in $any 0ays. Hou can choose anything that you 'eel co$'ortable.
Bny 0ay in this topic the line you $ust be loo!ing at is the one that has gets() $etho/ or 'unctionI
it 0aits 'or a !eyboar/ inputI 0hen you give an input an/ press enterI it ta!es your input an/ assigns
the value to variableI in this case the variable is na$e.
)omments
Co$$ents are s$all pieces o' notes you can put into a progra$ so that you or so$e one else 0hen
going through the progra$ 7I65" years 'ro$ no0 0ill re$e$ber or co$e to !no0 0hat its /oing.
Hou $ay be s$art to/ayI but to$orro0 you $ay not be as s$art as you are no0I your boss or client
0ho has pai/ you 0ill yell upon you at that $o$ent to 'i# a priority bug or to up/ate a so't0are.
Hou open your /ot rb 'ile an/ see this co/e
puts "Hello I am Zigor, a automated Robot that says Hello"
print "Please enter your name:"
name = gets()
puts "Hello #{name}"
Hou $ight be able to un/erstan/ it no0I but a'ter 7I65" years
11
@ Bt that ti$e you $ight have
'orgotten Ruby altogether< 4o start co$$enting. 4ee the sa$e progra$ comment.rb belo0I ho0 it
loo!s li!e @
# The client is an idiot
# he wants me to update a software after 7,658 years.
# The hell with him
puts "Hello I am Zigor, a automated Robot that says Hello" # zigor is some
stupid robot
print "Please enter your name:" # Tells the user to enter his name
name = gets() # gets the user name and assigns it to a variable named name
puts "Hello #{name}" # Embeds name into the string that gets printed
*oo! at the co/e aboveI you have tol/ so$ething about client in the 'irst three lines. %hese lines
start 0ith a # +hash or chec! sign,. %he thing that 'ollo0s a'ter a chec! sign is a co$$entI
co$$ents /on7t inter'ere 0ith progra$s e#ecution but it can be use/ to provi/e visual hints to
hu$ans o' 0hats going on in the progra$.
No0 lets loo! at this line
puts "Hello #{name}" # Embeds name into the string that gets printed
11 Hou can live so long i' science progresses 'ast enough. Researches have /ata to $a!e you live so long< 4o be
hope'ul.
55
I Love Ruby 2015 Beta
here you have #{name} enclose/ 0ithin /ouble :uotesI hences its treate/ as a e$be//e/ ruby co/e
in a string rather than a co$$entI 0hereas # Embeds name into the string that gets
printed is treate/ as co$$ent.
4o I hope you un/erstan/ that co$$ent can one /ay help. ;ro'essionals al0ays co$$ent 0hen they
0rite co/e. %hey 0ill ta!e pains so that al$ost any Ruby co/er 0ho rea/s their progra$ 0ill be
able to un/erstan/ ho0 it 0o!s.
Multiline omments
I' you 0ant to put lot o' co$$entsI about the siGe o' a paragraphI then you can put that piece o' te#t
bet0een =begin an/ =end as sho0n in the progra$ comments_multiline.rb belo0
=begin
The client is an idiot
he wants me to update a software after 7,658 years.
The hell with him
=end
puts "Hello I am Zigor, a automated Robot that says Hello" # zigor is some
stupid robot
print "Please enter your name:" # Tells the user to enter his name
name = gets() # gets the user name and assigns it to a variable named name
puts "Hello #{name}" # Embeds name into the string that gets printed
In the co/e above note ho0 0e put these te#tA
The client is an idiot
he wants me to update a software after 7,658 years.
The hell with him
bet0een =begin an/ =end I 0hen you e#ecute the progra$I those bet0een the =begin an/ =end
0ill be ignore/. 4o /on7t hesitate to 0rite a lot o' co$$entI as no0 you !no0 there is a 0ay to /o it
an/ it 0ill bene'it you an/ your 'ello0 progra$$ers greatly.
%here is one s$all thing you $ust !no0 about =begin an/ =end I that is they $ust start 'ro$ the
'irst colu$nI there shoul/ not be any spaces be'ore the = signI i' there isI ruby 0ill thin! there its a
progra$$ing $ista!e an/ 0ill signal an error.
56
I Love Ruby 2015 Beta
Comparison and ogic
Logical +perators
*ogical operators lets you /eter$ine 0eather so$e thing is true or not. 3or e#a$ple one is oneI
thats 0hat hu$ans thin!I lets see 0hat co$puters thin! about it. 3ire your irb an/ type one e:uals to
one as sho0n
>> 1 == 1
=> true
.ellI 0hats that /ouble e:ualto sign@ B single e:ual to sign $eans assign$entI 'or e#a$ple a = 5 I
puts value 5 into a. B /ouble e:ual to sign is co$parison. 4o above 0e have chec!e/ i' 1 is e:ual to
1 an/ the ans0er is true. Co$puters are intelligentI aren7t they@
2KI no0 lets chec! i' 1 e:uals to 5I so 0e type 1==2 an/....
>> 1 == 2
=> false
%he co$puter +Ruby interpreter in this case, tells its 'alse. .ell .. 0hat to say@
15
3ineI i' 1 is not e:ual to 5 to a co$puter 0hen 0e type itI it $ust putout trueI so type it in your
console
>> 1 != 2
=> true
%he <= stan/s 'or not e:ual to. %he < 4tan/s 'or not
No0 0e chec! i' one is not e:ual to 1 an/ the co$puter as e#pecte/ gives 'alse as output.
>> 1 != 1
=> false
.e no0 chec! i' 5 is greater than 6I 'or greater thanI 0e use V sign
>> 2 > 3
=> false
2h< 5 is not greater than 6I poor poor 5 AL+
*ets get $ore intelligent hereI 0e 0ill chec! i' 5 is less than 6I 'or less than 0e use W sign
>> 2 < 3
=> true
15 Rea/ a $athe$atical proo' that co$puters /o go 0rong
57
I Love Ruby 2015 Beta
Cool< .e 'oun/ that i' 5 is not greater than 6I then its less than 6. .ell 0e are going to get a Nobel
priGe 'or Math
16
.
%he V= stan/s 'or greater than or e:ual to
>> 5 >= 3
=> true
4ince 5 is greater than 6I it returns true
4ee the e#pression belo0I it still returns true because 5 is e:ual to 5
>> 5 >= 5
=> true
5 is not greater than 5 so it returns 'alse
>> 5 > 5
=> false
6 is less than 5 hence the less than or e:ual to operator W= returns true
>> 3 <= 5
=> true
6 is e:ual to 6 hence the less than or e:ual to operator still returns true
>> 3 <= 3
=> true
6 is not less than 6I its e:ual to 6 +si$ilar to all hu$ans are e:ual,I hence the less than operator
returns 'alse
>> 3 < 3
=> false
Hou can also try these 0ith nu$bers
2perator Meaning
!<
Not less than
!>
Not greater than
Bn/ /o they 0or!@ N,
true 34 5true6
In the logic operator section you $ight see that irb gives true or 'alse as output. Hou $ustn7t con'use
16 .hen contacte/I un'ortunately the Nobel co$$ittee tol/ $e that i' I ha/ /iscovere/ 5 is less than 6 in "-I--- J.C it
0oul/ a0ar/ $e the Nobel priGe. 4o$e crac! see$e/ to have /iscovere/ it be'ore I /i/. Bny 0ay no proble$I i' I
can invent a ti$e $achine an/ goto "-I--- JC an/ announce $y great /iscovery I 0ill get the Nobel. 4o I $ight on
or o'' 0riting the boo! as I have to concentrate $y energy on inventing %i$e Machine.
5"
I Love Ruby 2015 Beta
0ith >true? an/ >'alse?. %he true an/ false are logical values 0hereas >true? an/ >'alse? are
string.
if
%he if !ey0or/ is use/ to e#ecute a state$ent i' a con/ition is satis'ie/. %a!e a loo! at the progra$
belo0. 1#ecute it.
# if.rb
puts "Whats your name?"
name = gets.chop
puts "#{name} is genius" if name == "Zigor"
puts "#{name} is idiot" if name != "Zigor"
%his is ho0 thee result 0oul/ be i' you give a na$e other than Uigor
Whats your name?
Karthik
Karthik is idiot
%a!e a loo! at the progra$. %a!e a loo! at the 'ollo0ing line
puts "#{name} is genius" if name == "Zigor"
%he progra$ gets your na$e in variable calle/ name . No0 it chec!s i' the name is Uigor in the
co/e highlighte/ aboveI i' yes it e#ecutes the state$ent associate/ 0ith itI in this case it prints out
that the particular na$e is genius. It then co$es /o0n to ne#t state$ent
puts "#{name} is idiot" if name != "Zigor"
In this state$ent it chec!s i' name is not UigorI i' yes it prints the na$e is i/iot.
if else
*ets 0rite the 0ho7s genius progra$ in another 'or$I here 0e use if else con/ition instea/ o' if.
%a!e a loo! at the co/e belo0 na$e/ if_else.rb
# Zigor says if the person is intelligent or not
print "Enter your name: "
name = gets.chop
if name == "Zigor"
puts "#{name} is intelligent"
else
puts "#{name} is idiot"
end
%he progra$ 0hen e#ecute/ gives the sa$e output as previous if.rb I 0hats /i''erent is ho0 the
logic is represente/ insi/e the progra$. .e see a thing calle/ if name == "Zigor" I then 0hat
has to be e#ecute/ i' the co/e is true co$es a'ter that as sho0n
5&
I Love Ruby 2015 Beta
if name == "Zigor"
puts "#{name} is intelligent"
No0 0e can put any nu$ber o' state$ents a'ter that if an/ all 0ill be e#ecute/ i' the con/ition
given is satis'ie/. 3ine till no0I but ho0 0ill Ruby !no0 0here the i' state$ent gets over@ %o say
that things en/ here 0e put an en/ !ey0or/ as sho0n.
if name == "Zigor"
puts "#{name} is intelligent"
end
*ets say that that con/ition+s, given in the i' is not satis'ie/ an/ 0e nee/ to /o so$ething i'
con/ition is invali/I then 0e put those state$ents that gets e#ecute/ 0hen con/itions 'ails un/er the
else !ey0or/ as sho0n
if name == "Zigor"
puts "#{name} is intelligent"
else
puts "#{name} is idiot"
end
Note that the else an/ state$ents that nee/s to be e#ecute/ 0hen con/ition 'ails co$es be'ore the
end state$ent. %he end $ar!s the en/ o' i' else bloc!. Its not al0ays necessary to have elseI
instea/ 0e coul/ have a co/e as sho0n
if <condition>
# many lines of code goes here
end
In the above you can put $any lines o' co/e that nee/s to be e#ecute/ insi/e a if end bloc!.
elsif
.hen 0e use if an/ elseI the co/e un/er if gets e#ecute/ i' the con/ition is satis'ie/I else the
co/e un/er else section gets e#ecute/. *ets have a ne0 scenario 0here the co/e un/er if is not
satis'ie/I then the progra$ i$$e/iately Fu$ps to the else sectionI no0 the logic /e$an/s that 0e
nee/ to chec! another con/ition at the else level tooI 0hat shoul/ 0e /o@ %o /eal 0ith such a
scenario 0e can use the elsif co$$an/. %a!e a loo! at the co/e belo0
# elsif.rb
# finds the greatest of three numbers
a,b,c = 3,7,5
if a >= b and a >= c
puts "a = #{a} is greatest"
elsif b >= c and b >= a
puts "b = #{b} is greatest"
6-
I Love Ruby 2015 Beta
else puts "c = #{c} is greatest"
end
.hen e#ecute/ it pro/uces the 'ollo0ing result
b = 7 is greatest
*ets 0al!thru the co/e step by step. *ets loo! at the line
a,b,c = 3,7,5
In this line 0e assign values 6I 7 an/ 5 to variables a,b an/ c. *ets no0 co$e to the i' state$ent
if a > b and a > c
In this state$ent 0e chec! i' a is greater than b an/ i' a is greater than c. !ote the "e#word and$
%he if con/ition is satis'ie/ only i' both con/itions are true. a is less than b hence this con/ition
'ails so progra$ s!ips the if state$ent an/ co$es to the elsif state$ent
elsif b > c and b > a
elsif is else plus ifI here 0e chec! on another t0o con/itions thats separate/ by andI 0e chec! i'
b is greater than a an/ i' b is greater than cI both are true an/ hence the state$ent un/er elsif
puts "b = #{b} is greatest"
gets e#ecute/ an/ 0e get the result. 4ince the elsif is satis'ie/ other else an/ the co/e that co$es
un/er it is ignore/.
unless
(nless is another 0ay to chec! a con/ition. *et say that one is not a $aFor an/ is consi/ere/ a chil/
unless he or she is less than 1" years ol/. 4o ho0 to co/e it in Ruby@ Consi/er the progra$ belo0I
type it in a te#t e/itor an/ e#ecute it.
# unless.rb
print "Enter your age:"
age = gets.to_i
p "You are a minor" unless age >= 18
.hen e#ecute/ this is 0hat 0e get
Enter your age:16
"You are a minor"
%he progra$ as!s your ageI it says you are $inor i' age is not greater than 1". %hat is it says you
are a $inor i' unless your age is greater than or e:ual to 1" +see the highlighte/ co/e,. %he p is a
!in/ o' short 'or$ 'or puts
14
. I' you 0rite puts something I the ruby interpreter prints
something. I' you use p something I the ruby interpreter prints something.
14 %his isnot the right /e'initionI but Fust re$e$ber it in that 0ay
61
I Love Ruby 2015 Beta
I' 0e 0ant to put $ore than a line o' co/e un/er an unless bloc! 0e can use unless en/ bloc! as
sho0n belo0
unless <condition>
# many lines of code goes here
end
%he co/e in the bloc! gets e#ecute/ i' the <condition> 'ails. unless can be thought as opposite o'
if. B if bloc! gets e#ecute/ i' the con/ition in it is trueI a unless bloc! gets e#ecute/ i' the
con/ition in it is 'alse.
unless else
Kust li!e if 0ith elseI 0e can have else in an unless state$ent. %ype in the progra$ belo0 an/
e#ecute it
# unless_1.rb
print "Enter your age:"
age = gets.to_i
unless age >= 18
p "You are a minor"
else p "You are a grown up"
end
%his is 0hat you get 0hen you e#ecute it
Enter your age:37
"You are a grown up"
2KI here is ho0 it 0or!s I you get your ageI convert it into integer an/ store it in a variable calle/
age. Concentrate on the highlighte/ co/eI unless the age is less than 1" You are a minor
/oesn7t get printe/ out. I' the age is greater than or e:ual to 1" it gets route/ to the else state$ent
an/ You are a grown up gets printe/. Note that i' 0e use else 0ith unless 0e $ust ter$inate
the unless bloc! 0ith an end co$$an/.
*ets no0 loo! at another progra$ that uses the unless else. .e 0ant to hire people 'or ar$e/
'orcesI the person shoul/ be bet0een 1" an/ 65 years o' ageI our progra$ as!s the /etails 'ro$ a
person 0ho 0ishes to enrollI it chec!s his age an/ tells the result. %ype the progra$ belo0 an/
e#ecute it
# unless_2.rb
print "Enter your age:"
age = gets.to_i
unless age < 18 or age > 35
p "You can enter Armed forces"
else p "You cannot enter Army. You are either too young or too old"
65
I Love Ruby 2015 Beta
end
.hen e#ecute/ this 0ill be the result
Enter your age:23
"You can enter Armed forces"
I thin! you can e#plain this progra$ on your o0n. I' else contact $eI I 0ill 0rite an e#planation
unless I a$ laGy.
case $hen
4uppose you 0ant to 0rite a progra$ that has a /eter$ine/ output 'or /eter$ine/ inputI you can
use the case 0hen. *ets say that 0e 0ant to 0rite a progra$ that spells 'ro$ 1 to 5I 0e can /o it as
sho0n in case_when.rb I type the progra$ in te#t e/itor an/ e#ecute it.
# case_when.rb
# This program spells from one to five
print "Enter a number (1-5):"
a = gets.to_i
spell = String.new
case a
when 1
spell = "one"
when 2
spell = "two"
when 3
spell = "three"
when 4
spell = "four"
when 5
spell = "five"
else
spell = nil
end
puts "The number you entered is "+spell if spell
2utput
Enter a number (1-5):4
The number you entered is four
*ets see ho0 the above progra$ 0or!s. 3irst the user is pro$pte/ to enter a nu$berI 0hen he /oes
enters a nu$berI it gets converte/ 'ro$ 4tring to Integer in the 'ollo0ing state$ent
a = gets.to_i
%he variable a no0 contains the value o' nu$ber 0e have entere/I 0e have the case state$ent as
sho0n
66
I Love Ruby 2015 Beta
case a
......
end
In the above e$pty case state$ent 0e are going to 0rite co/e that gets e#ecute/ /epen/ing on the
value o' a. .hen a is 1 0e nee/ to spell out as >one? so 0e a// the 'ollo0ing co/e
case a
when 1
spell = "one"
end
4i$ilarly 0e a// co/e till the case is 5 as sho0n
case a
when 1
spell = "one"
when 2
spell = "two"
when 3
spell = "three"
when 4
spell = "four"
when 5
spell = "five"
end
%here coul/ be a case 0hen the hu$an 0ho runs this progra$ coul/ give a 0rong inputI so 0e nee/
to /eal 0ith those cases too. 3or that 0e a// a special state$ent calle/ elseI i' all the when cases
'ailsI the co/e un/er else is e#ecute/I it $ust ho0ever be note/ that its not $an/atory to have an
else bet0een case end bloc!. 4o no0 the progra$ changes as sho0n
case a
when 1
spell = "one"
when 2
spell = "two"
when 3
spell = "three"
when 4
spell = "four"
when 5
spell = "five"
else
spell = nil
end
Ne#t all 0e $ust /o is to print out spell 0hich 0e /o it in the 'ollo0ing state$ents
puts "The number you entered is "+spell if spell
Note that 0e print out only i' spell contains a valueI else i' spell is nil nothing is printe/. It is
ta!en care by the if con/ition thats been highlighte/ above.
64
I Love Ruby 2015 Beta
4o$eti$es it $ight be necessary that 0e nee/ to e#ecute sa$e set o' state$ents 'or $any
con/itions. *ets ta!e a sa$ple application in 0hich the progra$ /eter$ines a nu$ber 'ro$ 1 to 1-
+both inclusive, is o// or even. %ype the co/e belo0 +case_odd_even.rb, an/ e#ecute it
# case_odd_even.rb
num = 7 # put any number from 1 to 10
case num
when 1, 3, 5, 7, 9
puts "#{num} is odd"
when 2, 4, 6, 8, 10
puts "#{num} is even"
end
2utput
7 is odd
Notice that in above progra$ 0e assign a value 7 to a variable numI ne#t 0e put the num in a case
state$ent. .hen the nu$ber is 1I 6I 5I 7 an/ & 0e nee/ to print its o// so all 0e /o is to group the
cases. .hen its satis'ie/ it $ust print as o//I 'or that its Fust enough i' you put it as sho0n in
highlighte/ co/e belo0
case num
when 1, 3, 5, 7, 9
puts "#{num} is odd"
end
Ne#t all 0e nee/ to print the nu$ber is even i' its 5I 4I 6I " an/ 1-I to /o this tas! all 0e nee/ to /o
is to a// co/e that highlighte/ belo0
case num
when 1, 3, 5, 7, 9
puts "#{num} is odd"
when 2, 4, 6, 8, 10
puts "#{num} is even"
end
%hats it. %he co/e 0ill 0or! 'ine 'or all nu$bers 'ro$ 1 to 1-. %he $oral o' the story is 0e can
easily group cases an/ e#ecute a co$$on co/e un/er it.
- .
%he ? : is calle/ tertiary operator. It can be use/ as a si$ple if. %a!e the progra$ sho0n belo0.
Concentrate on the highlighte/ co/e belo0
# max_of_nums.rb
a,b = 3,5
max = a > b ? a : b
65
I Love Ruby 2015 Beta
p "max = "+max.to_s
.hen e#ecute/ the progra$ gives the 'ollo0ing output
"max = 5"
.ell the ?: 0or!s as 'ollo0s. It synta# is li!e this
<evaluate something > ? <if true take this thing> : <if false take this thing>
Hou give an e#pression be'ore the :uestion $ar!. %his e#pression $ust either return true or 'alse. I'
the e#pression returns true it returns the stu'' bet0een ? an/ : I i' 'alse it returns the stu'' a'ter A
In the e#pression
max = a > b ? a : b
.e can substitute the values o' a an/ b as 'ollo0s
max = 3 > 5 ? 3 : 5
6 is not greater than 5I hence its 'alse. Cence the value a'ter A is assigne/ to $a#. Cence $a#
beco$es 5.
/ssigning logic statement to variables
.on/er 0eather you notice/ or notI in previous e#a$ple max_of_nums.rb 0e have use/ a
state$ent li!e this
max = a > b ? a : b
Cere a > b is logic I i' its true it 0oul/ return a 0hich gets assigne/ to max or it returns b 0hich
gets assigne/ to max.
No0 the sa$e progra$ can be 0ritten as 'ollo0s
# max_of_nums_with_if.rb
a,b = 3,5
max = if a > b
a
else
b
end
p "max = "+max.to_s
2utput
"max = 5"
Kust ta!e a loo! at highlighte/ co/e part. Cere the variable max is assigne/ to an if con/ition. 4o i'
66
I Love Ruby 2015 Beta
a is greater than b it 0ill put a into $a# else it 0ill put b in max. Bs si$ple as that.
No0 there is another stu''. .hat i' there are $ore state$ents un/er if or else @ 4ince in this co/e
bloc!
max = if a > b
a
else
b
end
there is only one state$ent un/er if bloc! that is aI an/ un/er else bloc! 0e Fust have b I so its
straight 'or0ar/. No0 lets try out the e#a$ple given belo0
# max_of_nums_with_if_many_statements.rb
a,b = 3,5
max = if a > b
a+b
a
else
a-b
b
end
p "max = "+max.to_s
Run the above progra$ an/ this is 0hat you get
"max = 5"
4o 0hat to in'er@ %he rule is thisI i' you give $any state$ents in a bloc! an/ assign it to a variableI
the out put o' the last state$ent 0ill get returne/ an/ 0ill be put into the variable
15
+max in this
case,.
Cere is another progra$ I a 'or! o' case_when.rb I I guess you !no0 ho0 it 0or!s no0
# case_when_2.rb
# This program spells from one to five
print "Enter a number (1-5):"
a = gets.to_i
spell = String.new
spell = case a
when 1
"one"
when 2
"two"
when 3
"three"
15 Hou $any un/erstan/ it 0ell 0hen you are rea/ing about 'unctions
67
I Love Ruby 2015 Beta
when 4
"four"
when 5
"five"
else
spell = nil
end
puts "The number you entered is "+spell if spell
Run it an/ see it 'or yoursel'.
6"
I Love Ruby 2015 Beta
oops
Bt ti$es you $ight nee/ to /o so$e repetitive tas! lets say that I 0ant to 0rite a roc!et count/o0n
progra$I I 0ant to create a auto$ate/ robot that count /o0n 'or roc!etsI 0hen the count is 'inishe/
it says >Jlast 2''?I lets 0rite one an/ see
# count_down.rb
# Zigor tells about itself
puts "Hello, I am Zigor...."
puts "I count down for rockets"
# Count down starts
puts 10
p 9 # p is a short form for puts
p 8
p 7
p 6
p 5
p 4
p 3
p 2
p 1
p "Blast Off!"
.ell I hope you un/erstan/ the progra$ above. %here is one thing I 0oul/ li!e to e#plainI p is a
short 'or$ o' putsI rather than 0riting puts one can use p an/ get the sa$e result
16
. %he above
progra$ 0hen run prints the 'ollo0ing
Hello, I am Zigor....
I count down for rockets
10
9
8
7
6
5
4
3
2
1
"Blast Off!"
4o a per'ect e#ecutionI but 0e can $a!e this $ore e''icient to co/eI 0e 0ill soon see ho0
16 .ellI al$ost.
6&
I Love Ruby 2015 Beta
#o$nto
In your te#t e/itor type the 'ollo0ing progra$
# count_down_1.rb
# Zigor tells about itself
puts "Hello, I am Zigor...."
puts "I count down for rockets"
# Count down starts
10.downto 1 do |num|
p num
end
p "Blast Off!"
Run it an/ see. .ell your progra$ uses no0 a lot less co/e an/ yet it pro/uces the sa$e result< %o
!no0 ho0 the progra$ runsI loo! at the co/e highlighte/I notice the thing 10.downto 1 I this
state$ent $a!e Uigor count /o0n 'ro$ 1- to 1 I 0hile it count /o0ns you can /o so$e thing 0ith
the count/o0n value I you can put so$e co/e in the loop bloc!. %he loop starts 0ith a do an/ en/s
0hen it encounters a end co$$an/. Bny co/e you put shoul/ be bet0een the do an/ end bloc!
17
as
sho0n belo0
10.downto 1 do
# do some thing! Anything!!
end
4o bet0een the /o an/ en/ + technically its calle/ a bloc! , you can put the co/e to print the count
/o0n nu$ber. 3irst ho0 to get the nu$ber@ 0e 0ill get it in a variable calle/ num I so 0e re0rite
the co/e as sho0n
10.downto 1 do |num|
# put the printing stuff here
end
Notice above that num is surroun/e/ by X an/ X . Bll 0e nee/ to /o no0 is to print itI so 0e Fust print
it<
10.downto 1 do |num|
p num
end
times
ti$es is a very si$ple loopI i' you 0ant to get a co/e e#ecute/ N nu$ber o' ti$es you put the co/e
in it. No0 lets see 0hat Uigor !no0s
# times.rb
17 Hou can use open an/ close/ 'lo0er ) curly brac!ets Y an/ Z instea/ o' /o an/ en/ in Ruby
4-
I Love Ruby 2015 Beta
puts "Hi, I am Zigor"
puts "I am going to tell what I know"
7.times{
puts "I know something"
}
.ell 0hen e#ecute/ the progra$ prints the 'ollo0ing
Hi, I am Zigor
I am going to tell what I know
I know something
I know something
I know something
I know something
I know something
I know something
I know something
Uigor tells that it !no0s so$ething seven ti$es.
2K 0e have $a/e changes in the progra$I 0e are printing the count variable this ti$eI type the
progra$ belo0 an/ e#ecute
# times_1.rb
puts "Hi, I am Zigor"
puts "I am going to tell what I know"
7.times{ |a|
puts "#{a}. I know something"
}
Cere is 0hat you get the result
Hi, I am Zigor
I am going to tell what I know
0. I know something
1. I know something
2. I know something
3. I know something
4. I know something
5. I know something
6. I know something
.hy its counting 'ro$ Gero to si# rather than one to seven@ .ell i' all happens as you 0antI there
0ill be no nee/ o' progra$$ers li!e you an/ $eI so /on7t bother. Notice that in these progra$s 0e
use { an/ } rather than do an/ end. .ellI Ruby encourages /i''erent styles o' progra$$ing.
upto
upto counts so$e nu$ber upto so$e other nu$ber. Its li!e downto in reverse. %ype in the progra$
belo0 an/ e#ecute it
# upto.rb
41
I Love Ruby 2015 Beta
# upto is downto in reverse
17.upto 23 do |i|
print "#{i}, "
end
Bn/ here is ho0 the output loo!s li!e
17, 18, 19, 20, 21, 22, 23,
step
step loop can be thought as co$bination o' upto an/ downto all pac!e/ in oneI e#ecute the co/e
sho0n belo0
# step _1.rb
# explains step function
1.step 10 do |i|
print "#{i}, "
end
an/ here is the result. %his is very si$ilar to upto< Don7t you see<<
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
No0 lets $o/i'y the progra$ as sho0n belo0 an/ save it in another na$e
# step _2.rb
# explains step function
10.step 1 do |i|
print "#{i}, "
end
.hen e#ecute/ this progra$ pro/uces no output. .hat have 0e /one 0rong@ Mo/i'y the progra$
as sho0n belo0 an/ run it
# step_3.rb
# explains step function
# this time its stepping down
10.step 1, -1 do |i|
print "#{i}, "
end
.ell here is the output o' the progra$
10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
.hat goes on in step@ step receives three inputsI consi/er the co/e sho0n belo0
10.step 1, -1
%he 'irst one is the nu$ber that calls step is ta!en as the initial nu$berI in the above case it is 1-.
Ne#t is the en/ing nu$ber in this case it is 1I that is this 'unction counts 'ro$ 1- to 1I 0e $ust
/escen/ in this caseI so the count $ust be in steps o' L1.
45
I Love Ruby 2015 Beta
I can $o/i'y the sa$e progra$ to print even nu$bers in 1- to 1 as sho0n
# step_4.rb
# explains step function
# this time its stepping down
p "Even numbers between 10 and 1:"
10.step 1, -2 do |i|
print "#{i}, "
end
%his progra$ prints the 'ollo0ing output
Even numbers between 10 and 1:
10, 8, 6, 4, 2,
*ets no0 try a progra$ that 0ill print even nu$bers 'ro$ 1 to 1-I this ti$e in ascen/ing or/er
# step_5.rb
# explains step function
# this time its stepping upby two counts each loop
p "Even numbers between 1 and 10:"
2.step 10, 2 do |i|
print "#{i}, "
end
2utput
Even numbers between 1 and 10:
2, 4, 6, 8, 10,
4ee the highlighte/ or /ar!ene/ co/e above. .e have starte/ 'ro$ 5I0e 0ill en/ at 1- an/ 0e Fu$p
each loop by steps o' 5. Insi/e the loop 0e si$ply print the iterating value 0hich is capture/ in
variable i.
$hile
.hile
1"
loop is a loop that /oes so$ething till a con/ition is satis'ie/. Rea/ the co/e belo0
# while .rb
i=1
while i<=10 do
print "#{i}, "
i+=1
end
0hen e#ecute/I it pro/uces the 'ollo0ing output.
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
*ets no0 see ho0 an 0hile loop 0or!s. B 0hile loop nor$ally has 'our i$portant parts
1. InitialiGation
1" Kin/a li!e thisI 0hile 0ith a beauti'ul girl /on7t 'art
46
I Love Ruby 2015 Beta
5. Con/ition chec!
6. *oop bo/y
4. (p/ation
Initiali%ation
4ee the state$ent i=1 I here 0e initialiGe a variable na$e/ i an/ set it to value 1.
ondition chec"
4ee the state$ent while i<=10 I in this state$ent 0e speci'y that 0e are starting a 0hile loopI this
0hile loop on every iteration chec!s the value o' i I i' its less than or e:ual to 1- I the loops bo/y
gets blin/ly e#ecute/.
&oop bod#
Notice the do an/ end in the progra$. %hey encapsulate a piece o' co/e. %he do sy$boliGes the
start o' loop co/e bloc!I the end sy$boliGes the en/ o' loop co/e bloc!. Jet0een it 0e have so$e
state$ents about 0hich 0e 0ill /iscuss soon. 2ne o' the state$ent is to print the value o' iI 0hich
is acco$plishe/ by print "#{i}, "
'pdation
*ets say that 0e 'orgot to inclu/e i+=1 in the loop bo/yI at the en/ o' each iteration the value o' i
0ill al0ays re$ain 1 an/ i 0ill al0ays re$ain less than 1- hence the loop 0ill be e#ecute/ in'inite
nu$ber o' ti$es an/ 0ill print in'inite 17s, . In practical ter$s your progra$ 0ill crash 0ith possible
un/esirable conse:uence. %o avoi/ this 0e $ust inclu/e a up/ation state$ent. Cere 0e have put
i+=1 0hich incre$ents i by value one every ti$e an iteration continuesI this ensures that i<=10 to
beco$e 'alse at so$e stage an/ hence the loops stops e#ecution
1&
.
Cence 0e see that 'or a loop to 0or! in an /esirable $anner 0e nee/ to get these 'our parts into
sy$phony.
until
while loop !eeps going until a con/ition beco$es 'alseI until loop !eeps going until a
1& 4o$e cases a loop $ight be let to run in'inite ti$es +theoretically,. Currently those things are outsi/e the scope o'
this boo!.
44
I Love Ruby 2015 Beta
con/ition beco$es true. Rea/ the co/e belo0I type it in a te#t e/itor an/ e#ecute it.
# until .rb
i=1
until i>10 do
print "#{i}, "
i+=1
end
%his is 0hat you 0ill get as result
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4o ho0 this loop 0or!s@ Bt 'irst 0e /o set i=1 I then 0e use the until co$$an/ an/ say that until i
is greater than 1- !eep /oing so$e thing +loo! at the highlighte/ co/e,. .hat shoul/ be /one is sai/
bet0een the do an/ end !ey 0or/s. 4o till the con/ition 'ailsI the co/e in loops bo/y 0ill be
e#ecute/I so 0e get 1 to 1- printe/ as output.
break
4uppose you 0ant to brea! a0ay 'ro$ loopI you can use the break co$$an/. Bn e#a$ple is given
belo0. In the e#a$ple 0e 0ill brea! i' the iterating variable i beco$es 6. 4o nu$bers ranging only
'ro$ 1 to 5 gets printe/. .hen i beco$es 6 the loop brea!s or ter$inates
#break.rb
1.upto 10 do |i|
break if i == 6
print "#{i}, "
end
.hen e#ecute/I the above progra$ pro/uces the 'ollo0ing output
1, 2, 3, 4, 5,
next
break I brea!s out o' loop an/ ter$inates it. next is so$e 0hat /i''erent 'ro$ break I instea/ o'
brea!ing 'ro$ the loopI its a signal to continue the loop 0ithout e#ecuting state$ents that occurs
a'ter ne#t. Cere is a e#a$ple 'or you to un/erstan/ it
# next.rb
# This loop won't print 6
10.times do |num|
45
I Love Ruby 2015 Beta
next if num == 6
puts num
end
2utput
0
1
2
3
4
5
7
8
9
I' you notice the outputI you see that nu$bers 'ro$ - to & are printe/I but there is no 6. Notice the
highlighte/ line in ne#t.rb I 0e see a state$ent next if num == 6 I here i' num is 6I next is
e#ecute/I in other 0or/s all lines a'ter that in the do end bloc! is s!ippe/. (nli!e brake I the loop
is not ter$inate/I but Fust the lines a'ter ne#t is s!ippe/.
re#o
%here is another type thing calle/ re/o. ne#t s!ips any e#ecution 'urther an/ the iterating variable is
incre$ente/ ) /ecre$ente/ to ne#t possible value
5-
I re/o on other han/s s!ips 'urther e#ecution o'
co/e in the loop bloc!I but the iterating variable is not incre$ente/I instea/ the loop is rerun. %ype
the co/e belo0 an/ e#ecute it in the bro0ser
# redo.rb
5.times do |num|
puts "num = #{num}"
puts "Do you want to redo? (y/n): "
option = gets.chop
redo if option == 'y'
end
Run it an/ hope'ully you can e#plain it by yoursel' NL,
loop
4o 0e have seen $any types o' loops till no0I but I have le't out a basic loop 0hich is 0e call as
loop loop. .hy I have le't it out Jecause its /angerous to use
51
. 2!ay lets see an e#a$ple. %ype the
progra$ belo0 an/ e#ecute it. Note that you nee/ to press CtrlSC to stop it e#ecuting. 4o be
5- Its not right to thin! that ne#t 0ill incre$ent iterating value by 1. Chec!out
httpsA))ra0.github.co$)$in/aslab)ilr#)$aster)ne#tP0ithPstep.rb an/ try it.
51 I' you run this loop a $illion ti$es then it 0ill auto$atically trigger nuclear 0arhea/s in Brea 51. %his 0ill $a!e
Russia counteract thus unleashing a nuclear Br$age//on
46
I Love Ruby 2015 Beta
cautious
# loop.rb
loop do
puts "I Love Ruby"
end
2utput
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
......
%he output 0ill !eep on printing [I *ove Ruby[ until u press Ctrl an/ C !eys to brea!. %he basic is
thisA Bnything put bet0een loop do an/ end 0ill !eep on going.
4o no0 lets say that 0e /on7t 0ant this loop to be continuously running 'or ever. *ets see ho0 to
ta$e it. *ets print a progra$ that prints 'ro$ 1 to 1-. %ype the progra$ belo0 an/ run it .
# break_at_10.rb
i = 1
loop do
puts i
break if i == 10
i = i+1
end
2utput
1
2
3
4
5
6
7
8
9
10
47
I Love Ruby 2015 Beta
4o the progra$ prints 'ro$ 1 to 1- as I 0ishe/. *ets 0al! through it an/ see ho0 it 0or!s. %he 'irst
line i = 1 I stores the value 1 in variable na$e/ i. Ne#t 0e have this loop do line 0here any thing
put bet0een this an/ end 0ill run continuously.
In the ne#t line puts i I 0e print the value o' i an/ hence 1 gets printe/I no0 in break if i ==
10 I it chec!s i' i is 1-I here the con/ition is 'alse hence the loop 0ill continue to the ne#t state$ent
i = i+1 I 0e are a//ing 1 to i in i+1 an/ hence its beco$es 5 so by saying i = i+1 0e $ean i =
1+1 hence i 0ill beco$e 5 an/ it +the progra$, $eets the end state$entI it /oes not $ean en/ the
progra$ but the loop bloc! has got over so return bac! to top +that is to loop do,.
4o in loop /oI no0 i is 5I so the thing goes on an/ on till i is 1- an/ in that caseI in break if i
== 10 I i == 10 beco$es true an/ the loop brea!s.
Exercise: %ry $o/i'ying the break_at_10.rb I 0hen 0e have 'inishe/ printing 1- I the progra$
$ust print [Mo$ I have 'inishe/ printing 1-[
Answer: telling_mom.rb

Exercise: %hese 0estern guys /on7t li!e 16I so 0rite a progra$ to print 'ro$ 1 1- 5-I but o$it 16.
Answer: no_13.rb
Exercise: 1#plain i' no_13_a.rb 0ill 0or!. I' yaI ho0@ I' nayI 0hy not@
55
55 I' you can7t 'in/ outI you 0ill !no0 it on 16L14L5-15 BDI thats the Fu/ge$ent /ay. o/ 0ill /escen/ upon earth an/
give ans0er to this ulti$ate :uestion. I' you 0ant to !no0 0atch >%he Citchhi!er7s ui/e to the ala#y? 0hich
contains a very secret $essage. D2N%;BNIC.
4"
I Love Ruby 2015 Beta
!rrays
Brrays can be consi/ere/ as a rac!. Hou can !eep any thing
56
in a rac!I in a si$ilar 0ay you can
!eep any thing in an array. B rac! contains $any shel's or co$part$ents. I' you can count the$I
you can put nu$bers on each co$part$entI the rac! can be consi/ere/ an array o' space to store
so$e thing. 1ach co$part$ent can be i/enti'ie/ by a nu$ber an/ hence it beco$es easy to i/enti'y
it. Bn array is a rac! thats available to a progra$$er. *ets see an e#a$ple to learn $ore. %ype the
progra$ belo0 an/ e#ecute it
# array.rb
my_array = []
my_array << "Something"
my_array << 123
my_array << Time.now
my_array.each do |element|
puts element
end
%his is ho0 you 0ill get the output
Something
123
Tue Feb 02 18:10:06 +0530 2010
*ets 0al!thru the progra$I ta!e the line my_array = [] I in it 0e /eclare an array calle/
my_arrayI its an e$pty array that has got nothing in it. [] /enotes an e$pty array an/ 0e assign
my_array to it. Caving /one so 0e populate it 0ith so$e values in the 'ollo0ing state$ents
my_array << "Something"
my_array << 123
my_array << Time.now
.e appen/ ele$ents to an array. In the 'irst state$ent 0e appen/ a string constant SomethingI in
the secon/ state$ent 0e appen/ a integer 123 an/ in the thir/ state$ent 0e appen/ the current ti$e.
I' you have guesse/ it rightI 0e have use/ << operator to appen/ the array.
%ill no0 0e have create/ an array calle/ my_array an/ have put so$ething into it. No0 0e have to
see 0hat 0e have put in. %o /o so 0e use <array_name>.each +array na$e /ot each,. %his $etho/
e#tracts each ele$ent o' an array. 4o 'or my_array 0e use
my_array.each
56 %hings are calle/ obFects an/ classes in progra$$ing
4&
I Love Ruby 2015 Beta
2K 0e have to /o so$e thing 0ith each ele$ent o' an array. %o /o so 0e a// a do endI 0ithin
it 0e can /o so$ethingI so our co/e gets trans'or$e/ as
my_array.each do
end
.e have to capture each ele$ent o' an array into a variableI lets use a variable na$e/ element to
/o the FobI so 0e capture each ele$ent using the 'ollo0ing co/e
my_array.each do |element|
end
Notice ho0 0e put our ele$ent variable bet0een | an/ |. .e have capture/ each an/ every
ele$ent o' an arrayI 0hat to /o no0@ .e 0ill print it using a puts state$ent. 4o our array gets
printe/ success'ully. %he 'ollo0ing progra$ too 0or!s the sa$e 0ay as previous progra$I but 0e
use Array.new instea/ o' [] to say that my_array is an array
54
# array_1.rb
my_array = Array.new
my_array << "Something"
my_array << 123
my_array << Time.now
my_array.each do |element|
puts element
end
I 0ill 0rite another progra$ that 0ill use the for construct to iterate over each ele$ent o' an array
as sho0n belo0
# array_2.rb
my_array = Array.new
my_array << "Something"
my_array << 123
my_array << Time.now
for element in my_array
puts element
end
2utput
Something
123
2012-08-10 19:19:47 +0530
%here is a thir/ 0ay o' creating an array. %a!e a close loo! at the progra$ belo0. *oo! at the
/ar!ene/ state$ent. *oo! at it care'ullyI 0e have my_array thats an variable to 0hich 0e assign an
54 %hat is Brray.ne0 returns an e$pty arrayI thats get sore/ in variable $yParray
5-
I Love Ruby 2015 Beta
arrayI its been set to [ "Something", 123, Time.now ]. %hat is in this case 0e /eclare an/
a//e/ array ele$ents to my_array in the sa$e state$ent. Note that 0e put ele$ents o' an array in
s:uare brac!etsI this is another 0ay o' /eclaring array. 4o the progra$ array_3.rb 0or!s e#actly
sa$e as array_1.rb an/ array.rb( but its $ore concise. (nli!e $any languagesI Ruby lets the
progra$$er choose his o0n style o' co/ing.
# array_3.rb
my_array = [ "Something", 123, Time.now ]
puts my_array.join("\n")
Result
Something
123
Wed Feb 03 17:37:36 +0530 2010
%ore on /rray
*ets no0 see so$e array 'unctions. 3or this 0e 0ill be using our 'avorite irb rather than a te#t e/itor
>> array = Array.new
=> []
2K in the above state$ent 0e see that 0e create an Brray na$e/ array using Array.new .
Array.new creates an e$pty array.
%here is another 0ay to create an array. .e can create it by /irectly speci'ying the values that are
containe/ in an array as sho0n
>> array = ["Something", 123, Time.now]
=> ["Something", 123, Tue Feb 02 20:30:41 +0530 2010]
In the above state$entI 0e create an array 0ith three obFects in it. %he value that $ust be in an array
is given bet0een s:uare brac!ets \ an/ ]. 1ach obFect in array is separate/ by a co$$a. Jy
provi/ing no values bet0een \ an/ ] 0e can even create an e$pty array as sho0n
>> array = []
=> []
In the above e#a$ple the e$pty [] /oes the sa$e Fob as Array.new .
*ets create array 0ith para$eters 0ith Array.new as sho0n
>> array = Array.new("Something", 123, Time.now)
ArgumentError: wrong number of arguments (3 for 2)
from (irb):3:in `initialize'
51
I Love Ruby 2015 Beta
from (irb):3:in `new'
from (irb):3
from :0
Bs you see above it 'ails< Don7t use it that 0ay.
2KI lets no0 try so$e thing on the arrayI 'irst to get ho0 $any ele$ents are in the array 0e can use
the length 'unction as sho0n belo0A
>> array.length
=> 3
%he Foin 'unction Foins $any array ele$ents together an/ returns it. 4o 0hen our array ele$ent is
Foine/ this is 0hat 0e get as resultA
>> array.join(', ')
=> "Something, 123, Tue Feb 02 20:30:41 +0530 2010"
Note that 0e pass a string 7I 7 to the FoinI 0hen the array ele$ents are Foine/ as a string theI string 0e
passe/ gets inserte/ into the$ in bet0een.
.e have create/ an array an/ 0e have so$ething in itI 0hat i' 0e 0ant to a// so$ething to it@ %o
/o so 0e use the push $etho/. In the e#a$ple belo0I 0e push a nu$ber 5 into the array an/ as 0e
see the array gets e#pan/e/ an/ 5 is appen/e/ to the array at the last.
>> array.push(5)
=> ["Something", 123, Tue Feb 02 20:30:41 +0530 2010, 5]
%he pop $etho/ /oes the opposite o' pushI it pops out or re$oves the last ele$ent o' array. 4ee the
e#a$ple belo0I 0e pop an ele$ent an/ the last ele$ent 0hich is 5 gets poppe/ out.
>> array.pop
=> 5
B'ter popping it out lets see 0hats in the array
>> array
=> ["Something", 123, Tue Feb 02 20:30:41 +0530 2010]
.e see that the array siGe has re/uce/ by one an/ last ele$ent 5 is $issing.
Its not that you $ust only give a 'i#e/ values in pushI you can give variables an/ Ruby e#pressions
an/ any obFect to the push as argu$ent. Hou can see belo0 that 0e are pushing 5 raise/ to the
po0er o' 1- to the array an/ 1-54 gets a//e/ to the array at the last.
>> array.push 2**10
=> ["Something", 123, Tue Feb 02 20:30:41 +0530 2010, 1024]
Brray ele$ents are in/e#e/. %he 'irst ele$ent o' an array has a in/e# nu$ber - an/ its goes on
+theoretically till in'inity,. I' one 0ants to access ele$ent at in/e# n
55
I all he nee/s to /o is to put
55 n is a nu$berI but 0ait isn7t it a letter@
55
I Love Ruby 2015 Beta
the in/e# nu$ber in bet0een s:uare brac!ets. In the e#a$ple belo0 0e access the thir/ ele$ent in
the array na$e/ array so 0e type it as 'ollo0s
>> array[2]
=> Tue Feb 02 20:30:41 +0530 2010
%he pop $etho/ too accepts a 3i#nu$
56
as an argu$ent 0hich it uses to pop all ele$ents starting
'ro$ that in/e# an/ 'urther.
>> array.pop(2)
=> [Tue Feb 02 20:30:41 +0530 2010, 1024]
>> array
=> ["Something", 123]
Bs you see the thir/ ele$ent gets poppe/ outI so popping at ran/o$ is possible.
.e can push $any ele$ents into an array at once. Consi/er the co/e snippet belo0
>> array.push 5, "Who am I?", 23.465*24
=> ["Something", 123, 5, "Who am I?", 563.16]
.e 'irst push 6 ne0 ele$ents into the array an/ so 0e get a bigger one.
No0 0e pop all ele$ents 0ho7s in/e# nu$ber is 6 an/ above by giving array.pop 3
>> array.pop 3
=> [5, "Who am I?", 563.16]
Bs you can see the array siGe is re/uce/ an/ it no0 only has t0o ele$ents.
>> array
=> ["Something", 123]
%here is another 0ay to appen/ ele$ents in an arrayI its by using the /ouble less than operator <<I
let push so$e ele$ents into the array 0ith it as sho0nA
>> array << "a new element"
=> ["Something", 123, "a new element"]
>> array << 64
=> ["Something", 123, "a new element", 64]
as you see above 0e have appen/e/ a 4tring constant a new element an/ 64 to the array using
<< operator.
Hou can 'in/ $a#i$u$ an/ $ini$u$ values in an array using the max an/ min 'unction as sho0nA
>> nums = [1, 2, 64, -17, 5 ,81]
=> [1, 2, 64, -17, 5, 81]
>> nums.max
=> 81
>> nums.min
=> -17
Bs you see in above e#a$ple 0e create a array calle/ nums having so$e nu$bersI nums.max
56 B nu$ber
56
I Love Ruby 2015 Beta
returns the $a#i$u$ value in that array an/ nums.min returns the $ini$u$ value in that array.
*et operations
3or those 0ho !no0 set theory you $ust !no0 about intersectionsI unions an/ blah blah. I rea/
about set theory 0hen in school an/ no0 have 'orgotten about it. Hou can treat array as set an/ /o
$any operations on it. Cere are a 'e0 e#a$ples 0hich I trie/ out on irb
*ets ta!e a college volleyball tea$I in it are so$e people na$es Bsho!I ChavanI Karthi!I Kesus an/
Ju/ha. I' you ta!e a list o' cric!et tea$ there are Ju/haI Karthi!I Ragu an/ Ra$. *ets no0 co/e it
in ruby. %o have a collection o' people 0ho play in volleyball tea$ 0e create an array as sho0n
>> volleyball=["Ashok", "Chavan", "Karthik", "Jesus", "Budha"]
=> ["Ashok", "Chavan", "Karthik", "Jesus", "Budha"]
In a si$ilar 0ay 0e create another array that contains na$es o' those 0ho play in cric!et tea$ as
sho0n
>> cricket=["Budha", "Karthik", "Ragu", "Ram"]
=> ["Budha", "Karthik", "Ragu", "Ram"]
4o 0e have t0o sets o' people. No0 to 'in/ out 0ho are in volley ball an/ cric!etI all 0e nee/ to /o
is to BND +or ta!e intersection o', both arrays using the & operator as sho0n
>> volleyball & cricket
=> ["Karthik", "Budha"]
Bs you see 'ro$ above co/e snippetI the & +an/, operator sni''s out those ele$ents that are there in
both arrays. In $athe$atics this stu'' is calle/ intersection.
*ets say in another situation 0e 0oul/ li!e to 'in/ out all those 0ho are both in volleyball an/
cric!et tea$. %o /o so 0e use the or operator X . *ets no0 apply it
>> volleyball | cricket
=> ["Ashok", "Chavan", "Karthik", "Jesus", "Budha", "Ragu", "Ram"]
Bs you see 0e get na$es o' those 0ho are in volleyball an/ cric!et tea$. %he X +or, operator is
/i''erent 'ro$ the S +plus, operator. *ets a// volleyball an/ cric!et tea$s
>> volleyball + cricket
=> ["Ashok", "Chavan", "Karthik", "Jesus", "Budha", "Budha", "Karthik", "Ragu",
"Ram"]
Bs you can see 'ro$ above co/e snippet the na$es Karthi! an/ Ju/ha are /uplicate/. %his /oes not
happen 0hen 0e use the X +2R, operator.
*ets no0 'in/ that 0hich players play only 'or the volleyball tea$. 3or this 0e 0ill $inus the
54
I Love Ruby 2015 Beta
players o' cric!et 'ro$ the volleyball tea$ using the 9 +$inus, operator as sho0n
>> volleyball - cricket
=> ["Ashok", "Chavan", "Jesus"]
4o 0e see three players are e#clusively in volleyball tea$. 4o i' you are a $athe$atician you 0ill
'eel so$e 0hat co$'ortable 0ith Ruby.
55
I Love Ruby 2015 Beta
"ashes and Symbols
Cashes are arrays 0ith in/e# /e'ine/ by the progra$ or user an/ not by the Ruby interpreter. *ets
see a progra$ to 'in/ out ho0 hashes 0or!. %ype the 'ollo0ing progra$ +hash.rb, into your te#t
e/itor an/ e#ecute it.
#!/usr/bin/ruby
# hash.rb
mark = Hash.new
mark['English'] = 50
mark['Math'] = 70
mark['Science'] = 75
print "Enter subject name:"
sub = gets.chop
puts "Mark in #{sub} is #{mark[sub]}"
2utput 1
Enter subject name:Math
Mark in Math is 70
2utput 5
Enter subject name:French
Mark in French is
%a!e a loo! at output 1. %he progra$ as!s the user to enter subFect na$e. .hen the user enters
$athI the progra$ gives the $ath $ar!. *ets 0al!thru the co/e. Bt the very beginning 0e have the
line mark = Hash.new I in this line 0e /eclare a variable calle/ $ar! o' the type hash. %a!e a loo!
at the 'ollo0ing lines
mark['English'] = 50
mark['Math'] = 70
mark['Science'] = 75
(nli!e an arrayI hash can have a obFect as in/e#. In this case 0e have use/ si$ple string as in/e#.
.e put the $ar!s obtaine/ in 1nglishI Math an/ 4cience in mark['English'] I mark['Math'] I
mark['Science']. %he ne#t t0o state$ents
print "Enter subject name:"
sub = gets.chop
pro$pts the user to enter $ar!I 0hen he /oes itI it gets store/ into the variable calle/ sub. In the
'inal line puts "Mark in #{sub} is #{mark[sub]}" 0e si$ply access the hash value using sub
as the !ey an/ print it out.
%a!e a loo! at output 5I in this case I have entere/ French an/ the progra$ gives out no result. In
56
I Love Ruby 2015 Beta
the 'ollo0ing progra$ 0e 0ill learn ho0 to /eal 0ith it.
Default values in 0ash
.hen 0e pass the in/e# to an hash an/ i' its value /oes e#istI then the hash 0ill 'aith'ully return
that value. .hat i' the in/e# has no value /e'ine/. In the previous e#a$ple 0e sa0 the progra$
returns nothing. In this progra$ 0e hope to 'i# it. *oo! at the highlighte/ or /ar!ene/ co/e. In it
instea/ o' Fust giving mark = Hash.new as in the previous oneI 0e have given mark = Hash.new
0 I here the Gero is the /e'ault value. No0 lets run the progra$ an/ see 0hat happens.
#!/usr/bin/ruby
# hash_default_value.rb
mark = Hash.new 0 # We specify default value of mark is zero
mark['English'] = 50
mark['Math'] = 70
mark['Science'] = 75
print "Enter subject name:"
sub = gets.chop
puts "Mark in #{sub} is #{mark[sub]}"
2utput
Enter subject name:Chemistry
Mark in Chemistry is 0
*oo! at the outputI 0e haven7t /e'ine/ a value 'or mark['Chemistry']I yet 0hen the subFect na$e
is speci'ie/ as Che$istry 0e get 0 as result. %his is so because 0e have set Gero as the /e'ault
value. 4o by setting /e'ault value 0e 0ill have a value 'or those in/e#es 0e haven7t /e'ine/ yet.
Looping hashes
*ooping in arrays is :uiet easyI 0e nor$ally use each 'unction in array to iterate obFects in array. In
si$ilar 'ashion 0e can loop in hashes. %ype the 'ollo0ing co/e hashPlooping.rb into a te#t e/itor
an/ e#ecute it.
#!/usr/bin/ruby
# hash_looping.rb
mark = Hash.new 0 # We specify default value of mark is zero
mark['English'] = 50
mark['Math'] = 70
mark['Science'] = 75
total = 0
mark.each { |key,value|
total += value
}
puts "Total marks = "+total.to_s
57
I Love Ruby 2015 Beta
2utput
Total marks = 195
In the progra$ above 0e have calculate/ the total o' all $ar!s store/ in the Cash mark. Note ho0
0e use the each loop. Note that 0e get the !ey value pair by using X key,valueX in the loop bo/y.
%he key hol/s the in/e# o' the hash an/ value hol/s the value store/ at that particular in/e#
57
. 1ach
ti$e the loop is e#ecute/I 0e a// value to totalI so at the en/ the variable total has got the total
o' the values store/ in the hash. Bt last 0e print out the total.
Jelo0 is another progra$ 0here 0e store stu/ent $ar!s in an hashI 0e use the each loop to print
the !ey an/ value correspon/ing to the !ey. Cope you have un/erstoo/ enough to e#plain the co/e
belo0 all by your sel'.
#!/usr/bin/ruby
# hash_looping_1.rb
mark = Hash.new 0 # We specify default value of mark is zero
mark['English'] = 50
mark['Math'] = 70
mark['Science'] = 75
puts "Key => Value"
mark.each { |a,b|
puts "#{a} => #{b}"
}
2utput
Key => Value
Science => 75
English => 50
Math => 70
%ore $ay of hash creation
%here is another 0ay to create hashesI lets loo! at it. 4ee belo0I the e#planation o' the progra$ is
sa$e li!e the o' previous progra$ hash_looping_1.rb I e#cept 'or the highlighte/ line in the
progra$ belo0. 1#plain the progra$ to yoursel' as I /on7t have the $oo/ to 0rite no0
#!/usr/bin/ruby
# hash_creation_1.rb
marks = { 'English' => 50, 'Math' => 70, 'Science' => 75 }
puts "Key => Value"
marks.each { |a,b|
puts "#{a} => #{b}"
}
2utput
57 %he ter$ in/e# an/ !ey re'er to the sa$e stu''
5"
I Love Ruby 2015 Beta
Key => Value
Science => 75
English => 50
Math => 70
Using symbols
(sually in a hash 0e use 4y$bols as !eys instea/ o' 4tring. %his is because 4y$bol occupies 'ar
less a$ount o' space co$pare/ to 4tring. %he /i''erence in spee/ an/ space re:uire$ent $ay not be
evi/ent to you no0I but i' you are 0riting a progra$ that creates thousan/s o' hashes it $ay ta!e a
toll. 4o try to use sy$bols instea/ o' 4tring.
4o 0hat is sy$bol@ *ets 'ire up our irb by typing irb --simple-prompt in ter$inal. In it type the
'ollo0ing
>> :x.class
=> Symbol
Notice that 0e have place/ a colon be'ore # thus $a!ing it :x. 4y$bols have a colon at their start.
.hen 0e as! 0hat class is :xI it says its a sy$bol. B sy$bol is a thing or obFect that can be use/ as
a !ey in a hash
5"
. In si$ilar 0ay 0e /eclare another sy$bol calle/ na$e an/ see 0hat class it
belongs.
>> :name
=> :name
>> :name.class
=> Symbol
B variable can hol/ a sy$bol in it. Notice belo0 that 0e have assigne/ a variable 0ith value
:apple 0hich is nothing but a sy$bol. .hen 0e as! 0hat class it is a by using a.class I it says its
a sy$bol.
>> a = :apple
=> :apple
>> a.class
=> Symbol
4y$bols can be converte/ to string using the to_s $etho/ ) 'unction. *oo! at the irb e#a$ple
belo0 0here 0e convert sy$bol to string.
>> :orange.to_s
=> "orange"
%here is no $etho/ in 4tring to convert it to sy$bol. 4uppose 0e 0oul/ li!e to convert a string to
sy$bolI 0e coul/ /o it as sho0n. In the e#a$ple belo0 0e try to convert a string calle/ >hu$an? to
sy$bol. %o /o so 0e e$ploy the 'ollo0ing tric!
5" .ell it can be use/ 'or $any things other than that. 3or no0 re$e$bering this is su''icient
5&
I Love Ruby 2015 Beta
>> human = ":"+"human"
=> ":human"
3irst 0e appen/ colon to a >hu$an? to $a!e it >Ahu$an? 0hich still is a 4tring.
>> human.class
=> String
as 0e can see above the variable human that contains :human is saying that its type is 4tring.
.hat co$es ne#t is a cool thingI loo! at the co/e snippet belo0. .e have a variable calle/
human_sym to it is assigne/ eval(human). .hat that eval@ eval is a 'unction in Ruby that evaluates
any 4tring passe/ to it as a Ruby progra$< %his is a really po0er'ul 'eature. 4ubstituting the value
o' humanI it beco$es eval(:human) an/ eval evaluates it as a sy$bol 0hich gets store/ in
variable human_sym.
>> human_sym = eval(human)
=> :human
>> human_sym.class
=> Symbol
4o 0hen 0e call the class $etho/ 'or human_symI it says its a sy$bol. %han!s to very po0er'ul
'unction eval. Caving e:uippe/ us 0ith this !no0le/geI let us 0rite a progra$ in 0hich hashes
/on7t use 4tring but 4y$bols as !ey. %ype in the progra$ +belo0, hash_symbol.rb into te#t e/itor
an/ e#ecute it.
#!/usr/bin/ruby
# hash_symbol.rb
mark = Hash.new 0 # We specify default value of mark is zero
mark[:English] = 50
mark[:Math] = 70
mark[:Science] = 75
print "Enter subject name:"
sub = gets.chop
symbol = eval ":"+sub
puts "Mark in #{sub} is #{mark[symbol]}"
2utput
Enter subject name:Math
Mark in Math is 70
.hen the progra$ is runI it pro$pts 'or subFect na$eI 0hen its entere/ it sho0s correspon/ing
$ar!. *ets 0al!thru the co/e an/ see ho0 it 0or!s. Notice that 0e use 4y$bols an/ not 4trings as
!eys in $ar! Cash as sho0n
mark[:English] = 50
mark[:Math] = 70
mark[:Science] = 75
Ne#t 0e pro$pt the user to enter $ar!s by using print "Enter subject name:" I the user enters
6-
I Love Ruby 2015 Beta
the subFect na$e . No0 loo! at the ne#t three linesI 'irst 0e get the subFect na$e into variable sub
using the 'ollo0ing state$ent
sub = gets.chop
Caving got the subFect na$e 0e nee/ to convert it into 4y$bol 0hich is /one by using eval
$etho/ as sho0n belo0
symbol = eval ":"+sub
In the state$ent above colon is concatenate/ be'ore the value in subI an/ this is passe/ to eval
$etho/ 0hich returns a 4y$bol. %his 4y$bol is store/ in variable calle/ symbol. 4o i' 0e have
entere/ subFect na$e as MathI the eval 0oul/ have returne/ :Math 0hich gets store/ in sy$bol.
Bll 0e /o ne#t is to access the array value at !ey symbol an/ print it using the 'ollo0ing state$ent
puts "Mark in #{sub} is #{mark[symbol]}"
.ell 0hy /i/n7t Ruby $a!e it so easy to convert a sy$bol to 4tring an/ $a!e it so har/ to convert a
string to 4y$bol. .ell try this in irb
>> "hello".to_sym
=> :hello
No0 re0rite the progra$ above all by your sel' by using ne0ly gaine/ !no0le/ge.
4o you have seen this progra$ hash_creation_1.rb I 0e have no0 !no0le/ge o' sy$bolsI so 0e
can 0rite it as 'ollo0s in hash_creation_1_a.rb
#!/usr/bin/ruby
# hash_creation_1_a.rb
marks = { :English => 50, :Math => 70, :Science => 75 }
puts "Key => Value"
marks.each { |a,b|
puts "#{a} => #{b}"
}
2utput
Key => Value
English => 50
Math => 70
Science => 75
4ee the highlighte/ line marks = { :English => 50, :Math => 70, :Science => 75 } 0e
here use sy$bols instea/ o' strings as a !ey to hash. Cash has so$e a/vantages co$pare/ to string
as they occupy less $e$ory co$pare/ to string +/uring the runti$e o' a progra$,. More than that I
/on7t !no0 0hy 0e use itI but I thin! 0e use it to prove that 0e are ruby gurus<<
61
I Love Ruby 2015 Beta
In ruby 1.& there is better 0ay to 0rite has_creation_1_a.rb I you can see it in
hash_creation_2.rb $entione/ belo0. Kust loo! at the highlighte/ line in progra$ belo0
#!/usr/bin/ruby
# hash_creation_2.rb
marks = { English: 50, Math: 70, Science: 75 }
puts "Key => Value"
marks.each { |a,b|
puts "#{a} => #{b}"
}
%his progra$ 0or!s e#actly as the previous oneI but the highlighte/ line marks = { English:
50, Math: 70, Science: 75 } gets translate/ +assu$e that its been translate/, to the 'ollo0ing
co/e marks = { :English => 50, :Math => 70, :Science => 75 } so its the ne0 short 'or$
0ay to /eclare hash 0ith sy$bols as !eyI ne0ly intro/uce/ in ruby 1.&
65
I Love Ruby 2015 Beta
Ranges
4o$e ti$es 0e nee/ to have a range o' valuesI 'or e#a$ple in a gra/ing syste$. I' a stu/ent scores
'ro$ 6- to 1-- $ar!sI his gra/e is BI 'ro$ 5- to 5& his gra/e is J an/ so on. .hen ever 0e nee/ to
/eal 0ith a Range o' values 0e can use ranges in Ruby. %ype irb --simple-prompt in your
ter$inal an/ type these into it
>>(1..5).each {|a| print "#{a}, " }
2utput
1, 2, 3, 4, 5, => 1..5
2K 0hats that (1..5) in the above state$entI this is calle/ Range. Range is a obFect that has got an
upper value an/ a lo0er value an/ all values in bet0een. Note that li!e arrayI each an/ every value
in a range can be got out using a each $etho/ as sho0n above.
Range /oes not 0or! only on nu$bers it can 0or! on strings too as sho0n belo0
>> ("bad".."bag").each {|a| print "#{a}, " }
2utput
bad, bae, baf, bag, => "bad".."bag"
*ets try out another 'e0 e#a$ples in our irb that 0ill tell to us $ore about Ranges. 4o 'ire up your
irb an/ type the 'ollo0ing
>> a = -4..10
2utput
=> -4..10
In the above co/e snippet 0e create a range that ranges 'ro$ value L4 to 1-. %o chec! 0hat variable
type a belongs lets 'in/ out 0hat class it is
>> a.class
2utput
=> Range
Bs 0e can see a belongs to range class
%o get the $a#i$u$ value in a range use the max $etho/ as sho0n
>> a.max
2utput
66
I Love Ruby 2015 Beta
=> 10
%o get the $ini$u$ in a range use the min $etho/ as sho0n
>> a.min
2utput
=> -4
Its possible to convert range to an array by using to_a $etho/ as sho0n
>> a.to_a
2utput
=> [-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Ranges use# in case 11 $hen
*oo! at the progra$ belo0 + ranges_case_when.rb ,I 0e are buil/ing a stu/ent gra/ing syste$ in
0hich 0hen a $ar! is entere/ the progra$ puts out the gra/e o' the stu/entI stu/y the co/eI type it
an/ e#ecute itI 0e 0ill soon see ho0 it 0or!s.
#!/usr/bin/ruby
# ranges_case_when.rb
puts "Student grading system"
print "Enter student mark: "
mark = gets.chop.to_i
grade = case mark
when 80..100 : 'A'
when 60..79 : 'B'
when 40..59 : 'C'
when 0..39 : 'D'
else "Unable to determine grade. Try again."
end
puts "Your grade is #{grade}"
2utput
Enter student mark: 72
Your grade is B
I' you e#ecute the progra$ above in Ruby 1.&.6I it 0ill thro0 out an error. 3or Ruby 1.&I this is ho0
you nee/ to co/e the above progra$
#!/usr/bin/ruby
# ranges_case_when_19.rb
puts "Student grading system"
print "Enter student mark: "
64
I Love Ruby 2015 Beta
mark = gets.chop.to_i
grade = case mark
when 80..100
'A'
when 60..79
'B'
when 40..59
'C'
when 0..39
'D'
else
"Unable to determine grade. Try again."
end
puts "Your grade is #{grade}"
Bt 'irst the progra$ prints that the so't0are is stu/ent gra/ing syste$ an/ as!s the user to enter the
stu/ent $ar!. .hen the $ar! is entere/ its got using gets state$entI the trailing ne0line character
is choppe/ using the chop $etho/ an/ its converte/ to integer using the to_i $etho/ an/ the $ar!
is store/ in the variable mark. Bll o' it is /one using this mark = gets.chop.to_i state$ent.
2nce 0e have the $ar!I 0e nee/ to co$pare it 0ith a range o' values to /eter$ine the gra/e 0hich
is /one using the 'ollo0ing state$entsA
grade = case mark
when 80..100 : 'A'
when 60..79 : 'B'
when 40..59 : 'C'
when 0..39 : 'D'
else "Unable to determine grade. Try again."
end
Cere 0e see that $ar! is passe/ to the case state$ent. In the when+s, 0e /on7t have a nu$ber or
4tring to co$pare the $ar!I in 'act 0e have ranges. .hen the $ar! lies 'ro$ "- to 1-- +both
inclusive, the gra/e is set to BI 0hen its lies in 6- to 7& its set to JI C 'or 4- to 5& an/ D 'or - to 6&.
I' the user enters so$ething 0rongI gra/e 0ill be set to [(nable to /eter$ine gra/e. %ry again.[.
4o as 0e can see ranges co$e very han/y 0hen they are use/ 0ith case when state$ent. It $a!es
progra$$ing relatively si$ple 0hen co$pare/ to other languages.
)hecking Intervals
Bnother use o' Ranges is to chec! i' any thing is locate/ in a particular interval. Consi/er the
progra$ + ranges_cap_or_small.rb , belo0
65
I Love Ruby 2015 Beta
#!/usr/bin/ruby
# ranges_cap_or_small.rb
print "Enter any letter: "
letter = gets.chop
puts "You have entered a lower case letter" if ('a'..'z') === letter
puts "You have entered a upper case letter" if ('A'..'Z') === letter
2utput
Enter any letter: R
You have entered a upper case letter
Rea/ it care'ully an/ e#ecute it. In the above case I have entere/ capital R an/ hence the progra$
says I have entere/ a upper case letter. I' I ha/ entere/ a lo0er case letterI the progra$ 0oul/ have
sai/ I ha/ entere/ a lo0er case letter. *ets see ho0 the progra$ 0or!s. %he 'ollo0ing linesA
print "Enter any letter: "
letter = gets.chop
pro$pts the user to enter a letterI 0hen the user enters a letter the gets $etho/ gets itI chop chops
o'' the ne0 line character thats a//e/ /ue to the enter !ey 0e press. In the ne#t line loo! at the if
('a'..'z') === letter I here 0e chec! i' the value in variable letter lies 0ith 7a7 an/ 7G7 +both
inclusive, I i' it /oesI 0e print that user has entere/ s$all letter.. Note that 0e /on7t use /ouble e:ual
to == but 0e use triple e:ual to ===
5&
to chec! i' its in range. In a si$ilar 0ay ('A'..'Z') ===
letter returns true i' letter has capital letter in it an/ the progra$ prints the user has entere/ a
capital letter.
Using triple #ots 2
Bnother thing in Range I 0oul/ li!e to a// is using triple /ots instea/ o' using /ouble /ots. Kust try
these out on your irb.
>> (1..5).to_a
=> [1, 2, 3, 4, 5]
>> (1...5).to_a
=> [1, 2, 3, 4]
4ee 'ro$ above co/e snippet 0hen I type (1..5).to_a 0e get an array output as [1, 2, 3, 4,
5] I but 'or (1...5).to_a 0e get output as [1, 2, 3, 4] . .hen 0e use the /ouble /ot the last
thing in Range that 0oul/ appear 0hen 0e use triple /ots it gets cut out.
5& %his triple e:ual to = = = is technically calle/ case e:uality operator. .ho cares@
66
I Love Ruby 2015 Beta
#unctions
.hen you are using sa$e piece o' co/e $any ti$esI you can group the$ into a thing calle/
'unctionI you can call that groupe/ co/e any 0here in your progra$ to /o that particular tas!. *ets
ta!e a real 0orl/ e#a$pleI you goto the hotel an/ a 0aiter co$es up to you. Hou or/er an 'ish 'ry
an/ you get it. Hou are not bothere/ 0hat happens a'ter you or/er.
2nce you have or/ere/ the 'ryI there are lots o' proce/ures that ta!es place. %he 0aiter notes /o0n
your or/erI he goes up to the !itchen an/ places the or/er chit to the che'I the che' tells hi$ that it
0oul/ ta!e so $uch ti$e 'or the /ish to get coo!e/. %he 0aiter thin!s ho0 he coul/ !eep you 'ro$
getting $a/ an/ arrives at your tableI reco$$en/s a starter an/)or an appetiGerI serves you a /rin!
that 0oul/ go 0ell be'ore you eat the /ishI he pools the !itchen to see i' the /ish is rea/y. I' the /ish
is rea/y an/ i' you have 'inishe/ your starter he serves it. I' you haven7t 'inishe/ your starterI he
tells the !itchen to !eep the /ish 0ar$ an/ 0aits 'or you to 'inish. 2nce he gets the /ish to your
tableI he lays the plate containing the /ish an/ cutlery.
Bll you have /one is to or/er a 'ish 'ryI an/ have bliss'ully ignore/ 0hat is being functioned at the
bac!groun/. Hou gave so$e or/er +input, to a 0aiter an/ got a /ish +output,. .hat to /o an/ not to
is preprogra$$e/ or traine/ into the 0aiters $in/I accor/ing to his trainingI the 0aiter 'unctions.
*ets get starte/ 0ith 'unctions in Ruby. .e 0ill be loo!ing at a progra$ in 0hich 0e 0ill be
0riting a 'unction calle/ print_line I 0hich prints a line. %ype the 'ollo0ing progra$ into your
te#t e/itor an/ run it.
# function.rb
def print_line
puts '_'*20
end
print_line
puts "This program prints lines"
print_line
%his is 0hat you 0ill get as output.
____________________
This program prints lines
____________________
67
I Love Ruby 2015 Beta
*ets analyGe the progra$. Consi/er the 'ollo0ing piece o' co/e
def print_line
puts '_'*20
end
%he def tells that you are /e'ining a 'unction. B 'unction $ust have a na$eI the na$e 'ollo0s
i$$e/iately a'ter def !ey 0or/. In this case the na$e o' the 'unction is print_line. In it you can
0rite 0hat ever co/e you 0ant. In this case 0e are creating a line 0ith t0enty un/erscore
characters.
4o 0e have create/ a 'unction an/ have a//e/ co/e into it. Bll 0e nee/ to /o no0 is to call the
'unction 'ro$ our progra$. Its /one by Fust typing the na$e o' the 'unction in the progra$ as
highlighte/ in co/e belo0
# function.rb
def print_line
puts '_'*20
end
print_line
puts "This program prints lines"
print_line
Bs seen in the outputI a line $a/e up o' t0enty un/erscore characters gets printe/ above an/ belo0
the string >%his progra$ prints lines?.
/rgument ,assing
*ets get $ore control o' the 'unctions in this section. Hou /on7t goto a hotel an/ or/er a single /ishI
you can or/er ho0 $uch ever or ho0 less you 0ant. I' you go 0ith 'rien/s you can or/er $ore
servingsI i' you are aloneI you 0ill or/er less. .hy can7t 0e /o the sa$e thing 0ith print_line
'unction@ .hy can7t 0e vary its lengthI /oing so 0ill be a 0on/er'ul thingI 0e can print lines o'
length 0hat ever 0e choose.
%a!e a loo! at co/e highlighte/ belo0I 0e have type/ a thing calle/ length a'ter the 'unction na$eI
its calle/ as argu$ent. *i!e a 'unctionI an argu$ent has an na$eI in this case 0e have na$e/ it
length. .e can pass any values to it to vary the length o' the line printe/. %ype the co/e belo0 an/
e#ecute it
# function_1.rb
6"
I Love Ruby 2015 Beta
def print_line length
puts '_'*length
end
10.step(50,10) do |x|
print_line x
end
40.step(10,-10) do |x|
print_line x
end
Hou 0ill get a /esign pattern as sho0n belo0
__________
____________________
______________________________
________________________________________
__________________________________________________
________________________________________
______________________________
____________________
__________
%a!e a loo! at the 'ollo0ing co/e
10.step(50,10) do |x|
print_line x
end
40.step(10,-10) do |x|
print_line x
end
.e have use/ step 'unctions to incre$ent or /ecre$ent the value 0hich 0e capture it into a variable
calle/ x 0hich is insi/e the loopI 0e pass x to the print_line 'unction by placing it a'ter its call as
highlighte/ above. 4o each ti$e a line o' varying length +/eter$ine/ by x, gets printe/. %he
progra$ is constructe/ in a 0ay so that a pattern is generate/.
Default /rgument
In function_1.rb you have seen ho0 to pass an argu$ent to a 'unction. .hat i' suppose you 'ail
to pass an argu$ent to the 'unction. I' you /o soI an error 0ill be generate/ 0hich a goo/
progra$$er 0ill not /esire
6-
to happen. %o prevent this an/ to $a!e progra$$ing a bit easy its
better to provi/e a /e'ault argu$ent to a 'unction. Note the highlighte/ co/e given belo0 in
'unctionP/e'aultPargu$ent.rb
# function_default_argument.rb
6- >Desire is the cause o' all su''ering? L Ju//ha
6&
I Love Ruby 2015 Beta
def print_line length = 20
puts '_'*length
end
print_line
print_line 40
1#ecute the progra$ an/ observe the result
____________________
________________________________________
Hou can see in the progra$I in 'unction print_line by giving length = 20 0e have in/icate/
that i' no argu$ent is passe/ the 'unction $ust assu$e that value o' length is 5- . I' passe/ this
value 0ill be overri//en 0ith 0hat ever value you pass. Bs you can see in the secon/ highlight
+0here the 'unction is highlighte/,I 0e si$ply call the 'unction Fust by its na$e + print_line,. .e
/on7t bother to pass value 'or length to itI yet 0e see a line o' I length 5- units gets printe/ in the
output. I hope you !no0 0hy.
Returning (alues
.e have till no0 seen 'unction ta!ing in argu$entsI 0e 0ill no0 see that the 'unction can return
bac! values 0hich can be use/ 'or so$e purpose. *ets no0 see the progra$ 'unctionPreturn.rbI
stu/y the co/eI type it an/ e#ecute it.
#! /usr/bin/ruby
# function_return.rb
def addition x, y
sum = x+y
return sum
end
a, b = 3, 5
puts addition a,b
2utput
8
%he output you get out a'ter e#ecuting is "I 0hich proves
61
that 0e have 0ritten a 'la0less progra$.
Note the $etho/ na$e/ addition in the above progra$. It accepts t0o argu$ents x an/ yI insi/e
the $etho/ 0e /eclare a variable calle/ sum 0hich is assigne/ to the a//ition o' x 0ith y. %he ne#t
state$ent is the hero hereI see that 0e have use/ a !ey0or/ returnI this returns the value out o' the
'unction. In the above progra$ 0e return out the sum an/ hence 0hen 0e get the ans0er out.
61 Not a soli/ proo' ho0ever<
7-
I Love Ruby 2015 Beta
Its not that 0e $ust use return state$ent to return a value. %he last state$ent that gets e#ecute/ in a
Ruby 'unction gets returne/ by /e'ault. Consi/er the progra$ function_last_gets_returned.rb
thats sho0n belo0. In it 0e have a $etho/ calle/ square_it 0hich accepts a single argu$ent
calle/ x. It has a single state$ent x**2 0hich happens to be the last state$ent as 0ell.
#!/usr/bin/ruby
# function_last_gets_returned.rb
def square_it x
x**2
end
puts square_it 5
%ype the progra$ an/ e#ecute it.
25
Bs you see 0e have calle/ square_it 5 an/ 0e get 55 as the result. Its possible because in Ruby
the result o' last e#ecute/ state$ent gets returne/ by /e'ault.
Recursive function
*ets see another $ath thing. Hou $ight be 0on/ering 0hy a$ I /oing all $ath@ Certain
progra$$ers /o 0rite boo!s that !eeps out as $uch $ath out as possibleI I a$ not a pro'essional
$athe$aticianI but I a/$ire $ath. Co$puters are base/ on $ath. Bll co$puters use a thing calle/
boolean algebra to /o all tas!s. I 0oul/n7t say that you $ust be a $athe$atician to be a
progra$$erI but !no0ing $ath /oes help.
2K 0hat is a 'actorial@ %a!e a nu$berI lets ta!e 6I no0 0hat 0ill be 6 M 5 M 1 I that 0ill be si#<
4i$ple isn7t it@ 6 is 'actorial o' 6. .ell 0e 0ill ta!e 4 no0I so 4 M 6 M 5 M 1 0ill be 54I in si$ilar
0ay 'actorial o' 5 0ill be 5 M 1 0hich is 5. Caving e:uippe/ 0ith this !no0le/ge 0e 0ill no0
construct a progra$ that 0ill give us 'actorial o' a nu$ber.
4tu/y the progra$ given belo0. Concentrate on the 'unction na$e/ 'actorial
# factorial.rb
def factorial num
fact = 1
1.upto(num) { |a|
fact = fact * a
}
fact
end
number = 17
71
I Love Ruby 2015 Beta
puts "Factorial of #{number} = #{factorial number}"
1#ecute the co/e above an/ this is 0hat you get as output
Factorial of 17 = 355687428096000
In the above e#a$ple +in the 'unction 'actorial, 0e have ta!en all nu$ber 'ro$ one to the particular
nu$berI $ultiplie/ it an/ got 'actorial. No0 stu/y the co/e 'actorialP1.rb sho0n belo0
# factorial_1.rb
def factorial num
return 1 if num == 1
return num * factorial(num-1)
end
number = 17
puts "Factorial of #{number} = #{factorial number}"
1#ecute the co/e above an/ this is 0hat you get as output
Factorial of 17 = 355687428096000
%he output is sa$e as the previous progra$ factorial.rb . %a!e a very close loo! at the 'unction
na$e/ 'actorial in above progra$. *et $e list it out 'or you to see
def factorial num
return 1 if num == 1
return num * factorial(num-1)
end
%his 'unction is con'usingI isn7t it@ .hen I 0as craGy an/ /i/ 0ant to learn about progra$$ing I
stu/ie/ C. %he concept o' recursive 'unctions 0as e#plaine/ using 'actorialI an/ I never /i/
un/erstan/ it 'or a long ti$e. %o avoi/ the pain let $e e#plain in /etail.
%a!e the nu$ber 1. 3actorial o' it is 1. 4o i' 1 is encountere/ 1 is returne/ as sho0n in highlighte/
co/e belo0
def factorial num
return 1 if num == 1
return num * factorial(num-1)
end
No0 ta!e the nu$ber 5. 3actorial o' it 5 M 1 I 0hich is 5 $ultiplie/ 'actorial o' 1. In other 0or/s
0e can 0rite it as 5 $ultiplie/ by 'actorial o' 5L1 + 5 x factorial 51 ,. 4o i' nu$ber t0o is
encountere/ in the 'unction 'actorialI it s!ips the 'irst i' state$ent an/ the secon/ state$ent thats
highlighte/ belo0 gets e#ecute/
def factorial num
return 1 if num == 1
return num * factorial(num-1)
end
75
I Love Ruby 2015 Beta
In this an interesting thing happens. Cere 'actorial +5L1, is calle/I that is 'actorial 'unction calls
itsel'. 4o 0hen 'actorial o' 5L1 I i.e 'actorial o' 1 is calle/I it returns 1I this 1 is $ultiplie/ by 5 an/
is returne/ bac!I so in this case 5 is returne/ ulti$ately.
No0 ta!e the nu$ber 6. Its 'actorial is 6 M 5 M 1. %his can be 0ritten as 6 $ultiplie/ by 'actorial 5.
3actorial 5 gets translate/ as 5 $ultiplie/ by 'actorial 1. Cence the result is got out 'inally. 3or any
nu$ber larger than 1I the 'actorial 'unction calls itsel' repeate/ly. %he process o' 'unction calling
itsel' is calle/ recursion.
(ariable number of arguments
*ets say that you /o not !no0 ho0 $any argu$ents are passe/ to a 'unctionI lets say that you are
0riting a 'unction to a// N nu$bersI the value o' N is not !no0nI so ho0 coul/ you get variable
nu$ber o' argu$ents. .ell type the progra$ 'unctionPvariablePargu$ents.rb thats given belo0 an/
e#ecute it.
# function_variable_arguments.rb
def some_function a, *others
puts a
puts "Others are:"
for x in others
puts x
end
end
some_function 1,2,3,4,5
2utput
1
Others are:
2
3
4
5
4o the output o' the progra$ is sho0n above. Bs you see 0e pass 1,2,3,4,5 as argu$entsI then a
is Fust a single variable an/ hence it ta!es the value 1I the other variables are be absorbe/ by the
variable *others +note the star be'ore variable na$e, 0hich is a special !in/ o' argu$entI it ta!es
all the rest o' the argu$ents that are not absorbe/ by previous argu$ent variables an/ stores it in
variable na$e others +as an array,. No0 in the 'ollo0ing piece o' co/e
for x in others
puts x
end
76
I Love Ruby 2015 Beta
.ell thats it. No0 try 0riting a 'unction to 'in/ $a#i$u$ o' nLnu$bers an/ 0rite another 'unction
to 'in/ $ini$u$ o' nLnu$bers an/ 0rite a progra$ to 'in/ $a#i$u$ an/ $ini$u$ o' a bunch o'
nu$bers.
0ashes to functions
Bnother 0ay to snea! in $ultiple argu$ents into a 'unction is to pass the$ as hashes. *oo! at the
progra$ belo0I 0e have a 'unction na$e/ some_function 0hich gets in t0o argu$entsI the 'irst
one na$e/ first_arg an/ secon/ one na$e/ others_as_hashI 0e call this 'unction in the
'ollo0ing line some_function "Yoda", {jedi: 100, sword: 100, seeing_future: 100} I
e#ecute it an/ note the output
# hashes_to_functions.rb
def some_function first_arg, others_as_hash
puts "Your first argument is: #{first_arg}"
puts "Other arguments are:"
p others_as_hash
end
some_function "Yoda", {jedi: 100, sword: 100, seeing_future: 100}
2utput
Your first argument is: Yoda
Other arguments are:
{:jedi=>100, :sword=>100, :seeing_future=>100}
Bs 0e have e#pecte/ the progra$ prints the 'irst argu$ent an/ the hash passe/ to others_as_hashI
0ell this one is no surpriseI but ta!e a loo! at the progra$ hashes_to_function_1.rb belo0I
e#ecute itI its output 0ill be the sa$e as progra$ above
# hashes_to_functions_1.rb
def some_function first_arg, others_as_hash
puts "Your first argument is: #{first_arg}"
puts "Other arguments are:"
p others_as_hash
end
some_function "Yoda", jedi: 100, sword: 100, seeing_future: 100
Jut Fust note the highlighte/ partI 0e have calle/ some_function as sho0n
some_function "Yoda", jedi: 100, sword: 100, seeing_future: 100
74
I Love Ruby 2015 Beta
In the 'unction 0e pass the secon/ argu$ent as a hash but its given as sho0n above +highlighte/,I
note that 0e have continently avoi/e/ the curly braces an/ it still 0or!s. %hats the point.
75
I Love Ruby 2015 Beta
$ariable Scope
.e have seen about 'unctions in the last section an/ 0e have seen about variable be'ore. I thin! the
ti$e is right to type about variable scope. In this chapter 0e e#a$ine ho0 long or ho0 'ar a variable
is valuable 0hen its /eclare/ in a particular section o' a progra$. *ets start 0ith a e#a$ple. 3ire up
your te#t e/itorI type the co/e belo0 +variable_scope.rb, an/ e#ecute it.
#!/usr/bin/ruby
# variable_scope.rb
x = 5
def print_x
puts x
end
print_x
2utput
variable_scope.rb:7:in `print_x': undefined local variable or method `x' for
main:Object (NameError)
from variable_scope.rb:10
.ell you get an error. 4ee that you have /eclare/ a variable by typing x = 5. In the 'unction
print_x you tell the ruby progra$ to print out the variable xI but it thro0s a error. *oo! at the
outputI it says undefined local variable or method `x' for main:Object (NameError)
from variable_scope.rb:10 I 0ell 0e have /e'ine/ x an/ have assigne/ it to value 5 at the
beginningI then ho0 co$e Ruby thro0s the error@ .ellI 0e have /e'ine/ x outsi/e the 'unction
print_x hence x has no scope insi/e itI so 0e get an error.
B goo/ progra$$er is the one 0ho e#ploits the a/vantages provi/e/ by a progra$ing language an/
0ho is s$art enough to play by rules an/ li$itations it i$poses. It $ight loo! as a real han/icap to a
ne0bie that 0e are not able to access a variable 0e have assigne/ outsi/e a 'unctionI but as your
progra$ an/ you beco$e $ature progra$$erI you 0ill realiGe its blessing in /isguise.
%o learn $ore type the progra$ belo0 +variablePscopeP1.rb, in your te#t e/itor an/ e#ecute it.
#!/usr/bin/ruby
# variable_scope_1.rb
x = 5
76
I Love Ruby 2015 Beta
def print_x
x=3
puts x
end
print_x
puts x
2utput
3
5
%a!e a care'ul loo! at the output. 3irst 0e /eclare a variable x = 5 I then in 'unction print_x 0e
/eclare a variable x = 3. Note that the variable /eclare/ in 'unction print_x is not the sa$e one as
thats been /eclare/ outsi/e the 'unction. Ne#t 0e call upon the 'unction print_x 0hich prints the
output as 6 0hich is e#pecte/ since insi/e print_x 0e have 0ritten puts x a'ter x = 3. Ne#t
state$ent is the hero hereI +outsi/e the 'unction, 0e have 0ritten puts x a'ter print_xI i' you
e#pecte/ to print 6 then you are 0rong. Cere x is the x that 0e have /eclare/ it outsi/e the 'unctionI
here it 0ill get printe/ as 5. %his $eans that a variable /eclare/ insi/e the 'unction has no scope
outsi/e it.
%o !no0 $ore an/ to convince oursel' that variable /eclare/ insi/e a 'unction has no scope outsi/e
itI 0e 0ill try out another progra$. %ype in the progra$ variablePscopeP5.rb into your te#t e/itor
an/ e#ecute it.
#!/usr/bin/ruby
# variable_scope_2.rb
def print_variable
y = 3
puts y
end
print_variable
puts y
2utput
3
variable_scope_2.rb:10: undefined local variable or method `y' for main:Object
(NameError)
Cere is ho0 the progra$ 0or!s or here is ho0 the progra$ /oesn7t 0or!s as it thro0s an error. %a!e
a loo! at the 'unction print_variableI in it 0e have /eclare/ a variable calle/ y using state$ent y
= 3 an/ tol/ the ruby interpreter to print its value using state$ent puts y. 4o in the progra$ 0hen
0e call print_variable the y is /eclare/ an/ its value 6 is printe/ 0ithout a glitch. Ne#t 0e say
puts y outsi/e the 'unction print_variableI since y is only /eclare/ 0ithin the 'unction outsi/e
77
I Love Ruby 2015 Beta
itI the variable y /oesn7t e#ist an/ in technical ter$s it has no scopeI so the Ruby interpreter thro0s
an error. 4o 0e get the error $essage as 'ollo0sA
variable_scope_2.rb:10: undefined local variable or method `y' for main:Object
(NameError)
---- x X x ----
*oo!s li!e MatG +the creator o' Ruby, hasn7t seen the $ovie 7Jac! to the 'uture7. *ets see another
progra$ that proves that ti$e travel isn7t built into RubyI type the progra$ belo0
+variable_scope_3.rb, into your te#t e/itor an/ e#ecute it.
#!/usr/bin/ruby
# variable_scope_3.rb
puts a # you can't access a variable that will be created in future
a = 10
2utput
variable_scope_3.rb:4: undefined local variable or method `a' for main:Object
(NameError)
I' you have anticipate/ rightI the progra$ thro0s out an error. .e have given puts a be'ore a has
been /eclare/. Ruby interpreter /oes not consi/er 0hats /eclare/ in 'utureI so 0hen puts a is
encountere/ itI at that point o' ti$e a is un/eclare/I an/ hence an error is thro0n. In other 0or/s
scope o' an variable starts only a'ter it has been /eclare/.
Global (ariables
I' you are a one 0ho /on7t li!e the i/ea that variables /eclare/ outsi/e a 'unction cant be accesse/
'ro$ itI then Ruby provi/es a 0ay to /o it. %here are special variables calle/ global variables that
can be accesse/ 'ro$ any 0here. lobal variables are prece/e/ by a /ollar +R, sign. %o !no0 about
global variables lets see an e#a$ple. %ype the progra$ belo0 +globalPvariables.rb, an/ e#ecute it.
#!/usr/bin/ruby
# global_variables.rb
$x = 5
def print_x
$x = 3
puts $x
end
print_x
puts $x
2utput
3
7"
I Love Ruby 2015 Beta
3
Caving run it success'ully lets see ho0 it 0or!s. 3irst 0e /eclare a global variable $x an/ assign it
to the value 5 in the state$ent $x = 5. Ne#t 0e /e'ine a 'unction print_x in 0hich 0e change the
value o' $x to 3 using state$ent $x = 3I then 0e print the value o' $x using puts $x. 4o obviously
0e call print_x 0e get the output as 3. Ne#t outsi/e the 'unction a'ter calling print_xI 0e print
the value o' $x using puts $x. I' you thin! it 0oul/ print 5I then you are $ista!en. 4ince $x can be
accesse/ 'ro$ any 0hereI an/ 0e have calle/ print_xI in print_x 0e have change/ the value o'
$x to 3I no $atter 0hatI even outsi/e the scope o' the 'unction the value o' $x 0ill be change/.
*ets see another e#a$ple to un/erstan/ global variables better. *oo! at the e#a$ple belo0
+global_variables_1.rb,I type it in your te#t e/itor an/ e#ecute it
#!/usr/bin/ruby
# global_variables_1.rb
$x = 5
def print_x
puts $x
end
print_x
$x = 7
print_x
$x = 3
print_x
here is ho0 the output o' the progra$ loo!s li!e
5
7
3
*ets see ho0 the progra$ 0or!s. Bt 'irst 0e /eclare a global variable $x an/ assign it to value 'ive
using $x = 5I then 0e /e'ine a 'unction calle/ print_x in 0hich 0e Fust print out the value o' $x
using puts $x state$ent. .hile 0e call the 'irst print_x state$entI the value o' $x is 5 an/ hence
5 gets printe/. Ne#t 0e change the value o' $x to 7 in state$ent $x = 7 an/ 0hen 0e call print_xI
the value o' $x 0hich is no0 7 gets printe/. 3inally 0e set $x to 6 using $x = 3I 0hen 0e call
print_x 'or the 'inal ti$e 6 gets printe/ out.
%his progra$ proves that global variables can be $anipulate/ 'ro$ any 0here an/ these
$anipulate/ values can be accesse/ 'ro$ any 0here.
Ne#t arises a :uestion 0eather global variable an/ local variable can have the sa$e na$e. %he
ans0er is yes. Its because global variables start 0ith a R sign an/ local variables start 0ith a letter or
7&
I Love Ruby 2015 Beta
un/erscore characterI so ruby can clearly tell the /i''erence bet0een the$. *ets see a progra$ that
proves thisI rea/I learn type an/ e#ecute the progra$ given belo0 +globalPvariablesP5.rb,. 2nce
you are /one 0ith itI 0e 0ill see ho0 it 0or!s.
#!/usr/bin/ruby
# global_variables_2.rb
$x = 5
x = 5
def print_x
$x = 3
x = 3
puts "In print_x"
puts "$x = "+$x.to_s
puts "x = "+x.to_s
end
print_x
puts "Outside print_x"
puts "$x = "+$x.to_s
puts "x = "+x.to_s
2utput
In print_x
$x = 3
x = 3
Outside print_x
$x = 3
x = 5
In the above progra$ 0e /eclare t0o variables one global $x an/ assign it to value 5 an/ another
local x an/ assign it to value 6 in the 'ollo0ing lines
$x = 5
x = 5
Ne#t 0e create a 'unction print_x in 0hich 0e change the value o' $x to 6I since $x is globalI the
change is a''ecte/ every 0here in the progra$I ne#t 0e have state$ent x = 3I this variable x is
local one an/ is /i''erent 'ro$ x = 5 0hich 0e /e'ine/ outsi/e the 'unction. Ne#t 0e 0ill tell the
progra$ to print the values o' $x an/ local x using he 'ollo0ing state$ents
puts "$x = "+$x.to_s
puts "x = "+x.to_s
2KI 0hen the progra$ encounters the print_x callI 0e get the 'ollo0ing output
In print_x
$x = 3
x = 3
Note that $x is no0 6 an/ local x is also 6. No0 outsi/e the 'unction 0e print the values o' $x an/ x
"-
I Love Ruby 2015 Beta
using the 'ollo0ing state$ents +last 6 lines o' the progra$,
puts "Outside print_x"
puts "$x = "+$x.to_s
puts "x = "+x.to_s
.hen these state$ents are e#ecute/I 0e get the 'ollo0ing output
Outside print_x
$x = 3
x = 5
Cere as $x has been assigne/ to 6I 6 is printe/ as its value. x over here re$ains 5 as here x re'ers to
not the x thats /e'ine/ insi/e print_xI but the one thats /e'ine/ out o' it.
"1
I Love Ruby 2015 Beta
Classes % Ob&ects
)reating a *3uare
Classes can be thought as variables an/ 'unctions bun/le/ un/er one na$e. %o illustrate about
classes lets loo! at a hu$ble obFect calle/ s:uare. 4:uare is a very si$ple geo$etric shape that has
'our si/es o' e:ual lengthI ho0 to represent this s:uare in a Ruby progra$@ .e no0 0rite an e$pty
class calle/ s:uare
#square.rb
class Square
end
.e have 0ritten an e$pty class. %he 0or/ class tells that 0e are 0riting a /e'inition o' a class.
.hat 'ollo0s the class !ey0or/ is the na$e o' the classI in this case is Square. 2ne $ust note that
na$e o' a class in Ruby $ust start 0ith a capital letter
65
.
B s:uare has got 'our si/esI all have the sa$e length. .e no0 put an variable into s:uare calle/
side_length.
#square.rb
class Square
attr_accessor :side_length
end
Hou $ight as! 0hat attr_accessor is@ It stan/s 'or attribute accessorsI 0hich enables you to get
an/ set the side_length easily. *ets use this s:uare class an/ see ho0 it 0or!s. Mo/i'y the co/e
above as sho0n belo0A
#square.rb
class Square
attr_accessor :side_length
end
s1 = Square.new # creates a new square
s1.side_length = 5 # sets its side length
puts "Side length of s1 = #{s1.side_length}" # prints the side length
.hen you e#ecute the above co/eI this is 0hat you 0ill get as result
Side length of s1 = 5
65 %he na$e o' a class is al0ays a constant. Re$eber@ %hat constants in Ruby al0ays start 0ith a capital letter.
"5
I Love Ruby 2015 Beta
*ets 0al! thru the ne0ly a//e/ co/eI ta!e the line
s1 = Square.new
In the above state$ent 0e create a ne0 s:uare an/ store its para$eters into a variable calle/ s1. B
ne0 class instance can be create/ by using <class name>.new. Caving create/ a ne0 s:uareI 0e
can no0 access its side_length using the /ot operator 7.7. 4o 0e 'irst set the side_length to 'ive
units using the 'ollo0ing state$ent
s1.side_length = 5
No0 having assigne/ the si/e lengthI 0e can use it 'or any purpose. No0 0e Fust si$ply print the
side_length o' s:uare using the 'ollo0ing state$entN
puts "Side length of s1 = #{s1.side_length}"
'unctions in )lass
.e have a class calle/ s:uare 0hich has a attribute na$e/ side_length. .ith the side_length
0e can 'in/ the s:uares areaI its peri$eter an/ its /iagonal length. In this e#a$ple I a$ going to
'in/ the area an/ peri$eter. .hy I o$it /iagonal length@ .ell its $y 0ishI i' you are not happy
about it $o/i'y this boo! an/ re/istribute it. 4o lets a// t0o 'unctions to 'in/ our area an/
peri$eter. Mo/i'y the co/e as sho0n + I a$ saving the $o/i'ie/ co/e in a 'ile calle/ s:uareP1.rb ,
#square_1.rb
class Square
attr_accessor :side_length
def area
@side_length * @side_length
end
def perimeter
4 * @side_length
end
end
In the highlighte/ co/e above you see that I have a//e/ t0o 'unctionsI one na$e/ area an/ another
na$e/ perimeter 0hich co$putes an/ returns the area an/ peri$eter o' the s:uare respectively .
%hese 'unctions are very si$ilar to any other 'unction 0e have create/ be'oreI only no0 its place/
insi/e a class. *ets 0rite so$e a//itional co/e to e#ploit the ne0 'eatures 0e have a//e/I Fust a//
the co/e highlighte/ belo0 an/ run it
#square_1.rb
class Square
attr_accessor :side_length
"6
I Love Ruby 2015 Beta
def area
@side_length * @side_length
end
def perimeter
4 * @side_length
end
end
a = Square.new
a.side_length = 5
puts "Area: #{a.area}"
puts "Perimeter: #{a.perimeter}"
Run the e#a$ple an/ here is 0hat you 0ill get as output
Area: 25
Perimeter: 20
%he e#planation is pretty straight 'or0ar/ in the 'ollo0ing lines
a = Square.new
a.side_length = 5
.e have /eclare/ a ne0 s:uare an/ have assigne/ side_length as 5 units. In lines belo0 0e
si$ply print out the values o' a.area an/ a.perimeter
puts "Area: #{a.area}"
puts "Perimeter: #{a.perimeter}"
4ee ho0 0e have e$be//e/ the values o' a7s area an/ peri$eter + highlighte/ in the co/e above ,.
2ne thing that $ust be ne0 'o you i' you are rea/ing this boo! is sho0n belo0 +highlighte/,A
def area
@side_length * @side_length
end
.e !no0 that s:uare has an attribute calle/ side_length 0hich is /e'ine/ by the state$ent
attr_accessor :side_length , 0ell as sho0n in highlighte/ co/e above 0e have use/
@side_length instea/ o' side_length I thats because insi/e the classI classLvariables are pre'i#e/
0ith O +at, sy$bol. %his helps us to i/enti'y bet0een class variables an/ local variables or
'unctions that share the sa$e na$e.
Initiali4ers or )onstructors
In previous e#a$ples 0here 0e /ealt 0ith s:uaresI have you ever 0on/ere/ 0hat happens 0hen
you say li!e s = Square.new @ .ell in this case a ne0 Square gets create/ an/ its put insi/e the
variable s. I' one as!s a :uestion 0eather 0e can /o so$ething 0hen a Square initialiGes@ %he
ans0er is yes< In 'act you can /o al$ost anything you 0ant. Bll you have to /o is to put co/e insi/e
"4
I Love Ruby 2015 Beta
a 'unction calle/ initializeI this 'unction gets calle/ 0hen ever there is a <class name>.new
call
*oo! at the e#a$ple square2.rb I ta!e a goo/ loo! at the highlighte/ or /ar!ene/ linesI there 0e
/e'ine a 'unction calle/ initialize I this 'unction ta!es in one argu$ent na$e/ side_length
0ho7s /e'ault value is Gero. I' side_length is speci'ie/I it sets the @side_length attribute in the
s:uare class to that value else @side_length ta!es the /e'ault value o' Gero. %ype s:uare5.rb into
te#t e/itor an/ e#ecute it
#square_2.rb
class Square
attr_accessor :side_length
def initialize side_length = 0
@side_length = side_length
end
def area
@side_length * @side_length
end
def perimeter
4 * @side_length
end
end
s1 = Square.new 4
s2 = Square.new
s2.side_length = 5
puts "Area of s1 is #{s1.area} squnits"
puts "Peimeter of s2 is #{s2.perimeter} units"
2utput
Area of s1 is 16 squnits
Perimeter of s2 is 20 units
In the progra$ concentrate on the 'ollo0ing lines
s1 = Square.new 4
s2 = Square.new
s2.side_length = 5
In the 'irst line s1 = Square.new 4 0e create a 4:uare na$e/ s1 0ho7s @side_length is 4 units.
In the secon/ line s2 = Square.new 0e create a Square na$e/ s2I initially its si/e length
+@side_length, 0oul/ be set to Gero unitsI only in the thir/ line s2.side_length = 5 its
@side_length is set to 5 units.
In rest o' the co/e
"5
I Love Ruby 2015 Beta
puts "Area of s1 is #{s1.area} squnits"
puts "Peimeter of s2 is #{s2.perimeter} units"
.e print the area o' 4:uare s1 an/ peri$eter o' 4:uare s2 0hich pro/uces the desired output.
,rivate %etho#s
Jy /e'ault the $etho/s or 'unctions in a class is public +can be accesse/ outsi/e the classes scope,I
i' you /on7t 0ant it to be accesse/ by progra$s outsi/e a class you can $a!e it private. *ets create a
class calle/ Cu$anI an/ put a private $etho/ in itI lets try to access it 'ro$ outsi/e the class an/
see 0hat happens to it. %ype in the progra$ an/ e#ecute it
# private_method.rb
class Human
attr_accessor :name, :age
def tell_about_you
puts "Hello I am #{@name}. I am #{@age} years old"
end
private
def tell_a_secret
puts "I am not a human, I am a computer program. He! Hee!!"
end

end
h = Human.new
h.name = "Zigor"
h.age = 314567
h.tell_about_you
h.tell_a_secret # this wont work
%he progra$ above 0hen e#ecute/ pro/uces the 'ollo0ing result
Hello I am Zigor. I am 314567 years old
human.rb:20: private method `tell_a_secret' called for #<Human:0xb7538678
@name="Zigor", @age=314567> (NoMethodError)
*oo! at the highlighte/ line in the progra$I the 'unction tell_a_secret is place/ un/er the
!ey0or/ privateI this $a!es it not accessible 'ro$ outsi/e the class. Note the line 0hen 0e call
the $etho/ tell_a_secret I it thro0s an errorI in 'act it says a no $etho/ error +NoMethodError)
0hich $eans that the calle/ $etho/ /oes not e#ist in the class. It /oes not $ean the co$puter is
telling a lieI instea/ its sa'ely !eeping a secret.
In progra$ing you only let certain parts o' your progra$ visible to othersI this helps !eep the
"6
I Love Ruby 2015 Beta
inter'ace si$ple an/ give your users only the resource they really nee/ to 0rite co/eI this sort o'
hi/ing un0ante/ things unco$plicates progra$$ing.
2ne $ight :uestionI i' there is no 0ay to access a private $etho/I then 0hy 0e nee/ to have it@
.ell there are 0ays to access it in/irectly as you see in e#a$ple belo0. %ype it an/ e#ecute it
# private_method_1.rb
class Human
attr_accessor :name, :age
def tell_about_you
puts "Hello I am #{@name}. I am #{@age} years old"
end
def confess
tell_a_secret
end
private
def tell_a_secret
puts "I am not a human, I am a computer program. He! Hee!!"
end

end
h = Human.new
h.name = "Zigor"
h.age = 314567
h.tell_about_you
h.confess
%his is ho0 the result 0ill be
Hello I am Zigor. I am 314567 years old
I am not a human, I am a computer program. He! Hee!!
%a!e a goo/ loo! at the $etho/ confess I in it 0e call the private $etho/ tell_a_secret I so
0hen 0e call confess even outsi/e the class + h.confess ,I the con'ess $etho/ 0hich is public
calls the private $etho/I since confess is insi/e the class HumanI it can access any private $etho/
in Human 0ithout an hin/ranceI so the progra$ e#ecutes per'ectly.
)lass variables an# metho#s
%ill no0 0e have learne/ to create a classI 0e !no0 that a class can have certain attributesI 'or
e#a$ple a hu$an $ight have attributes li!e na$eI age an/ blah blah... .e !no0 that class can
"7
I Love Ruby 2015 Beta
have so$e 'unctions in it 0hich can be calle/ by variable 0hich is a instance o' the class. 2K 'ine
0ell an/ goo/. .hat i' 0e 0ant to call a 'unction or a class 0ithout /eclaring a variable 0hich is
the instance o' that class@ %hose 'unctions that can be calle/ 0ithout /eclaring a instance variable
that belongs to the class type is calle/ class $etho/s. %hose variables that can be accesse/ 0ithout
using instance variables are calle/ class variables.
*ets loo! at a progra$ that 0ill /e$onstrate class variables an/ $etho/s. In the 'ollo0ing progra$
class_var_methods.rb I I 0ill create a class na$e/ Robot. It 0ill have a class variable na$e/
@@robot_count 0hich 0ill !eep trac! o' ho0 $any Robots 0ere create/. 4ince its a class variable
0e in/icate it to the co$puter by using t0o O +at, sy$bols be'ore itI hence in progra$ 0e /enote it
li!e @@robot_count .
.e create a 'unction na$e/ robots_created that 0ill return nu$ber o' Robots that 0ere create/.
Notice +in progra$ belo0, that the 'unction robots_created is written as
self.robots_created I the sel' !ey0or/ tells the co$puter that this 'unction can be calle/ 0ithout
an instance obFect being /eclare/.
%ype the progra$ sho0n belo0 class_var_method.rb in te#t e/itor an/ e#ecute it
# class_var_methods.rb
class Robot
def initialize
if defined?(@@robot_count)
@@robot_count += 1
else
@@robot_count = 1
end
end
def self.robots_created
@@robot_count
end
end
r1 = Robot.new
r2 = Robot.new
puts "Created #{Robot.robots_created} robots"
r3, r4, r5 = Robot.new, Robot.new, Robot.new
puts "Created #{Robot.robots_created} robots"
.hen e#ecute/ the progra$ above 0ill give the 'ollo0ing result
Created 2 robots
Created 5 robots
*ets see the initialize $etho/ an/ lets analyGe ho0 0e !eep trac! o' nu$ber o' Robot7s create/.
""
I Love Ruby 2015 Beta
.hen the 'irst Robot is create/ in the state$ent
r1 = Robot.new
%he progra$ control goes to the initialize $etho/I since its the 'irst time the variable
@@robot_count is not /e'ine/I so the con/ition in the 'ollo0ing if state$ent
if defined?(@@robot_count)
@@robot_count += 1
else
@@robot_count = 1
end
'ails an/ the co/e goes to the else part an/ there @@robot_count = 1 /e'ines the variable
@@robot_count an/ initialiGes to value 1.
In the secon/ state$ent 0here 0e create robot na$e/ r2 using the 'ollo0ing co$$an/
r2 = Robot.new
%he control once again goes to the initialize $etho/I there the if state$ent passes as
@@robot_count has alrea/y been /e'ine/ 0hen 0e create/ r1I no0 the @@robot_count gets
incre$ente/ by 1I no0 beco$es 5.
Ne#t is the puts state$ent 0e call Robot.robots_created 0hich Fust returns the @@robot_count I
hence 5 gets printe/. Ne#t in the 'ollo0ing state$entA
r3, r4, r5 = Robot.new, Robot.new, Robot.new
0e create three ne0 robots r3I r4 an/ r5. No0 the @@robot_count 0ill get incre$ente/ to 5. In the
ne#t puts state$entI the result gets printe/. %he $oral o' the story is thisI class $etho/s have a
self. +sel' /ot, be'ore the$I class variables have t0o O +OO, be'ore the$.
3ineI hope everything 0ent right 'or the rea/er. .hy no0 0e use attr_reader 'or robot_count
variable so that our progra$ gets si$pli'ie/ as sho0n belo0. %ype in an/ e#ecute it.
# attr_for_classvar.rb
# this program dosent work
class Robot
attr_reader :robot_count
def initialize
if defined?(@@robot_count)
@@robot_count += 1
else
@@robot_count = 1
end
end
"&
I Love Ruby 2015 Beta
end
r1 = Robot.new
r2 = Robot.new
puts "Created #{Robot.robot_count} robots"
r3, r4, r5 = Robot.new, Robot.new, Robot.new
puts "Created #{Robot.robot_count} robots"
.hat 0as the result you got@ Can attr_reader be use/ 'or class variables@
Inheritance
.e evolve/ 'ro$ $on!eys. Chi$ps loo! li!e usI 0e both share $any characteristicsI 0e have $any
attributes si$ilar to chi$psI they are so si$ilar usI that chi$ps 0ere sent into space be'ore us to see
the i$pact o' Gero gravity on a $on!eys bo/y. 2nly 0hen the scientist 'elt sa'e /i/ they sen/
hu$ans
66
. .hen $an evolve/ 'ro$ $on!eys he inherite/ $any things 'ro$ the$I 'or e#a$ple 0e
loo! li!e $on!eysI /on7t believe it@ Kust go an/ stan/ in 'ront o' a $irror<
2KI in progra$ing 0orl/ 0e have a thing calle/ inheritance in 0hich one class can have property
o' another class 0ith so$e little +or so$eti$es e#tre$e, changes. *et $e tell you a $ath truthI 7a
s:uare is a rectangle in 0hich all si/es are e:ual7 I is it not so@ Bll s:uares are rectanglesI but not all
rectangles are s:uares. .e 0ill be using this stu'' to 0rite our ne#t progra$ inheritance.rb .
.rite the progra$ in te#t e/itor an/ e#ecute it.
# inheritance.rb
class Rectangle
attr_accessor :length, :width
def initialize length, width
@length = length
@width = width
end
def area
@length * @width
end
def perimeter
2 * (@length + @width)
end
end
class Square < Rectangle
def initialize length
@width = @length = length
66 (ri agarin o' the 4oviet (nion 0as the 'irst $an to go into space
&-
I Love Ruby 2015 Beta
end
def side_length
@width
end
def side_length=(length)
@width = @length = length
end
end
s = Square.new 5
puts "Perimeter of the square s is #{s.perimeter}"
r = Rectangle.new 3, 5
puts "Area of rectangle r is #{r.area}"
.hen e#ecute/I the progra$ above pro/uces the 'ollo0ing result
Perimeter of the square s is 20
Area of rectangle r is 15
Rea/ the progra$ care'ullyI 0e have /e'ine/ a class calle/ Rectangle that has t0o attributes
na$ely @length an/ @width. .hen 0e initialiGe it in state$ent r = Rectangle.new 3, 5I 0e
pass these t0o para$eters. .hen area is calle/ the pro/uct o' these t0o attributes is returne/I 0hen
its peri$eter is calle/ using so$e genius 'or$ula the peri$eter is calculate/ an/ returne/. 3ine I 0e
then /e'ine a class calle/ Square that inherits the properties o' Rectangle. %o say that the class
Square inherits Rectangle 0e use a W +less than, sign as sho0n
class Square < Rectangle
%a!e a loo! at the initialiGe $etho/ in Square classI it ta!es only one argu$ent length 0hich it uses
to set the values o' attributes @length an/ @width . 4ince Square inherits Rectangle class it gets
all attributes an/ $etho/s o' Rectangle by /e'ault. Caving set the @width an/ @height o' the
Square 0e can no0 call the 4:uare7s area an/ perimeter 'unctions Fust li!e 0e /o that 0ith
Rectangle.
+verri#ing %etho#s
.e have seen that class can inherit attributes an/ $etho/s 'ro$ its base class. *ets say that 0e have
a class B that is a parent class o' J + i.e. J inherits B ,I no0 the scenario is there is a $etho/ /e'ine/
in J 0hich has the sa$e na$e that o' $etho/ in B. .hen 0e create a instance variable o' type J
an/ call that $etho/ na$e it 0ill chec! i' the $etho/ is present in class J i' yes that $etho/ 0ill be
e#ecute/I i' that $etho/ is not 'oun/ in JI then the Ruby interpreter chec!s it in class BI i' its 'oun/
its e#ecute/I else NoMetho/1rror
64
is raise/.
64 No $etho/ error $eans that the $etho/ na$e calle/ cannot be 'oun/I hence an error is raise/ by the Ruby
&1
I Love Ruby 2015 Beta
%o $a!e this clear lets see an e#a$pleI type an/ e#ecute override_methods.rb
#!/usr/bin/ruby
# override_methods.rb
class A
def belongs_to
puts "I belong to in class A"
end
def another_method
puts "Just another method in class A"
end
end
class B < A
def another_method
puts "Just another method in class B"
end
end
a = A.new
b = B.new
a.belongs_to
a.another_method
b.belongs_to # This is not overriden so method in class A is called
b.another_method # This is overridden so method in class B is called
Result
I belong to in class A
Just another method in class A
I belong to in class A
Just another method in class B
%a!e a loo! at the result. .hen a.belongs_to is calle/ the progra$ prints out I belong to in
class A as it 0as /e'ine/ in class B. .hen a.another_method is calle/ 0e see the progra$ prints
out Just another method in class A as it 0as /e'ine/ in class B . .hen b. belongs_to is
calle/ the progra$ once again prints out I belong to in class A as there is no belongs_to
$etho/ in class J an/ hence the parent $etho/ is calle/. 4ee the /ra$a 0hen b.another_method
is calle/ I the progra$ prints out Just another method in class B an/ not Just another
method in class A as J has another_method in its scopeI so there is no nee/ to loo! 'or that
$etho/ in class B.
.e 0ill ta!e the concept o' overri/ing a step 'urtherI !no0 that everything in Ruby is a obFect.
Ruby is purely an obFect oriente/ progra$ing language. 4hoot up your irb an/ type the 'ollo0ing
>> "Something".class
interpreter
&5
I Love Ruby 2015 Beta
=> String
>> 1.class
=> Fixnum
>> 3.14278.class
=> Float
.hen ever in Ruby you put an .class a'ter obFect it returns the class to 0hich the obFect belongs.
4o 0e see that nu$bers li!e 1I 5 I6........ belong to the Fixnum class. *ets overri/e its !ey $etho/
the S . ;lus sign is use/ in Ruby to a// t0o nu$bers. %ry these e#a$ples in your irb
>> 1+2
=> 3
>> 478+90
=> 568
4o 0e see that 0hen there is a 3i#nu$I 'ollo0e/ by a plus sign an/ another 3i#nu$ Ruby
interpreter a//s these t0o 3i#nu$7s 0hich is returne/ as result. *ets no0 $ess up 0ith the plus
sign. %a!e a loo! at overri/eP$etho/sP1.rb I type it in your te#t e/itor an/ e#ecute it.
# override_methods_1.rb
class Fixnum
def + a
416
end
end
puts 3+5
puts 7+12
Result
416
416
*oo! at the resultI aren7t you surprise/@ .hen three an/ 'ive are a//e/ the result you get is 416 an/
0hen 7 an/ 15 are a//e/I once again the result is 416. %a!e a loo! at the blac!ene/ or highlighte/
co/e in the 3i#nu$ class. %o $a!e your rea/ing convenientI here is the co/eA
def + a
416
end
In it 0e have re/e'ine/ the $etho/ S in 3i#nu$ class. In itI 0e have sai/ no $atter 0hat ever be the
value o' a + that is nu$ber that is at the right si/e o' S sign in a//itionI , 0e $ust return a value o'
416I so the Ruby interpreter si$ply obeys it.
3i#nu$ is a core class o' RubyI in $any progra$$ing languages +'or e#a$ple Kava, I one /oes not
have the lu#ury to $o/i'y the core class as Ruby allo0s it to /o. Many authors an/ progra$$ing
gurus 0ho have 0ritten boo!s about Ruby have calle/ this Ruby 'eature as a /angerous oneI its
/angerous in/ee/I i' you /o $o/i'y a i$portant class in Ruby an/ i' our co/e is burie/ /eep in a
&6
I Love Ruby 2015 Beta
proFectI so$e ti$es it can result in severe logical errors in our progra$ an/ so$eti$es $ay cost lot
o' resource 0aste as one nee/s to bury hi$sel' to /ebug the co/e. 4o be'ore overri/ing $etho/s in a
i$portant or core class please thin!I an/ then /o $a!e a leap.
The super function
4ee the progra$ belo0
#!/usr/bin/ruby
# class_super.rb
class Rectangle
def set_dimension length, breadth
@length, @breadth = length, breadth
end
def area
@length * @breadth
end
end
class Square < Rectangle
def set_dimension side_length
super side_length, side_length
end
end
square = Square.new
square.set_dim 7
puts "Area: #{square.area}"
2utput
Area: 49
In the progra$ you see a Rectangle classI in it you see a 'unction calle/ set_dimension as
highlighte/ belo0. %his 'unction receives t0o argu$ents length an/ breadthI 0hich is assigne/ to
class variables @length an/ @breadth in this line @length, @breadth = length, breadth
class Rectangle
def set_dimension length, breadth
@length, @breadth = length, breadth
end
def area
@length * @breadth
&4
I Love Ruby 2015 Beta
end
end
No0 see the class Square. Square inherits Rectangle as all s:uares are rectangles +0hos lengths
an/ brea/ths are e:ual,I but not the other 0ay aroun/. No0 note the highlighte/ part in the piece o'
co/e belo0
class Square < Rectangle
def set_dimension side_length
super side_length, side_length
end
end
Hou can see that the Square class has its o0n set_dimension $etho/I no0 loo! 0hat it hasI it has
a ne0 stu''I loo! at the line that sho0s super side_length, side_length I + the bol/ line in co/e
aboveI , here 0e call a ne0 $etho/ calle/ super. super is a special $etho/I i' you call it in
set_dimensionI it 0ill see i' the parent class has the $etho/ 0ith the sa$e na$eI i' yes it calls the
$etho/. Cence super here 0ill call the set_dimension in Rectangle an/ 0ill pass side_length
to length thus setting it to @length I an/ side_length to breadthI thus setting it to @breadth
respectively.
B rectangle 0ho7s @length an/ @breadth are e:ual is a s:uare< Isn7t it notI thin!<<<
&xten#ing class
Ruby lets the progra$$er to e#ten/ pree#isting classes in +al$ost, any 0ay you 0antI it /oesn7t
$atter i' the classes are 0ritten by you or bun/le/ into the Ruby language itsel'. In the 'ollo0ing
e#a$ple 0e 0ill be e#ten/ing 3i#nu$ class to suit our nee/s. %ype the progra$ into te#t e/itor an/
e#ecute it
# extending_class.rb
class Fixnum
def minute
to_s.to_i * 60
end
def hour
to_s.to_i.minute * 60
end
&5
I Love Ruby 2015 Beta
def day
to_s.to_i.hour * 24
end
def week
to_s.to_i.day * 7
end
end
puts Time.now + 2.week
Result
Wed Apr 07 16:55:44 +0530 2010
%he progra$ puts 0hat 0oul/ be %i$e e#actly 5 0ee!s 'ro$ current secon/I note that 0e /o it by
this state$ent A
puts Time.now + 2.week
%he Time.now gets the current %i$e instanceI to 0hich 0e a// 2.week. In realityI the native
3i#nu$ class has no $etho/ na$e/ week in it but see in the progra$ 0e have /e'ine/ a 3i#nu$
class 0hich has $etho/ na$e weekI 0hen its calle/ it returns nu$ber o' secon/s in a 0ee! 0hich
can be a//e/ or subtracte/ to ti$e obFect to get past an/ 'uture ti$e.
In a si$ilar 'ashion you can e#ten/ any class in RubyI you can overri/e al$ost any $etho/. 2'
course so$e progra$$ers +0ho li!e to be calle/ as pro'essionals, see this as a threat as so$e
acci/ental changes $ight intro/uce a bug in your co/eI but i' you truly love Ruby this shoul/n7t
$atter a lot.
Reflection
Re'lection is a process by 0hich a co$puter progra$ can analyGe itsel' an/ $o/i'y it on the go. In
the 'ollo0ing pages 0e 0ill Fust be scratching its sur'ace. I' ti$e 0illing I 0ill a// $eta
progra$$ing section in this boo! 0here I can /iscuss $ore. Right no0 I /on7t really !no0 0hat
$eta progra$$ing is.
2KI so lets Fu$p in. .e 0ill try out these e#a$ples in irb I so in your ter$inal type irb 9si$pleL
pro$pt . In the irb pro$pt belo0 I have /eclare/ a 4tring variable a an/ set it to a value Some
string
>> a = "Some string"
=> "Some string"
No0 lets see that 0hat $etho/s are available 0ith variable that 0e can use. %o /o so type
a.methods in irb
&6
I Love Ruby 2015 Beta
>> a.methods
=> ["upcase!", "zip", "find_index", "between?", "to_f", "minmax", "lines",
"sub", "methods", "send", "replace", "empty?", "group_by", "squeeze", "crypt",
"gsub!", "taint", "to_enum", "instance_variable_defined?", "match", "downcase!",
"take", "find_all", "min_by", "bytes", "entries", "gsub", "singleton_methods",
"instance_eval", "to_str", "first", "chop!", "enum_for", "intern", "nil?",
"succ", "capitalize!", "take_while", "select", "max_by", "chars", "tr!",
"protected_methods", "instance_exec", "sort", "chop", "tainted?", "dump",
"include?", "untaint", "each_slice", "instance_of?", "chomp!", "swapcase!",
"drop", "equal?", "reject", "hex", "minmax_by", "sum", "hash",
"private_methods", "all?", "tr_s!", "sort_by", "chomp", "upcase", "start_with?",
"unpack", "succ!", "enum_slice", "kind_of?", "strip!", "freeze", "drop_while",
"eql?", "next", "collect", "oct", "id", "slice", "casecmp", "grep", "strip",
"any?", "delete!", "public_methods", "end_with?", "downcase", "%", "is_a?",
"scan", "lstrip!", "each_cons", "cycle", "map", "member?", "tap", "type", "*",
"split", "insert", "each_with_index", "+", "count", "lstrip", "one?",
"squeeze!", "instance_variables", "__id__", "frozen?", "capitalize", "next!",
"each_line", "rstrip!", "to_a", "enum_cons", "ljust", "respond_to?", "upto",
"display", "each", "inject", "tr", "method", "slice!", "class", "reverse",
"length", "enum_with_index", "rpartition", "rstrip", "<=>", "none?",
"instance_variable_get", "find", "==", "swapcase", "__send__", "===", "min",
"each_byte", "extend", "to_s", "rjust", "index", ">=", "size", "reduce", "tr_s",
"<=", "clone", "reverse_each", "to_sym", "bytesize", "=~",
"instance_variable_set", "<", "detect", "max", "each_char", ">", "to_i",
"center", "inspect", "[]", "reverse!", "rindex", "partition", "delete", "[]=",
"concat", "sub!", "dup", "object_id", "<<"]
Bs you can see a.methods returns the $etho/s ) 'unctions that can be use/ upon a 4tring. Ne#t 0e
0ill try out an/ 'in/ 0hat class or type a belongs. 2' course 0e !no0 that it belongs to 4tring typeI
but 'or the sa!e o' learning to progra$ type a.class into irb
>> a.class
=> String
an/ it 'aith'ully returns that a is o' the type 4tring.
3ine 0e have seen so$e thing about re'lection till no0. %o un/erstan/ it better lets /e'ine our o0n
class an/ see ho0 re'lection 0or!s upon it. %ype the progra$ +belo0, re'lection.rb into a te#t e/itor
an/ e#ecute it.
# reflection.rb
class Someclass
attr_accessor :a, :b
private
# A dummy private method
def private_method
end
protected
# A dummy protected method
def protected_method
end
&7
I Love Ruby 2015 Beta
public
# A dummy public method
def public_method
end
end
something = Someclass.new
something.a = 'a'
something.b = 123
puts "something belongs to #{something.class}"
puts
puts "something has the following instance variables:"
puts something.instance_variables.join(', ')
puts
puts "something has the following methods:"
puts something.methods.join(', ')
puts
puts "something has the following public methods:"
puts something.public_methods.join(', ')
puts
puts "something has the following private methods:"
puts something.private_methods.join(', ')
puts
puts "something has the following protected methods:"
puts something.protected_methods.join(', ')
2utput
something belongs to Someclass
something has the following instance variables:
@a, @b
something has the following methods:
inspect, protected_method, tap, clone, public_methods, __send__, object_id,
instance_variable_defined?, equal?, freeze, extend, send, methods,
public_method, hash, dup, to_enum, instance_variables, eql?, a, instance_eval,
id, singleton_methods, a=, taint, enum_for, frozen?, instance_variable_get,
instance_of?, display, to_a, method, b, type, instance_exec, protected_methods,
==, b=, ===, instance_variable_set, kind_of?, respond_to?, to_s, class, __id__,
tainted?, =~, private_methods, untaint, nil?, is_a?
something has the following public methods:
inspect, tap, clone, public_methods, __send__, object_id,
instance_variable_defined?, equal?, freeze, extend, send, methods,
public_method, hash, dup, to_enum, instance_variables, eql?, a, instance_eval,
id, singleton_methods, a=, taint, enum_for, frozen?, instance_variable_get,
instance_of?, display, to_a, method, b, type, instance_exec, protected_methods,
==, b=, ===, instance_variable_set, kind_of?, respond_to?, to_s, class, __id__,
tainted?, =~, private_methods, untaint, nil?, is_a?
something has the following private methods:
exit!, chomp!, initialize, fail, print, binding, split, Array, format, chop,
iterator?, catch, readlines, trap, remove_instance_variable, getc,
singleton_method_added, caller, putc, autoload?, proc, chomp, block_given?,
throw, p, sub!, loop, syscall, trace_var, exec, Integer, callcc, puts,
&"
I Love Ruby 2015 Beta
initialize_copy, load, singleton_method_removed, exit, srand, lambda,
global_variables, gsub!, untrace_var, open, `, system, Float, method_missing,
singleton_method_undefined, sub, abort, gets, require, rand, test, warn, eval,
local_variables, chop!, scan, raise, printf, set_trace_func, private_method,
fork, String, select, sleep, gsub, sprintf, autoload, readline, at_exit,
__method__
something has the following protected methods:
protected_method
Hou $ust have got pretty big output as sho0n above. *ets no0 0al!thru the co/e. 3irst 0e /e'ine a
class calle/ Someclass in 0hich 0e have t0o attributes ) class variables a an/ b. .e have a private
$etho/ calle/ private_method I protecte/ $etho/ calle/ protected_method an/ public $etho/
calle/ public_method.
B'ter /e'ining the class 0e create a variable calle/ something o' the type Someclass an/ give
values to its attributes in the 'ollo0ing lines
something = Someclass.new
something.a = 'a'
something.b = 123
Ne#t 0e as! the ruby interpreter to print the class o' variable so$ething using the 'ollo0ing
state$ent puts "something belongs to #{something.class}" 0hich it 'aith'ully /oes an/ so
0e get the 'ollo0ing outputA
something belongs to Someclass
Ne#t 0e 0oul/ li!e to !no0 that i' something 0hich is an obFect o' type Someclass has any
instance variables. %o !no0 it 0e co$$an/ as
puts "something has the following instance variables:"
puts something.instance_variables.join(', ')
'or 0hich 0e get the 'ollo0ing output
something has the following instance variables:
@a, @b
Ne#t 0e 0oul/ li!e to !no0 0hat $etho/s are there 0ith so$ething that can be use/. %o !no0 that
0e can use the $etho/s 'unctionI so 0e 0rite the 'ollo0ing co/eA
puts "something has the following methods:"
puts something.methods.join(', ')
In the above co/e something.methods returns an array o' $etho/sI this $ust be converte/ to a
string 0hich is /one by the join $etho/. %he ele$ents o' the array are Foine/ by the 4tring passe/
to the join $etho/. Notice that there are $ore $etho/s than 0e have /e'ine/I thats because even
Someclass is o' type Object
65
0hich itsel' has $any $etho/s o' its o0n. In Ruby everything is a
65 2bFect is one o' the $ost 'un/a$ental class in Ruby upon 0hich al$ost all other classes are built upon. Bll classes
&&
I Love Ruby 2015 Beta
2bFect<
%he $etho/s an/ public_methods o' any 2bFect returns the sa$e result. 4o 0e 0ill s!ip the
/iscussion on these
puts "something has the following public methods:"
puts something.public_methods.join(', ')
state$ents
Ne#t 0e 0ant to !no0 0hat are the privateI public an/ protecte/ $etho/s areI that are in
SomeclassI since something belongs to SomeclassI private $etho/s can be got using
private_methods 'unctionI thus by giving the 'ollo0ing state$ents
puts "something has the following private methods:"
puts something.private_methods.join(', ')
.e are able to get private $etho/s in so$e class.
4i$ilarly protecte/ $etho/s are got by using protected_methods 'unction 0hich I 0on7t /iscuss
/ue to $y laGiness.
&ncapsulation
Hou $ust have ta!en a capsule tablet in so$e point o' ti$e in your li'e. In it the $e/icine is pac!e/
insi/e a gelatin capsule. .hen you ta!e it 0ith 0ater it sli/es to your sto$ach 0here 0ater brea!s
out the gelatin layer releasing the $e/icine in it 0hich cures your bo/y o' ail$ents. I' you try to
s0allo0 the $e/icine 0ithout the capsule it 0ill be a bitter e#perience.
In si$ilar 'ashion $o/ern progra$ing language allo0s you to hi/e un0ante/ /etails an/ let your
'ello0 progra$$er loo! only at the nee/e/ /etails. %his techni:ue is calle/ encapsulation 0hich
0hen properly i$ple$ente/ 0ill result in pro/ucing clean co/e an/ one thats easy to use.
Bnother great e#a$ple o' encapsulation is your car. (n/er the hoo/ your car has thousan/s o' parts
that turn this 0ay an/ that 0ayI yet all you nee/ to /o is to turn on the !ey an/ operate the steering
0heel an/ pe/als
66
to get a /riving e#perience. %here is no nee/ 'or you to bother 0hat goes on
behin/ the hoo/.
*ets see a s$all e#a$ple that 0ill e#plain to us ho0 encapsulation 0or!s. %ype out the progra$
encapsulation.rb in your te#t e/itor an/ e#ecute it.
i$plicitly inherit 2bFect
66 ears are slo0ly being eli$inate/ in to/ays cars
1--
I Love Ruby 2015 Beta
# encapsulation.rb
class Human
attr_reader :firstname, :lastname
def name=(name)
@firstname, @lastname = name.split
end
end
guy = Human.new
guy.name = "Ramanuja Iyengaar"
puts "First name: #{guy.firstname}"
puts "Last name: #{guy.lastname}"
2utput
First name: Ramanuja
Last name: Iyengaar
4o 0e get the 'irst na$e o' the person as Ra$anuFa an/ last na$e as Iyengar. %hese t0o lines are
printe/ out /ue to the 'ollo0ing state$ents
puts "First name: #{guy.firstname}"
puts "Last name: #{guy.lastname}"
4ee the t0o lines be'ore these state$ents. 3irst 0e /eclare a ne0 variable na$e/ guy o' the type
hu$an by 0riting guy = Human.new I ne#t 0e set guy.name = "Ramanuja Iyengaar" I but in the
'irst puts state$ent 0e call guy.firstname an/ in the ne#t one 0e call guy.lastname an/ 0e get
the ans0ers< %his is because insi/e the progra$ in the $etho/ calle/ name +see highlighte/ co/e,
0e split it an/ assign the 0or/ be'ore space as @firstname an/ 0or/ a'ter space as @lastname
using the 'ollo0ing piece o' co/eA
@firstname, @lastname = name.split
4o 0hen 0e call guy.firstname an/ guy.lastname it gets printe/ 'aith'ully. Note that outsi/e the
class 0e never set the @first_name an/ @last_nameI it 0as totally encapsulate/ 'ro$ us.
2ne $ight be 0on/ering 0hat the state$ent attrPrea/er A'irstna$eI Alastna$e /oes@ It /eclares t0o
variables @first_name an/ @last_name. %he attrPrea/er signi'ies that the t0o variables can only
be rea/ by progra$ outsi/e the classI in other 0or/s i' 0e try to set guy.first_name =
Ramanuja the Ruby interpreter 0ill thro0 out an error.
,olymorphism
;oly $eans $anyI an/ $orphis $eans 'or$s. I thin! its either in ree! or *atinI 0ho cares@ In
progra$$ing language you can use one thing to /o $any thingsI lets see a 'e0 e#a$ples. *ets ta!e
1-1
I Love Ruby 2015 Beta
the hu$ble plus sign. .hen 0e ta!e >Cello ? an/ >.orl/<? an/ put a plus sign in bet0eenI the
output is >Cello .orl/<?. In technical tal! 0e call this concatenation +Foining together,. .hy there
are so $any /i''icult 0or/s to learn 0hen you 0ant to be progra$$er@ .ho !no0s@ ;ossibly
spea!ing so$e nonLun/erstan/able blah blah $ight $a!e you loo! intelligentI possibly 'etch higher
pay. 4o here is the irb e#a$pleA
>> "Hello " + "World!"
=> "Hello World!"
No0 lets use this plus sign on nu$bers. .e no0 stic! it bet0een 164 an/ &7. .hen 0e /o that 0e
get the ans0er as 561 an/ not as 164&7. .hy@ Its because the plus sign is traine/ to /o /i''erent
things 0hen its stuc! in bet0een /i''erent things.
>> 134 + 97
=> 231
.hen you stic! it in bet0een 4tring7s
67
it Foins the$I 0hen you stic! it in bet0een nu$bers it a//s
the$. 4o the operator plus ta!es $any 'or$s or /oes /i''erent operations /epen/ing upon the
situation.
In a si$ilar 0ay 0hat 0ill happen i' 0e $ultiply a string by a nu$ber. .ell 0hen 0e /o it as sho0n
belo0
>> "Hello"*5
=> "HelloHelloHelloHelloHello"
0e see that string is printe/ the nu$ber o' ti$es. 4o $ultiplying >Cello? by 6 prints >Cello? si#
ti$es. In the ne#t e#a$ple 0e assign value si# to a variable na$e/ hello an/ $ultiply it by 'ive
>> Hello = 6
=> 6
>> Hello*5
=> 30
4ince hello is a variable that carries a nu$berI $ultiply itI results is a nu$ber. 4o you see even an
$ultiplication operator ta!es $any 'or$s or /i''erent 'unctions /epen/ing on the situation. Its li!e
this a police$an 0hen at ho$e is !in/ 0ith his 'a$ilyI 0hen he is $a/e to ta!e a thu/ he behaves in
a /i''erent 0ay.
In a si$ilar 0ay the length operator ) 'unctionI 0hen you are 'in/ing out the length o' a stringI it
tells the nu$ber o' characters in it.
>> "some text".length
=> 9
67 B piece o' te#t
1-5
I Love Ruby 2015 Beta
.hen you are 'in/ing the length o' an array it tells the nu$ber o' ele$ents the array has.
>> [5, 7, "some text", Time.now].length
=> 4
4o 0e see that in RubyI a thing can /o /i''erent thingsI Fust li!e an real 0orl/ obFect /oes
6"
.
)lass )onstants
Kust li!e any other progra$$ing languageI one can have a constant values in a class in Ruby. *ets
Fu$p into actionI ta!e a loo! at the 'ollo0ing progra$ class_constant.rb I it source co/e is li!e
this
#!/usr/bin/ruby
# class_constant.rb
class Something
Const = 25
end
puts Something::Const
2utput
25
Note the pieces o' co/e I have /ar!ene/. In the class 4o$ethingI you see the state$ent Const =
25. I' you 0ere rea/ing this boo! 0ellI you $ight realiGe that constant in Ruby starts 0ith a capital
letter. In the class 4o$ethingI 0e have /eclare/ a constant na$es Const an/ assigne/ it to 25.
Note the state$ent puts Something::Const . puts is 'or printing al$ost anything thro0n at it.
Cere 0e thro0 Something::Const an/ it 'aith'ully prints out the constant value. 4o class constants
can be access by <class_name>::<constant_name> I this is ho0 you access constants o' a class.
*et7s see ho0 class instance can access a class constant. %ype the progra$ class_constant_1.rb
#!/usr/bin/ruby
# class_constant.rb
class Something
Const = 25
end
puts Something::Const
s = Something.new
puts s.Const
2utput
6" *i!e nuclear energy can be use/ to e#plo/e an ato$ic bo$b or po0er an entire cityI /epen/ing on 0hat hu$ans
/eci/e to /o 0ith it
1-6
I Love Ruby 2015 Beta
25
class_constant_1.rb:10: undefined method `Const' for #<Something:0xb745eb58>
(NoMethodError)
4o in this progra$ +above, 0e have /eclare/ a variable s 0hose class is Something. In line puts
s.Const I 0e try to access the constant value insi/e so$ething via its instance variable s an/ 0e get
a No Metho/ 1rrorI or the Ruby interpreter thin!s Const is a $etho/ since 0e use s /ot Const. %o
'i# this issueI you can 0rite a $etho/ calle/ Const an/ call it as sho0n in class_constant_2.rb
#!/usr/bin/ruby
# class_constant_2.rb
class Something
Const = 25
def Const
Const
end
end
puts Something::Const
s = Something.new
puts s.Const
2utput
25
25
4o /e'ining a $etho/
6&
an/ returning Const 'ro$ it solves the proble$.
4o$e $ight thin! one can access class constant value using the instance variable by using /ouble
colon +AA, instea/ o' the /ot operator as sho0n in class_constant_3.rb I 0ell it 0ont 0or! as you
can see 'ro$ its output
#!/usr/bin/ruby
# class_constant_3.rb
class Something
Const = 25
def Const
Const
end
end
puts Something::Const
s = Something.new
puts s::Const
2utput
6& It7s not necessary that the $etho/ shoul/ have the sa$e na$e as the constant.
1-4
I Love Ruby 2015 Beta
25
class_constant_3.rb:14: #<Something:0xb74029fc> is not a class/module
(TypeError)
1-5
I Love Ruby 2015 Beta
Struct and OpenStruct
2!ayI in the last chapter 0e have seen about classesI no0 lets see so$ething si$ple calle/ struct
4-
.
I' its si$pleI 0hy not 0rite about I be'ore@ %he ans0er is si$pleII never !ne0 struct be'ore an/ I
/on7t 0ant one to use struct in serious progra$$ing. .hy@ Jecause I 'eel they are not
h$$$$...........
.e 0ill :uic!ly see so$e e#a$ples an/ I 0ill close the chapter. %ype the 'ollo0ing progra$ an/
e#ecute it
# struc_start.rb
person = Struct.new :name, :age
p = person.new
p.name = "Karthik"
p.age = 30
puts "Hello, I am #{p.name}, age #{p.age}"
)utput
CelloI I a$ Karthi!I age 6-
.ellI no0 lets see ho0 it 0or!s. 3irst you are creating a ne0 type o' struct uing this state$ents.
Struct.new :name, :age
No0 you 0ant to na$e itI so that you can use itI lets na$e it as person
person = Struct.new :name, :age
2nce na$e/I this variable person 0ill act li!e a class or so$e thinI you can /eclare a ne0 instance
o' it li!e this
p = person.new
In the above state$ent p is the instance o' person.
No0 0e can assign :name an/ :age o' p using the 'ollo0ing state$ents
p.name = "Karthik"
p.age = 30
%hen you can print the /ata li!e sho0n belo0
puts "Hello, I am #{p.name}, age #{p.age}"
4- Its !in/ o' struct you see in CSSI but its $uch si$pler
1-6
I Love Ruby 2015 Beta
%hats it. .ithout $uch clas thing an/ blah blahI you have create/ a /ata structure an/ use/ it< Don7t
you thin! its great<<
Its not that person in person = Struct.new :name, :age shoul/ be variable +i.e start 0ith lo0er
case,I but it coul/ also be a constant li!e ;erson. %hats 0hat e#actly is going on in the ne#t piece o'
co/e here
# struct_constant.rb
Person = Struct.new :name, :age
p = Person.new
p.name = "Karthik"
p.age = 30
puts "Hello, I am #{p.name}, age #{p.age}"
)utput
CelloI I a$ Karthi!I age 6-
4o in these lines
Person = Struct.new :name, :age
p = Person.new
loo! at the highlighte/ partI 0e have use/ Person 0ith capital ; an/ the co/e 0or!s<
I' you are 0orrie/ about the 'act that you nee/ to type/ a lot in the previous progra$ you can
shorten it as sho0n belo0. Kust ta!e a loo! at the highlighte/ line.
# struct_one_line.rb
person = Struct.new :name, :age
p = person.new "Karthik", 30
puts "Hello, I am #{p.name}, age #{p.age}"
)utput
CelloI I a$ Karthi!I age 6-
.e get the sa$e output but in this one line
p = person.new "Karthik", 30
.e have $anage/ to eli$inate these t0o lines
p.name = "Karthik"
p.age = 30
I' you have notice/ it rightI /oesn7t p = person.new "Karthik", 30 loo! li!e a constructor
41
stu''
41 I' you /on7t un/erstan/ 0hat this isI rea/ 1ncyclope/ia Jritannica in Cebre0.
1-7
I Love Ruby 2015 Beta
in classes@
Its not that a struct is Fust li$ite/ to its attribute /ata structure. Hou can ave 'unction that a struct
instance coul/ call as sho0n belo0 progra$. %ype it an/ e#ecute it.
# struct_about_me.rb
person = Struct.new :name, :age do
def about_me
"Hello, I am #{self.name}, age #{self.age}"
end
end
p = person.new "Karthik", 30
puts p.about_me
)utput
CelloI I a$ Karthi!I age 6-
Bs you can seeI there is a 'unction calle/ aboutP$e /e'ine/ bet0een the /o en/ bloc! o' the struct.
.e /eclare a person p in this line p = person.new "Karthik", 30 an/ call the aboutP$e
'unction on p li!e this puts p.about_me an/ the progra 0or!s 'ine. Hou ust also note that 0e can
pass argu$ents to 'unctions in structI but I haven7t sho0n that e#a$ple /ue to $y laGiness.
No0 lets see ho0 to /o structure in a 0rong 0ay. %ype the progra$ belo0 an/ e#ecute it
# struct_wrong.rb
person = Struct.new :name, :age
p = person.new
p.name = "Karthik"
p.age = 30
p.profession = "Engineer"
puts "Hello, I am #{p.name}, age #{p.age}, and I am on a #{p.profession}"
)utput
structP0rong.rbA7Ain ^W$ainV7A un/e'ine/ $etho/ ^pro'ession=7 'or _Wstruct na$e=[Karthi![I
age=6-V +NoMetho/1rror,
I' you get the !in/ o' output as sho0n aboveI it $eans that you have type/ the progra$ rightly
0rong. %he proble$ is in the highlighte/ line p.profession = "Engineer" I 0e are assigning
/ata to a attribute na$e/ pro'ession 0hich 0e haven7t /eclare/ in the struct person =
Struct.new :name, :age . 4o it thro0s an error. %o avoi/ these !in/ o' thingsI you can use a
2pen 4truct as sho0n in progra$ belo0
# open_struct.rb
1-"
I Love Ruby 2015 Beta
require 'ostruct'
p = OpenStruct.new
p.name = "Karthik"
p.age = 30
puts "Hello, I am #{p.name}, age #{p.age}"
)utput
CelloI I a$ Karthi!I age 6-
2pen 4truct is li!e structI but its /oes not has its /ata structure or attributes pre/e'ine/. No0 I a$
laGyI so thin! that I have e#plaine/ the progra$ above to you.
1-&
I Love Ruby 2015 Beta
Rdoc
Hou are rea/ing this boo! because you are loo!ing 'or so$e !in/ o' /ocu$entation to start
progra$$ing in Ruby. Docu$entation is highly i$portant in any !in/ o' progra$$ing. Keeping a
goo/ /ocu$entation 'or the piece o' co/e you 0rite $ight /istinguish you 'ro$ a goo/ progra$$er
an/ $a!e you the one 0ho is sought a'ter. %his chapter tells you t0o thingsI 'irst 0here are Ruby7s
core /ocu$entationI an/ ho0 to 'in/ it an/ rea/ it. %he secon/I it teaches you ho0 to generate
/ocu$entation so that others can better un/erstan/ your progra$.
Rea#ing Ruby Documentation
*ets say that you 0ant to !no0 about 4tring class in Ruby progra$. Hou 0ant to !no0 ho0 to
count nu$ber o' character in ones na$e using RubyI so ho0 to /o it@ 8isit this lin! httpA))rubyL
/oc.org) I its the centraliGe/ place 0here ruby /ocu$entations are available. No0 i' you can go
through it a bit you 0ill 'in/ a thing ) lin! li!eA 5.1.1 core L Core B;I /ocs 'or Ruby 5.1.1. Clic! on
it an/ you 0ill be /irecte/ to this lin!A httpA))rubyL/oc.org)coreL5.1.1) I its here 0here core libraries
'or 5.1.1 are /ocu$ente/.
B :uestion $ay ariseI ho0 to 'in/ out the version o' ruby you are using@ In ter$inal type ruby -v
it 0ill thro0 out an output li!e thisA ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-
linux] I loo! at the highlighte/ piece o' co/eI this tells $e that I a$ using ruby 1.&.6p1&4. .ho the
hec! cares 0hat p1&4 is@ I !no0 I a$ using ruby 1.&.6I so I a$ going to see its /ocu$entation<
2KI in httpA))rubyL/oc.org)coreL5.1.1) you nee/ to bro0se 'or 4tringI i' you /o you 0ill 'in/ this
lin!A httpA))rubyL/oc.org)coreL5.1.1)4tring.ht$l I this is 0here the 4tring class /ocu$entation is. Hou
can get to this /ocu$entation in this long long + going through al$ost everything, 0ay or by typing
4tring in the top search bar in 0hich case R/oc 0ill /isplay vali/ search results.
%he i$age belo0 sho0s I a$ 'iltering the classes in Ruby by typing 4ting into a te#t bo# labele/
Classes. %his 0ill help $e to 'ilter the results ) classes easily.
11-
I Love Ruby 2015 Beta
2K thenI i' you have got it rightI clic! on the 4tring to get you here httpA))rubyL/oc.org)coreL
5.1.1)4tring.ht$l an/ bro0se /o0nI you 0ill 'in/ so$ething calle/ _length 0hich 0hen clic!e/ 0ill
scroll here httpA))rubyL/oc.org)coreL5.1.1)4tring.ht$l_$etho/LiLlength I so it /oes say 0e have a
thing ) 'unction ) $etho/ calle/ length an/ another thing calle/ siGe.
3ro$ an e/ucate/ guess 0e $ust be able to !no0 that this is 0hat gives the length o' a 4tringI lets
try it out on irb
$ irb --simple-prompt
>> "Karthikeyan A K".length
=> 15
>> "Karthikeyan A K".size
=> 15
4o it 0or!s< %he basic thing is to reach httpA))rubyL/oc.org) an/ brea! your hea/I that 0ill get
so$ething going an/ 0ill get you starte/ !no0ing to rea/ Ruby /ocu$entation.
)reating Documentation
4o hope'ully or hopelessly you $ight or $ight not !no0 rea/ ruby7s /ocu$entation. *ets see ho0
to create one. 2KI type the co/e belo0 in a /ocu$ent calle/ r/ocPs:uare.rb I or 0hatever na$e you
pre'er. 3or si$plicity put it into a 'ol/er an/ $a!e sure that no other 'ile is present in that 'ol/er.
#rdoc_square.rb
# This class Square takes in side_length (of type float or fixnum)
# as argument
111
I Love Ruby 2015 Beta
class Square
# The length of a square's side
attr_accessor :side_length
# Retuns the area of the square
def area
@side_length * @side_length
end
# Returns perimeter of the square
def perimeter
4 * @side_length
end
end
Notice ho0 I have a//e/ co$$ents
45
be'ore attributes an/ 'unctions. No0 navigate to that 'ol/er
+ using console ) ter$inal , 0here r/ocPs:uare.rb is locate/ an/ type this co$$an/ rdoc I thats itI
the $agic happens. Hou 0ill 'in/ a 'ol/er na$e/ /oc create/I Fust navigate into the 'ol/er an/ open
/ocu$ent na$e/ in/e#.ht$l I you can then clic! on the 4:uare lin! in Classes and Modules Index
bo# to get a nice /ocu$entation as sho0n.
In the picture aboveI in the Bttributes section you can see the /ocu$entation 'or side_length
attributeI see Fust belo0 that is the /ocu$entation 'or it that rea/s The length of a square's side.
No0 chec! the co/e r/ocPe#a$ple.rb chec! the t0o highlighte/ lines sho0n belo0
class Square
# The length of a square's side
attr_accessor :side_length
45 Its possible to use $ar!/o0n in R/oc. %o !no0 about $ar!/o0n visit httpsA))en.0i!ipe/ia.org)0i!i)Mar!/o0n
115
I Love Ruby 2015 Beta
....
end
.e have Fust a//e/ a co$$ent line be'ore attr_accessor :side_length that appears on the
/ocu$entation page. %hats ho0I r/oc /eter$ines 0hat to put 'or /ocu$entation. It Fust chec!s 0hat
are the co$$ents that occurs be'ore the /eclaration o' classesI variables an/ 'unction /e'initions
an/ puts it into the /ocu$entationI pac!s it neatlyI puts a nice C44 +that is styling, an/ Kavascript
+ thats 'or the /yna$ic e''ects
46
, an/ gives it to you rea/y to re'er. Hou can /istribute the co/e as
0ell as the /oc 'ol/er to other 'or re'erence so that people 0ill have better ti$e un/erstan/ing your
co/e 0ithout going through all the lines o' ruby co/ing.
4o these are the steps to generating a /ocu$entation
;ut co$$ente/ ruby 'iles into 'ol/er
Navigate to the 'ol/er via ter$inal an/ type rdoc
Hou 0ill see a 'ol/er calle/ /oc create/I Fust go into the 'ol/er an/ launch the 'ile in/e#.ht$l
46 type so$ething into search bo# an/ see
116
I Love Ruby 2015 Beta
Modules and Mi'ins
.hen ever you thin! o' $o/ulesI you thin! o' a bo# or so$ething. Kust loo! at your printer. Its a
$o/ule. It can /o so$e thing. It has things to /o so$ething. In a si$ilar 0ay $o/ules in Ruby can
contain Ruby co/e to /o so$ething. Mo/ules are 0ay to pac! Ruby co/e into possible logic units.
.hen ever you 0ant to use the co/e in a $o/uleI you Fust inclu/e it in your Ruby progra$.
*ets loo! at our 'irst $o/ule progra$ calle/ module_function.rb . %he progra$ belo0 has t0o
$o/ules na$ely StarI Dollar. Joth these $o/ules have the sa$e 'unction calle/ line. Note that
in the 'unction line in $o/ule StarI 0e print a line o' 5- star +T, characters. In si$ilar 'ashion in
'unction line in $o/ule Dollar 0e print a line o' 5- /ollar +R, characters. %ype the progra$ in
your te#t e/itor an/ e#ecute it.
# module_function.rb
module Star
def line
puts '*' * 20
end
end
module Dollar
def line
puts '$' * 20
end
end
include Star
line
include Dollar
line
2utput
********************
$$$$$$$$$$$$$$$$$$$$
*ets loo! at the progra$ thats outsi/e the $o/ule. .e have the 'ollo0ing co/eA
include Star
114
I Love Ruby 2015 Beta
line
include Dollar
line
In the line include StarI 0e inclu/e the co/e thats in the Star $o/uleI then 0e call the 'unction
lineI so 0e get output as a line o' 5- stars. *oo! at the ne#t lineI 0e inclu/e the $o/ule Dollar.
Dollar too has a 'unction calle/ line. 4ince this $o/ule is calle/ a'ter StarI the line 'unction in
Dollar $o/ule over 0rites or in the right ter$s hi/es the line 'unction in the Star $o/ule. Cence
calling line a'ter include Dollar 0ill e#ecute co/e in the line 'unction o' Dollar $o/ule. Cence
0e get a line o' t0enty /ollar sign.
In the co$ing e#a$ple module_function_0.rb 0e 0ill see 0hat happens 0hen 0e call the line
'unction 0ithout inclu/ing any $o/ule. %ype the progra$ belo0 an/ e#ecute it
# module_function_0.rb
module Star
def line
puts '*' * 20
end
end
module Dollar
def line
puts '$' * 20
end
end
line
2utput
module_function_0.rb:15:in `<main>': undefined local variable or method `line'
for main:Object (NameError)
Bs you can see that line is consi/ere/ as un/e'ine/ local variable or a $etho/
44
. 4o 0e can say that
the 'unctions in $o/ule can be accesse/ only i' the $o/ule is inclu/e/ in your progra$.
*ets say that 0e 0rite another $o/ule 0ithout any 'unction but Fust co/e in it. I 0rote the 'ollo0ing
progra$ module.rb Fust because I 0ant to see 0hat happens. Bs it turns outI 0hen $o/ule is co/e/
in a Ruby 'ile an/ e#ecute/I the co/e in $o/ule gets e#ecute/ by /e'ault. %his happens even i' 0e
44 Metho/s are another na$e 'or 'unction
115
I Love Ruby 2015 Beta
/on7t inclu/e the $o/ule.
# module.rb
module Something
puts "Something"
end
module Nothing
puts "Nothing"
end
2utput
Something
Nothing
%he output o' the above progra$ module.rb prints out Something an/ Nothing. .e have put t0o
$o/ules calle/ Something 0hich contains the co/e puts Something an/ another $o/ule
Nothing 0hich contains puts Nothing. %hough I haven7t inclu/e/ these $o/ules in $y progra$
using include state$entI the co/e un/er the$ gets e#ecute/ any0ay.
)alling functions $ithout inclu#e
In the progra$ module_function.rb I 0e have seen ho0 to inclu/e $o/ule an/ call the
'unction+s, in it. .e printe/ a line o' stars an/ /ollars. *ets /o the sa$e in a /i''erent 0ay. %his ti$e
0e 0ont be using the include !ey0or/.
%ype the progra$ module_function_1.rb an/ e#ecute it.
# module_function_1.rb
module Star
def Star.line
puts '*' * 20
end
end
module Dollar
def Dollar.line
puts '$' * 20
end
end
116
I Love Ruby 2015 Beta
Dollar::line
Star::line
Dollar::line
2utput
$$$$$$$$$$$$$$$$$$$$
********************
$$$$$$$$$$$$$$$$$$$$
%a!e a loo! at the 'ollo0ing co/eA
Dollar::line
Star::line
Dollar::line
.hen 0e call Dollar::line I the line 'unction in Dollar $o/ule gets e#ecute/. .hen 0e call
Star::line I the line 'unction in the Star $o/ule gets e#ecute/. Doesn7t it loo! si$ple that to use
include state$ent@ 4o 0hen you 0ant to call a 'unction in $o/ule Fust use the 'ollo0ing synta#
<module-name>::<function-name> .
Note that in $o/ule StarI 0e have /e'ine/ the 'unction line as Star.line an/ not Fust line.
4i$ilarly in $o/ule Dollar 0e have /e'ine/ it as Dollar.line.
2KI 0e are getting to !no0 about $o/ulesI no0 lets get our han/s really /irty. %ype the co/e belo0
+module_function_2.rb, an/ e#ecute it.
# module_function_2.rb
module Star
def Star.line
puts '*' * 20
end
end
module Dollar
def Dollar.line
puts '$' * 20
end
end
module At
def line
puts '@' * 20
end
117
I Love Ruby 2015 Beta
end
include At
Dollar::line
Star::line
Dollar::line
line
2utput
$$$$$$$$$$$$$$$$$$$$
********************
$$$$$$$$$$$$$$$$$$$$
@@@@@@@@@@@@@@@@@@@@
2K you have got so$e output. %a!e a loo! at the 'ollo0ing lines
include At
Dollar::line
Star::line
Dollar::line
line
Note that 0e have inclu/e/ the $o/ule At at 'irst +see highlighte/ co/e above, using the include
At state$ent. .hile e#ecuting the Dollar::line state$entI 0e get an output o' t0enty /ollars
0hich 'or$s a line. .hile e#ecuting Star::line 0e get a output o' t0enty stars. Ne#t 0e once
again call Dollar::lineI then co$es the catch. .e Fust call the 'unction line. 4ince 0e have
inclu/e/ At at 'irstI 0hen the state$ent line is encountere/ it calls the line $etho/ in At $o/ule
gets calle/. %his sho0s that though 0e have calle/ Dollar::line an/ Star::line I it /oes not
inclu/e
45
the $o/ule co/e in the progra$I instea/ it Fust e#ecutes the particular 'unction in the
$o/ule.
In module_function _1.rb I 0e have seen ho0 0e can call a 'unction in a $o/ule say
Star::line I 0here 4tar is the $o/ule na$e an/ line is the 'unction na$e. %o /o so in 4tar $o/ule
0e have /e'ine/ the 'unction line as 'ollo0s
def Star.line
puts '*' * 20
end
.here instea/ o' na$ing it Fust lineI 0e have na$e/ it Star.line. Note that
45 2r $i#in
11"
I Love Ruby 2015 Beta
$o/uleP'unctionP6.rb is si$ilar to module_function_1.rbI but ta!e a /eep loo! into line 'unction
in Dollar $o/ule. It is not na$e/ Dollar.line I instea/ its na$e/ Star.line . .hat 0ill happen
i' 0e $ess up the co/e li!e this@ 1#ecute the progra$ belo0 an/ see.
# module_function_3.rb
module Star
def Star.line
puts '*' * 20
end
end
module Dollar
def Star.line
puts '$' * 20
end
end
module At
def line
puts '@' * 20
end
end
include At
Dollar::line
Star::line
Dollar::line
line
2utput
@@@@@@@@@@@@@@@@@@@@
$$$$$$$$$$$$$$$$$$$$
@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@
Notice that 0henever 0e call Dollar::line I the line 'unction in At $o/ule is calle/. Its because
since 0e have /e'ine/ it as Star.line in Dollar $o/uleI Dollar::line si$ply /oes not e#ist an/
hence the 'unction line in the At $o/ule is calle/. Note that 0e have inclu/e/ At $o/ule using
the state$ent include At.
.e no0 consi/er another scenario 0here +see progra$ module_function_4.rb , in the Dollar
$o/ule 0e Fust /e'ine the 'unction line as line an/ not as Dollar.line. .hen 0e call it using
Dollar::line in the progra$ belo0I 0e see that the line 'unction in the At $o/ule gets calle/. 4o
11&
I Love Ruby 2015 Beta
the $oral o' the story isI i' you are calling <module-name>::<function-name> in your progra$I
$a!e sure that the 'unction is na$e/ <module-name>.<function-name> insi/e the $o/ule.
# module_function_4.rb
module Star
def Star.line
puts '*' * 20
end
end
module Dollar
def line
puts '$' * 20
end
end
module At
def line
puts '@' * 20
end
end
include At
Dollar::line
Star::line
Dollar::line
line
2utput
@@@@@@@@@@@@@@@@@@@@
********************
@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@
)lasses in mo#ules
.e have seen ho0 the Ruby interpreter behaves to 'unctions in $o/ules. *ets no0 see ho0 it
behaves to classes in $o/ules. %ype the progra$ belo0 module_class.rb an/ e#ecute it.
# module_class.rb
module Instrument
class Ruler
def what_u_do?
puts "I take measurements"
15-
I Love Ruby 2015 Beta
end
end
end
module People
class Ruler
def what_u_do?
puts "I govern this land"
end
end
end
r1 = People::Ruler.new
r2 = Instrument::Ruler.new
r1.what_u_do?
r2.what_u_do?
2utput
I govern this land
I take measurements
*ets analyGe the progra$. .e have t0o $o/ules. %he 'irst one is na$e/ InstrumentI an/ the
secon/ one is na$e/ People. Joth have a class na$e/ Ruler an/ both Ruler7s have $etho/ na$e/
what_u_do? . 3ineI no0 lets co$e to the progra$. .e have a state$ent r1 = People::Ruler.new
in 0hich r1 beco$es an instance variable o' Ruler class o' People $o/ule. 4i$ilarly 0e have r2
= Instrument::Ruler.new in 0hich r2 beco$es instance variable o' Ruler class in Instrument
$o/ule.
%his can be veri'ie/ by e#ecuting the 'ollo0ing co/e
r1.what_u_do?
r2.what_u_do?
In 0hich calling r1.what_u_do? outputs I govern this land an/ calling r2.what_u_do?
outputs I take measurements.
%he $oral o' the story is you can have sa$e class na$es in /i''erent $o/ulesI to call that class Fust
use <module-name>::<class-name> .
151
I Love Ruby 2015 Beta
%ixins
Bnother use o' $o/ules is that you can $i# co/e in $o/ules as you 0ish. %his one is calle/ $i#in.
.e have alrea/y seen about $i#ins but I haven7t tol/ you that it 0as $i#in. 3or e#a$ple lets say
that you are 0riting so$e application in Ruby 'or *inu# an/ Bpple $achine. Hou 'in/ that so$e
co/e 0or!s only on *inu# an/ other 0or!s only on BppleI then you can separate the$ as sho0n
belo0. %he Bpple stu'' goes into Bpple $o/ule an/ *inu# stu'' goes into the *inu# $o/ule.
*ets say that your 'rien/ uses a *inu# $achine an/ 0ants to run your progra$. Bll you nee/ to /o is
to inclu/e *inu# in your co/e as sho0n belo0.
# mixin.rb
module Linux
# Code for linux goes here
def function
puts "This function contains code for Linux systems"
end
end
module Apple
# Code for apple goes here
def function
puts "This function contains code for Apple systems"
end
end
include Linux
function
2utput
This function contains code for Linux systems
.hen the $etho/ function is calle/I the $etho/ function in *inu# $o/ule 0ill be calle/. In
short you have $i#e/ in *inu# co/e in your progra$ an/ have !ept out the Bpple stu''.
*ets see another e#a$ple o' $i#in. %a!e a loo! at the co/e mixin_2.rb belo0. *ets say that your
client tells that he is ba/ly nee/ o' a progra$ that co$putes the area o' circle an/ volu$e o' sphere.
4o you /evelop t0o classes calle/ Circle an/ Sphere an/ e:uip 0ith co/e to 'in/ area an/
155
I Love Ruby 2015 Beta
volu$e. 4o your client is happy. 4ince your client is in Mil!y0ay gala#yI the constant Pi
46
is 55
/ivi/e/ by 7. 4o 0e have put the value o' Pi in a $o/ule na$e/ Constants an/ have inclu/e/ in
Circle an/ Sphere class using the state$ent include Constants. %ype in the progra$ belo0 an/
e#ecute it.
# mixin_2.rb
module Constants
Pi = 22.0/7
end
class Circle
include Constants
attr_accessor :radius
def area
Pi * radius * radius
end
end
class Sphere
include Constants
attr_accessor :radius
def volume
(4.0/3) * Pi * radius ** 3
end
end
c = Circle.new
c.radius = 7
s = Sphere.new
s.radius = 7
puts "Circle Area = #{c.area}"
puts "Sphere Volume = #{s.volume}"
2utput
Circle Area = 154.0
Sphere Volume = 1437.333333333333
4o you get so$ething as output. Hou $ight as! 0hats so great in putting a constant in a $o/ule an/
$i#ing it in a class using include state$ent. .ell the above progra$ teaches you t0o $orals
Hou can put constants in a $o/ule
46 ;i is a $athe$atical constant use/ to 'in/ area o' circle an/ volu$e o' sphere. (nless you are 1instienI /on7t bother
about it.
156
I Love Ruby 2015 Beta
I' you have co$$on co/e
47
that can be share/ bet0een classesI you can put it into $o/ule
an/ share it.
I' you have /e'ine/ the value o' Pi separately in each class an/ i' you happene/ to get a client 'ro$
Bn/ro$e/a gala#y 0here ;i is 57 /ivi/e/ by 1".1664I you can $a!e change Fust in one placeI that
is in constants $o/ule an/ see the change re'lect in $any classes +Circle an/ Sphere classes in
our case,.
%hus $oral is $o/ules help us to cater custo$ers 0ho are beyon/ our o0n gala#y an/ 0e can truly
buil/ a galactic e$pire
4"
.
47 Co$$on 'unctions an/ constants
4" 4o$e0hat li!e a 4tar .ars thing. 4o i' you have a /rea$ to beco$e alactic 1$perorI stu/y Ruby.
154
I Love Ruby 2015 Beta
Shebang
()
*ets say that you have 0ritten a ruby progra$ calle/ something.rb an/ 0ant to run it. %o run itI in
your console you $ust $igrate to the /irectory in 0hich its present an/ type in ruby
something.rb to e#ecute it. Instea/ o' /oing such a te/ious proce/ure 0hy can I e#ecute the
progra$ by Fust typing its na$e li!e ./something.rb as you 0oul/ /o to e#ecute a e#ecutable 'ile.
*ets 'in/ out ho0 to /o it to a ruby progra$.
%o /o so 0e $ust 'in/ out 0here our Ruby interpreter is installe/I 'or that 0e 0ell :uery 0here is
Ruby as sho0n
$ whereis ruby
ruby: /usr/bin/ruby1.8 /usr/bin/ruby /usr/lib/ruby /usr/share/man/man1/ruby.1.gz
3ro$ e#perience on $y (buntu syste$ I can say $y Ruby interpreter is in )usr)bin 'ol/erI I can call
it or e#ecute it using the co$$an/ )usr)bin)ruby. 3ire up your te#t e/itorI type in the co/e sho0n
belo0 an/ save it as shebang.rb
#!/usr/bin/ruby
# shebang.rb
puts "Just put #!/usr/bin/ruby to make your Ruby programs
execute without using ruby before them"
%a!e a loo! at the 'irst line thats been highlighte/. %he line is calle/ shebang
5-
I its starts 0ith a
co$$ent sign _ 'ollo0e/ by a e#cla$ation $ar! < %hen its i$$e/iately 'ollo0e/ by the path to the
Ruby interpreter. %hats it. Hour rest o' the progra$ can 'ollo0 as usual.
%o e#ecute the piece o' 'ileI 0e $ust 'irst $a!e this as an e#ecutable. .e $a!e it as e#ecutable
using the chmod a+x file_name as sho0n
$ chmod a+x shebang.rb
2nce 0e have /one it all 0e nee/ to /o is to type the 'ilena$e as sho0n belo0
$./shebang.rb
Just put #!/usr/bin/ruby to make your Ruby programs
execute without using ruby before them
%he ./ says that the 'ile is in current 0or!ing /irectory. 2nce 0e type the 'ile na$eI /ue to the
shebang line the operating syste$ passes the 'ile to Ruby interpreter 0hich is locate/ in /usr/bin
4& 4hebang /oes not 0or! i' you have installe/ ruby using the rv$
5- I thin! its inventor 0as bange/ by his girl 0hile he 0as inventing thisI so he $ay have na$e/ it >4he Jang?
155
I Love Ruby 2015 Beta
an/ the interpreter 'aith'ully e#ecutes the progra$.
Date and *ime
Ruby has got 0ays by 0hich 0e can e#tract ti$e an/ /ate 'ro$ our co$puter cloc!. Bll $o/ern /ay
personal co$puters has got a thing calle/ R%C or real ti$e cloc! 0hich is po0ere/ by a battery an/
0oul/ $aintain the ti$e even i' the $achine is turne/ o''. Many progra$$ing languages let us
access this cloc! an/ /o $anipulation 0ith /ate an/ ti$e. *ets see ho0 to 0or! 0ith Ruby. *ets /o
this stu'' in our irb rather than 0riting progra$s into a 'ile
%he 'irst thing 0e /o is to 'in/ 0hats the ti$e no0@ 3or that Fust type Time.now in your irbI thats
it. Hou 0ill get the current ti$e.
>> Time.now
=> Thu Feb 25 16:54:45 +0530 2010
Time.now is a synony$ to Time.new 0hich creates a ne0 %i$e obFect. Hou can use Time.now or
Time.new I both 0ill give the sa$e result.
>> Time.new
=> Thu Feb 25 16:54:48 +0530 2010
In the 'ollo0ing co$$an/I 0e create a ne0 ti$e obFect ) instance an/ assign it to a variable t
>> t = Time.new
=> Thu Feb 25 16:55:02 +0530 2010
No0 having assigne/I ho0 to vie0 the value o' t@ .e 0ill use the inspect $etho/. 4o by typing
t.inspect I 0e can inspect 0hats in t.
>> t.inspect
=> "Thu Feb 25 16:55:02 +0530 2010"
t.inspect converts the ti$e obFect to a string an/ /isplays to us. %he sa$e thing can be /one by
to_s +to string, 'unction as sho0n belo0
>> t.to_s
=> "Thu Feb 25 16:55:02 +0530 2010"
t.year retrieves the year in ti$e obFect
>> t.year
=> 2010
t.month retrieves the $onth in ti$e obFect
>> t.month
156
I Love Ruby 2015 Beta
=> 2
t.day retrieves the /ay +in that $onth, in ti$e obFect
>> t.day
=> 25
t.wday retrieves the /ay7s nu$ber. Cere - $eans 4un/ayI 1 ` Mon/ayI 5 ` %ues/ay an/ so on till
6 $eans 4atur/ay
>> t.wday
=> 4
In above co/e snippetI the /ay 0as %hurs/ay
t.yday retrieves the /ay in that year. 3or e#a$ple 1
st
o' 3ebruary is the 65
n/
/ay in the year
>> t.yday
=> 56
t.hour retrieves the hour in the ti$e obFect. %he hour is 54 hour 'or$at
>> t.hour
=> 16
t.min retrieves the $inutes value in ti$e obFect
>> t.min
=> 55
t.sec retrieves the secon/s in ti$e obFect
>> t.sec
=> 2
t.usec retrieves $icrosecon/s in the ti$e obFect. %his 0ill be use'ul i' you are co$$issione/ to
0rite a stop0atch application 'or 2ly$pics.
>> t.usec
=> 357606
t.zone retrieves the Gone. I a$ in In/iaI 0e 'ollo0 In/ian 4tan/ar/ %i$e hereI its spelle/ I4% 'or
short
>> t.zone
=> "IST"
%here is a thing calle/ (%C or (niversal %i$e Coor/inate. Its the ti$e thats at longitu/e -
o
. %he
t.utc_offset /isplays the nu$ber o' secon/s your ti$e is 'ar a0ay 'ro$ the ti$e at (%C.
>> t.utc_offset
=> 19800
3ro$ the above e#a$pleI I ca$e to !no0 that a person living at reen0ich 0ill see sunrise a'ter
1&"-- secon/s a'ter I have seen.
D4% $eans /aylight saving ti$e. I /on7t !no0 0hat it is. I' your ti$eGone has a /aylight savingI
157
I Love Ruby 2015 Beta
this 'unction returns trueI else 'alse
>> t.isdst
=> false
I' your ti$eGone is (%CI the t.utc returns true or returns 'alse
>> t.utc?
=> false
I' you 0ant to get the local ti$e Fust call the local ti$e 'unction as sho0n. .e 0ant t to hol/ local
ti$e value in this case
>> t.localtime
=> Thu Feb 25 16:55:02 +0530 2010
In sa$e 0ay as local ti$eI the gmtime 'unction gets the reen0ich Meri/ian %i$e.
>> t.gmtime
=> Thu Feb 25 11:25:02 UTC 2010
%he getlocal 'unction is the alias o' local ti$e
>> t.getlocal
=> Thu Feb 25 16:55:02 +0530 2010
%he getutc 'unction is alias o' gmtime. Bctually gmtime is alias o' getutc
>> t.getutc
=> Thu Feb 25 11:25:02 UTC 2010
%he ctime 'unction 'or$ats the ti$e to so$e0hat hu$an rea/able 'or$.
>> t.ctime
=> "Thu Feb 25 11:25:02 2010"
*ets say 0e 0ant to subtract so$e secon/s 'ro$ the ti$e value tI 0e can /o it as sho0n. Jelo0 0e
subract "64-- secon/s +1 /ay, 'ro$ our ti$e value
>> t - 86400
=> Wed Feb 24 11:25:02 UTC 2010
Days bet$een t$o #ays
*ets no0 0rite a co/e snippet that 'in/s the nu$ber o' /ays bet0een 3ebruary 55
th
5-1- to May 1
st
5-1-I 'irst 0e /eclare a variable a an/ assign it 0ith the /ay 3ebruary 55
th
5-1- as sho0n
>> a = Time.local 2010, 2, 25
=> Thu Feb 25 00:00:00 +0530 2010
Notice 0e use a 'unction calle/ local in %i$e class or obFectI 0e can assign a /ate to it. Bs 0e
coul/ see in the outputI 0e get to !no0 that variable a no0 has the value o' 3ebruary 55
th
. In
si$ilar 'ashion 0e create a variable b an/ assign it 0ith /ate 1
st
o' May 5-1-
>> b = Time.local 2010, 5, 1
=> Sat May 01 00:00:00 +0530 2010
15"
I Love Ruby 2015 Beta
Bll 0e /o no0 is subtract a 'ro$ b
>> b-a
=> 5616000.0
%his gives nu$ber o' secon/s bet0een a an/ b. .e /ivi/e the result by "64-- +thats ho0 $any
secon/s that are in a /ay,
>> days = _ / 86400
=> 65.0
.e get a result as 65. Cool<
0o$ many #ays have you live#-
*ets no0 see a progra$ that ta!es in your birth/ay an/ prints out ho0 $any /ays have you live/.
%ype in the progra$ in te#t e/itor an/ e#ecute it
#!/usr/bin/ruby
# how_many_days.rb
print "Enter birthday (YYYY-MM-DD):"
bday = gets.chop
year, month, day = bday.split('-')
# puts " #{year}, #{month}, #{day}"
seconds = Time.now - Time.local(year, month, day)
days = (seconds / 86400).round
puts "You have lived for #{days} days"
Cere is the result
Enter birthday (YYYY-MM-DD):2000-5-23
You have lived for 3566 days
.ell this $ay vary on 0hen you e#ecute this progra$. *ets no0 analyGe it. In the 'irst line
print "Enter birthday (YYYY-MM-DD):"
.e as! the user to enter his or her birth/ayI once /one 0e per'or$ a tric! here. .e as!e/ the user
to enter it in HHHHLMMLDD 'or$atI in the state$ent
bday = gets.chop
.e get the /ate an/ store it in a variable calle/ bday. %he gets.chop gets the birth /ay an/ chops
o'' the enter sign 0e enter 0ith it. 4o bday no0 hol/s the string value o' birth/ay you entere/. In
the ne#t state$ent
year, month, day = bday.split('-')
0e have a $ultiple assign$ent in 0hich I have three variables yearI $onth an/ /ay. I a$ splitting
the birth/ay string an/ assigning it. .hat really happens is thisI i' 0e enter a /ate li!e 1&&4L6L54 it
gets split by 9 an/ beco$es an array 0hich is sho0n in co/e snippet belo0 e#ecute/ in irb
>> "1994-6-24".split '-'
15&
I Love Ruby 2015 Beta
=> ["1994", "6", "24"]
*ets assign this array to variables aI bI c si$ultaneously as sho0n
>> a, b, c = _
=> ["1994", "6", "24"]
I' you re$e$ber P +un/erscore, $eans the last obtaine/ result in irb. 4o having assigne/ it 0e no0
chec! values o' aI b an/ c 0hich 0e get as sho0n....
>> a
=> "1994"
>> b
=> "6"
>> c
=> "24"
Isn7t ruby spectacular@ In si$ilar 'ashion in
year, month, day = bday.split('-')
%he year variable gets the year partI the month gets the $onth an/ day gets the /ay. 2K having
obtaine/ the para$eters o' a particular /ay 0e can procee/. 1#a$ine the 'ollo0ing state$ent
seconds = Time.now - Time.local(year, month, day)
4ee the right han/ si/e o' the e:ual to signI 'irst 0e have Time.now 0hich gets the current ti$eI
'ro$ it 0e are subtracting a ti$e obFect thats been create/ using Time.local. Time.local can be
use/ to create a ti$e obFect thats 'i#e/ at any instanceI the instance can be pastI present or 'uture.
.e pass the year $onth an/ /ay to it to create a %i$e obFect. .hat happens 0hen 0e subtract these
bothI 0e get the /i''erence in secon/s 0hich gets store/ in variable calle/ seconds at the le't han/
si/e o' the e:uation.
Bll 0e nee/ to /o no0 is to convert the secon/ to /ays 0hich is /one by the 'ollo0ing state$ent
days = (seconds / 86400).round
Cere 0e /ivi/e secon/s by "64-- 0hich converts the$ to /ays. .e $ight be getting so$e value
li!e 67".567 /aysI to get ri/ o' the .567 0e roun/ it o'' using the round 'unctionI so (seconds /
86400).round returns a neat roun/e/ value 0hich can be rea/ by hu$ans :uiet easily. .e store
the value in a variable calle/ /ays. 3inally 0e print the 'act that 0e have live/ 'or so $any long
/ays using the 'ollo0ing state$ent
puts "You have lived for #{days} days"
.ell thats it.
I 0oul/ li!e to tell one thing I 'oun/ out 0ith Time.local 'unctionI its not that 0e $ust pass only
nu$bers to it as sho0n
16-
I Love Ruby 2015 Beta
>> Time.local "2010", "5", "1"
=> Sat May 01 00:00:00 +0530 2010
.e can pass a bit hu$an 'rien/ly values as sho0n belo0. Instea/ o' putting 5 'or $onthI 0e use
May.
>>Time.local "2010", "may", "1"
=> Sat May 01 00:00:00 +0530 2010
4o$e ti$es Ruby language loo!s as easy as tal!ing 1nglish
161
I Love Ruby 2015 Beta
#iles
(ntil no0 you have store/ /ata in variables in your progra$. 8ariable /ata gets lost 0hen the
progra$ stops e#ecuting or 0hen the co$puter is s0itche/ o''. I' you 0ant a persistent storage you
$ust store it in 'iles. .hen you store /ata in 'ilesI it stays there even i' the co$puter is shut /o0nI
an/ you can get the /ata bac! 0hen its turne/ on. %his very boo! i' you are rea/ing it on co$puterI
!in/le or electronic rea/er is a 'ile thats store/ per$anently on your co$puter. In this chapter 0e
0ill see ho0 0e can createI $anipulate an/ /elete 'iles using ruby progra$.
*toring output into files
*ets create a 'a$iliar Ruby progra$. %ype the progra$ belo0 into a te#t e/itor
#!/usr/bin/ruby
# write_file.rb
puts "Hello World!"
puts "Ruby can write into files"
.hile e#ecuting itI give co$$an/ as sho0n
$ ruby write_file.rb > something.txt
No0 goto the 0or!ing /irectory in 0hich the progra$ 0as an/ you 0ill see a 'ile na$e/
something.txt . 2pen it an/ this is 0hat you 0ill see in it
Hello World!
Ruby can write into files
.ellI this ti$e its so$e0hat li!e a cheat. .e haven7t 0ritten into a 'ile in our progra$I instea/ 0e
have instructe/ the ruby interpreter to ta!e the output that write_file.rb generates an/ put it in a
'ile calle/ something.txt. %o /o so 0e $a!e use o' > +greater than sign,.
Taking file as input
In the last e#a$ple 0e 0rote our output to a 'ile. No0 lets ta!e a 'ile as input an/ lets process it.
.rite the co/e belo0 in te#t e/itor an/ save it as linePcount.rb.
#!/usr/bin/ruby
# line_count.rb
puts "The file has #{readlines.length} line(s)"
165
I Love Ruby 2015 Beta
%o e#ecute itI 0e 0ill give co$$an/ as sho0n
$ ruby line_count.rb < something.txt
I' you have guesse/ it rightI 0e given something.txt as input to the progra$. .e use the W +less
than,sign to in/icate to the progra$ that 0e are giving a 'ile as input.
%he progra$ 0hen e#ecute/ provi/es the 'ollo0ing result
The file has 2 line(s)
*ets analyGe the progra$ so 0e !no0 0hat happens. 4ee the co/e that been highlighte/ in the
progra$ above. %he readlines co$$an/ ta!es in the 'ile an/ rea/s all the lines an/ stores it in an
arrayI each ele$ent o' the array has a line. Bll 0e have to /o is to get the length o' an array 0hich
0e can get by using the length 'unction. 4o readlines.length gives the length as output 0hich
0e e$be/ it into a string hence 0e 'inish it o'' by 0riting the 'ollo0ing state$ent
puts "The file has #{readlines.length} line(s)"
'ile copy 5 a kin# of
.ellI here is 'ile copy progra$ 0hich $ight $a!e so$e pun/its argue 0eather i' this progra$ is a
true 'ile copy progra$ or not. %ype the progra$ belo0 into a te#t e/itor
#!/usr/bin/ruby
# file_copy.rb
puts readlines.join
Bn/ run it li!e this
$ ruby file_copy.rb < something.txt > everything.txt
2utput
everthing.txt has got everything that something.txt has got. Kust open it an/ see 'or yoursel'.
%he tric! is in the co$$an/line. Cere 0e pass something.txt to the progra$ file_copy.rb I
no0 the progra$ ta!es in something.txt an/ it rea/s the lines 0hen it encounters the readlines
co$$an/. %he lines that are rea/e/ 'ro$ something.txt are store/ in the 'or$ o' an array. Bll 0e
no0 have to /o is to Foin the lines store/ in array using join co$$an/I so 0e /o it by a//ing
.join to readlinesI hence 0e get
readlines.join
No0 0e 0ill print out the resultI 0e /o this by using a puts co$$an/I hence our progra$ ta!es the
'ollo0ing incarnation
166
I Love Ruby 2015 Beta
puts readlines.join
.hile running the progra$ 0e tell it to ta!e input 'ro$ something.txt an/ 0rite the generate/
result to everything.txt by giving the 'ollo0ing co$$an/ to Ruby interpreter
$ ruby file_copy.rb < something.txt > everything.txt
4o 0e get the e''ect o' copying 0ithout really 0riting a progra$ 'or 'ile copy.
Displaying a file
*ets no0 0rite a progra$ that /isplays the content o' a 'ile. %o /o so 0e rea/ all lines in a 'ileI store
it in an array. Ne#t 0e ta!e each an/ every ele$ent o' an array an/ print it out. %ype the progra$
belo0 an/
#!/usr/bin/ruby
# display_file.rb
readlines.each do |line|
puts line
end
1#ecute it by typing the 'ollo0ing
$ ruby display_file.rb < something.txt
%his is 0hat you 0ill get as output
Hello World!
Ruby can write into files
4o 0hat 0e have /one in this progra$.@ *oo! at the highlighte/ co/e bloc!I 0hen ruby encounters
readlines I it rea/s 'ro$ the 'ile passe/ to the progra$I e#tracts the lines an/ stores it in an array.
.ith .each operator 0e e#tract a single line at a ti$e an/ store it into a variable calle/ line insi/e
the do end bloc!. .e print out this line in the co/e bloc! using puts. %he en/ state$ent put an
en/ to the co/e bloc! says all is over.
*ets see another progra$. In this progra$ 0e use a $ore cleaner approach. %ype the progra$ into a
te#t e/itor an/ e#ecute it
#!/usr/bin/ruby
# display_file_1.rb
puts File.open("something.txt").readlines
2utput
Hello World!
Ruby can write into files
*oo! at the single line in the progra$. .e have a puts state$entI that prints al$ost 0hat ever is
thro0n at it. Cere is the ne0 thing thats been intro/uce/. *oo! at the highlighte/ co/eI 0e have a
164
I Love Ruby 2015 Beta
thing calle/ File.open(something.txt) I the File.open opens a 'ileI but 0hat 'ile@ .e $ust
give the na$e o' the 'ile to it. Bs a 'ile na$e 0e pass something.txt in /ouble :uotes
51
. %he
File.open opens itI the .readlines attache/ to it rea/s lines an/ stores it in an array. .e thro0 the
array to puts 0hich prints it out. %hats it<
Rea#ing file line by line
%ill the last section 0e have seen ho0 to rea/ a 'ile in a go an/ pu$p its /ata out to the console. In
this e#a$ple 0e 0ill see ho0 to rea/ a 'ile line by line. %ype in the e#a$ple co/e given belo0 an/
e#ecute it
#!/usr/bin/ruby
# read_file_1.rb
File.open("something.txt").each { |line| puts line }
2utput
Hello World!
Ruby can write into files
%he output loo!s as sho0n above. *oo! at the highlighte/ co/e In the co/e 0e open a 'ile na$e/
something.txt using a File.open co$$an/ 0hich opens the 'ile an/ stores the lines as array
ele$ents. Bll 0e nee/ to /o no0 is to e#tract each ele$ent in an array an/ print it out on our
console 0hich is acco$plishe/ by the line highlighte/ above.
Instea/ o' using File.open I one coul/ use File.new to open a 'ile. Bll 0ill have the sa$e result.
B progra$ using File.new has been 0ritten an/ is sho0n belo0I e#ecute it an/ you 0ill get the
sa$e result.
#!/usr/bin/ruby
# read_file_2.rb
File.new("something.txt").each { |line| puts line }
2utput
Hello World!
Ruby can write into files
+pen an# ne$ 5 the #ifference
4een 'ro$ previous e#a$ples one $ight thin! that there isn7t $uch /i''erence bet0een 3ile.open
an/ 3ile.ne0I in'act there is a /i''erence. Consi/er the progra$ belo0I type it an/ e#ecute it
51 B na$e is a string right@
165
I Love Ruby 2015 Beta
#!/usr/bin/ruby
# file_open.rb
File.open("something.txt") do |f|
puts f.gets
end
2utput
Hello World!
%he progra$ above prints out the content present in so$ething.t#tI the sa$e thing is /one by
'ilePne0.rb as sho0n belo0
#!/usr/bin/ruby
# file_new.rb
f = File.new("something.txt", "r")
puts f.gets
f.close
2utput
Hello World!
2K so 0hats the /i''erence@ File.new returns a ne0 'ile obFect or han/le that can be store into a
variable. In the above progra$ 0e store the 'ile obFect into variable f. .e can use this variable any
0here in the progra$ to access an/ $anipulate the 'ile. Caving /one all nee/e/ 0ith the 'ile using
the variable fI 0e 'inally close the 'ile using f.close.
*ets 0rite a progra$ na$e/ file_open_error.rb as sho0n belo0
#!/usr/bin/ruby
# file_new.rb
File.open("something.txt") do |f|
puts f.gets
end
puts "Reading file after File.open block is closed:"
puts f.gets # This should throw an error
2utput
Hello World!
Reading file after File.open block is closed:
file_open_error.rb:8: undefined local variable or method `f' for main:Object
(NameError)
4ee the highlighte/ co/eI 0e try to rea/ the 'ile content a'ter 0e close the co/e bloc! an/ it thro0s
an errorI this is because File.open loa/s into 'ile han/le into variable f insi/e the /o en/ co/e
bloc!I a'ter the bloc! is close/ you have no 0ay to access the 'ile.
166
I Love Ruby 2015 Beta
%hough the /i''erence is $inorI there is still a /i''erence.
Defining our o$n line en#ings
%ill no0 rea/ing line by line $eans that the Ruby progra$ 0hen given a 'ile na$e searches 'or itI
loa/s it then it scans the 'ileI 0hen it encounters a line en/ing character 7an7
55
on the *inu# syste$
+its aran on 0in/o0s, it recogniGes the line has en/e/ an/ hence pac!s the characters be'ore it into
an array ele$ent. .hat i' 0e 0ant to /e'ine our o0n line en/ing character@ In 1nglish language 'ull
stop is consi/ere/ as a line en/ing character. .hy can7t 0e say to the Ruby interpreter to $ar! en/
o' the line at a 'ull stop character@ %o /o so lets create a si$ple te#t 'ile na$e/ line_endings.txt
an/ put the 'ollo0ing te#t in it
This is first line. This is second line. This
is the third. And fourth comes after third.
*ets 0rite a Ruby progra$ sho0n belo0 in te#t e/itorI save it as line_endings.rb
#!/usr/bin/ruby
# line_endings.rb
File.open("line_endings.txt").each('.') do |line|
puts line
end
.hen e#ecute/ the progra$ prints out the 'ollo0ing output
This is first line.
This is second line.
This
is the third.
And fourth comes after third.
4ee care'ully line_endings.txt . %his is 'irst line A This is first line.
an/ %his is secon/ line A This is second line.
Joth are on the sa$e line in line_endings.txt but it gets printe/ out as t0o /i''erent lines 0hen
the progra$ is e#ecute/. %his is because the state$ent File.open("line_endings.txt") loa/s
the entire content o' the 'ile into the $e$oryI the .each('.') splits the content at every /ot or 'ull
stop character +7.7,I an/ puts the each chun! o' split te#t into an array ele$ent. 4o the real hero here
is the each 'unction. In a si$ilar 0ay you can have any character that can /e'ine a line en/ing.
I' you are 0riting a C co$piler using RubyI you $ight use the se$icolon character + N , as your line
en/ing.
55 %he an character 0ill not be sho0n to the user an/ hence you 0ont be able to see it 0hen you open the 'ile 0ith a
te#t e/itor.
167
I Love Ruby 2015 Beta
Rea#ing byte by byte
4o$eti$es you 0ant to rea/ a 'ile byte
56
by byte instea/ o' rea/ing plain 1nglish in it. .hy on
earth 0e rea/ a 'ile byte by byte@ .ellI not all 'iles have te#t in it. 3iles such as $usic 'ilesI vi/eos
an/ so on have ra0 /ata 0hich only so$e progra$s can un/erstan/. I' you are 0riting a $usic or
vi/eo player or i$age vie0erI you nee/ to rea/ the ra0 /ata an/ /o so$ething 0ith it. 4o to rea/
an/ /isplay bytes o' /ata 0e use each_byte 'unction. %a!e a loo! at the co/e belo0. %ype it an/
e#ecute it
#!/usr/bin/ruby
# byte_by_byte.rb
File.open("something.txt").each_byte { |byte| puts byte }
.hen e#ecute/ this is ho0 the output 0ill loo! li!e
72
101
108
108
111
32
87
111
.
.
some stuff is removed to save pages printed
.
.
105
108
101
115
10
In the above progra$ 0e open the 'ile na$e/ something.txt using File.open I all the contents
gets loa/e/I no0 0e access the content byte by byte using the each_byte 'unctionI 0e capture the
bytes in variable calle/ byte an/ print it out. Notice that in this progra$ 0e have use/ curly
brac!ets Y an/ ZI these can be use/ instea/ o' do an/ end . I pre'er do an/ end as they loo! $ore
'rien/ly.
Rea#ing single character at a time
%he progra$ belo0 rea/s character by character an/ prints it. .e use a 'unction calle/ each_char
0hich 0or!s 0ith Ruby 1.&.# version. Currently I have not installe/ itI so I a$ not giving a0ay the
56 %o !no0 0hat byte is goto httpA))0i!ipe/ia.org)byte
16"
I Love Ruby 2015 Beta
output o' this progra$.
#!/usr/bin/ruby
# char_by_char.rb
# To get this program to work, you must
# have ruby 1.9
File.open("something.txt").each_char { |a| puts a }
2utput
H
e
l
l
o

W
o
r
l
d
!
R
u
b
y

c
a
n

w
r
i
t
e

i
n
t
o

f
i
l
e
s
16&
I Love Ruby 2015 Beta
Renaming files
Rena$ing a 'ile is e#tre$ely easy in RubyI all you have to /o is to call the rename 'unction in 'ile
class. %he 'irst argu$ent 0ill be the na$e o' the 'ile that nee/s to be rena$e/I the secon/ one 0ill
be the ne0 na$e. Its so si$ple you can try it out on the irb. %a!e a loo! at the source co/e o'
progra$ rename.rb given belo0. In it 0e rena$e a 'ile calle/ noname.txt to somename.txt.
Je'ore you run the progra$ place a 'ile calle/ noname.txt on the 0or!ing /irectory.
#!/usr/bin/ruby
# rename.rb
File.rename("noname.txt", "somename.txt")
2utput
%he 'ile nona$e.t#t 0as rena$e/ to so$ena$e.t#t
'in#ing out position in a file
Hou $ight so$eti$e nee/ to 'in/ out your position 0ithin a 'ile. %o /o so you can use the $etho/
pos. *ets see an e#a$ple that e#plains us ho0 to 'in/ our position in a 'ile. %ype an/ e#ecute
fie_position.rb
#!/usr/bin/ruby
# file_position.rb
f = File.open "god.txt"
puts "At the beginning f.pos = #{f.pos}"
f.gets
puts "After reading first line f.pos = #{f.pos}"
f.gets
puts "After reading second line f.pos = #{f.pos}"
2utput
At the beginning f.pos = 0
After reading first line f.pos = 43
After reading second line f.pos = 69
*ets no0 0al!thru the co/e an/ see ho0 it 0or!s. 3irst 0e open a 'ile na$e/ god.txt in the line f
= File.open "god.txt" ne#t 0e chec! out 0hats the position using the state$ent puts "At the
beginning f.pos = #{f.pos}" I note the f.posI the pos $etho/ is use/ to get the position that
0e are in 0hile 0e rea/ or 0rite a 'ile. Initially 0hen 0e open a 'ile the position 0ill be at Gero an/
so 0e get the 'ollo0ing output
At the beginning f.pos = 0
In the ne#t line 0e rea/ the 'irst line o' 'ile using '.gets I since 0e have rea/ the 'ile li!e the rea/ing
14-
I Love Ruby 2015 Beta
pointers position shoul/ have change/
54
I so 0hen 0e print f.pos it $ust /isplay so$e other
nu$ber than Gero. 4o the state$ent puts "After reading first line f.pos = #{f.pos}"
pro/uces the 'ollo0ing result
After reading first line f.pos = 43
Kust 'or the sa!e o' e/ucating $ore 0e rea/ the secon/ line using another f.gets no0 0e print the
ne0 'ile positionI no0 0e 'in/ that the pointer points to position 69.
I' you are 0on/ering 0hat god.txt hasI here is itA
All things exists because it was created.
Then the creator exists.
Did man ever think how the creator exist?
If such a mighty creator can exist without creation,
then why can't this simple universe exist without
a creator?
In the co$ing e#a$ple 0e 0ill see ho0 to change our position 0ithin a 'ile. %ype the e#a$ple
belo0 +file_changing_position.rb, an/ e#ecute it
#!/usr/bin/ruby
# file_changing_position.rb
f = File.open "god.txt"
puts "Reading file with f.pos = 0"
puts f.gets
puts "_"*40
f.pos = 12
puts "Reading file with f.pos = #{f.pos}"
puts f.gets
puts "Now f.pos = #{f.pos}"
2utput
Reading file with f.pos = 0
All things exists because it was created.
________________________________________
Reading file with f.pos = 12
xists because it was created.
Now f.pos = 43
Rea/ the progra$ care'ully an/ notice the output. 3irst 0e open the 'ile god.txt an/ the variable f
has its han/le. Ne#t in line
puts f.gets
.e are rea/ing 0ith 'ile 0ith f.pos at GeroI that is 0e are rea/ing 'ro$ the start o' 'ile. Bs you can
see the output 'or the 'irst puts f.gets 0e get the entire line All things exists because it
was created. gets printe/. Notice the ne#t line care'ullyI 0e no0 change our position 0ithin 'ile
to position 15 using the state$ent f.pos = 12I this $eans that our pointer is 15 bytes 'ro$ the
54 In this caseI shoul/ be at the en/ o' 'ile
141
I Love Ruby 2015 Beta
start. No0 in the secon/ puts f.gets I 0e get the output as xists because it was created.
%his sho0s us that 0e are able to change our position 0ithin a 'ile in a success'ul 0ay.
4o$e $in/s coul/ thin! that there coul/ be a possibility o' negative 'ile position 0here say i' you
0ant to rea/ the last 5- bytes o' 'ile you can assign f.pos = -20 an/ 0hen giving f.gets it 0oul/
get printe/. .ellI thats not possible 0ith Ruby. I' you 0ant try out the e#a$ple
+file_negative_position.rb, an/ see 0eather it gives a proper result.
#!/usr/bin/ruby
# file_negative_position.rb
# this example wont work
f = File.open "god.txt"
f.pos = -20
puts "Reading file with f.pos = #{f.pos}"
puts f.gets
"riting into files
%ill no0 0e have seen ho0 to rea/ 'ro$ 'ilesI 0e 0ill no0 see ho0 to 0rite content into 'iles. %o
learn ho0 to 0rite into 'iles type the belo0 e#a$ple + write_file_1.rb , into the te#t e/itor an/
e#ecute it
#!/usr/bin/ruby
# write_file_1.rb
File.open "god.txt", "w" do |f|
some_txt = <<END_OF_TXT
All things exists because it was created.
Then the creator exists.
Did man ever think how the creator exist?
If such a mighty creator can exist without creation,
then why can't this simple universe exist without
a creator?
END_OF_TXT
f.puts some_txt
end
B'ter e#ecution open the 'ile god.txt an/ this is 0hat you 0ill see in it
All things exists because it was created.
Then the creator exists.
Did man ever think how the creator exist?
If such a mighty creator can exist without creation,
then why can't this simple universe exist without
a creator?
145
I Love Ruby 2015 Beta
*ets 0al! thru the progra$ an/ see ho0 it 0or!s. 3irst in the state$ent File.open "god.txt",
"w" I 0e open a 'ile na$e/ god.txt 'or 0riting. .e in/icate that 0e are opening the 'ile 'or
0riting by passing w as secon/ argu$ent. %his secon/ argu$ent is calle/ as a 'lag. iven belo0
are list o' 'lags that can be use/ 'or 'ile operations.
0*ag 7hat it &ay&
r ,he fi*e i& opene% in rea% on*y (o%e8 ,he fi*e pointer i& p*ace% at the &tart of fi*e8
r9 In r9 (o%e both rea%ing an% /riting i& a**o/e%8 ,he fi*e pointer i& p*ace% at the &tart of
the fi*e
/ ,hi& (ean& /rite on*y8 If the fi*e %oe& not e:i&t a ne/ fi*e i& create% an% %ata i& /ritten
into it8 If the fi*e e:i&t& the previou& content i& rep*ace% by ne/ content
/9 In thi& (o%e both rea%ing an% /riting i& a**o/e%8 If the fi*e %oe& not e:i&t a ne/ fi*e i&
create%8 If it e:i&t& the o*% content i& *o&t an% ne/ one & /ritten8
a ,hi& f*ag open& the fi*e in appen% (o%e8 #ppen% (o%e i& a &pecia* for( of /rite (o%e in
/hich the ne/ content a%%e% i& p*ace% the en% of o*% content
55
by thi& /ay previou&
infor(ation i&n't *o&t8
a9 Both rea%ing an% /riting i& a**o/e% (i8e appen% (o%e p*u& rea%ing an% /riting)8 #ny
ne/*y a%%e% %ata i& p*ace% at the en% of the fi*e8
b Binary fi*e (o%e8 In thi& (o%e fi*e& that have %ata other than te:t i& rea%8 0or e:a(p*e
opening a (u&ic or vi%eo fi*e8
Caving opene/ a 'ile in 0rite $o/e 0e no0 have opene/ a do end bloc! 0ithin 0hich 0e capture
the 'ile han/le in variable f. Bll 0e nee/ to /o is to 0rite a string to the 'ile.
.e create a string using the 'ollo0ing co/e
some_txt = <<END_OF_TXT
All things exists because it was created.
Then the creator exists.
Did man ever think how the creator exist?
If such a mighty creator can exist without creation,
then why can't this simple universe exist without
a creator?
END_OF_TXT
No0 some_txt has got a string 0hich 0e nee/ to 0rite it into the 'ile. %o 0rite it into the 'ile 0e
use the 'ollo0ing state$ent
f.puts some_txt
gets gets the 'ile contentI puts 0rites so$ething into the 'ileI so as an argu$ent to the puts
'unction 0e pass some_txt I the content hel/ in it gets 0ritten into the 'ile. %he progra$ reaches the
endI the 'ile is close/ an/ that7s it. .hen you open god.txt you can see 0hat7s 0ritten in it.
55 %he 'ile pointer is place/ at the en/ o' the 'ile
146
I Love Ruby 2015 Beta
/ppen#ing content into files
%ill no0 0e have seen ho0 to rea/ 'ro$ 'iles an/ 0rite content in it. No0 lets see ho0 to appen/
content in it. .hile appen/ing content into 'ilesI the ol/ content stays on the ne0 content is a//e/ at
the botto$ o' the page.
%o un/erstan/ ho0 this 0or!s type the progra$ file_append.rb an/ e#ecute it.
#!/usr/bin/ruby
# file_append.rb
puts "Enter text to append into file: "
text = gets
f = File.new("log_file.txt", "a")
f.puts "\n"+Time.now.to_s+"\n"+text
.hen the progra$ pro$pts you to enter so$e thingI type so$e thing li!e It will be great if
dinosaurs were still around an/ press enter. Run this progra$ a 'e0 ti$esI type so$ethingI
a'ter you got bore/ 'ro$ 'e0 run7s open log_file.txt an/ see 0hat it contains. .hen I opene/
$ineI this is 0hat I gotA
Sat Mar 27 16:20:24 +0530 2010
This is my first log
Sat Mar 27 16:21:10 +0530 2010
This is my second log
Sat Mar 27 16:21:36 +0530 2010
This is my third log. Now I'm getting bored.
4ee ho0 neatly your entries have been recor/e/ along 0ith ti$e sta$p. %o un/erstan/ ho0 the
progra$ lets 0al! thru it.
%he 'irst line puts "Enter text to append into file: " I prints out Enter text to append
into file: an/ the control goes on to the ne#t line text = gets at 0hich stage the progra$ 0aits
'or you to enter so$ething an/ press enter. .hen you /o press enterI 0hat you entere/ gets store/ in
variable text.
%he ne#t line f = File.new("log_file.txt", "a")is the crucial one an/ highlight o' our
progra$. In this line 0e open a 'ile calle/ log_file.txt in appen/ $o/e. Notice that 0e pass a
as the secon/ argu$ent to File.new 0hich tells that 0e are opening it in appen/ $o/e. In this
$o/e the content that 0as previously store/ in the 'ile is not erase/ an/)or over 0rittenI instea/
0hats ne0 being a//e/ is 0ritten at the en/ o' the page. +I' you are rea/ing ;D3 version, Hou can a
144
I Love Ruby 2015 Beta
list o' 'ile 'lags by clic!ing here.
2nce having opene/ in appen/ $o/eI all 0e nee/ to /o is to put content store/ in variable text into
the 'ile. 4ince the 'ile han/le is store/ in variable fI 0e coul/ have co$plete/ the progra$ by
0riting f.puts text I but I 0ishe/ it 0oul/ be better i' 0e logge/ our /ata 0ith ti$e sta$psI an/ I
have le't line brea!s be'ore an/ a'ter each log so that it 0ill be nice to rea/I so I have 0ritten the
co/e f.puts "\n"+Time.now.to_s+"\n"+text .
%hats itI the content 0e have 0ritten at the progra$ pro$pt an/ along 0ith the ti$e sta$p gets
store/ into the 'ile. Bt the en/ o' the progra$ it 0oul/ have been nice i' 0e ha/ close/ the 'ile using
f.close I I haven7t /one it in this progra$I but it 0or!s.
*toring ob6ects into files
%ill no0 0e have seen to rea/I 0rite an/ appen/ into 'ilesI 0hats 0e store/ an/ rea/ 0ere pieces o'
te#t. No0 0e 0ill see ho0 to store obFects or instance o' classes into 'iles.
;&tore
;store is a binary 'ile 'or$at into 0hich you can store al$ost anything. In the co$ing e#a$ple 0e
are going to store 'e0 obFects that belongs to the s:uare class. 3irst 0e 0ill be 0riting a class 'or
s:uare an/ put it into a 'ile calle/ square_class.rb . I' you 'eel laGy copy the content an/ belo0
an/ put it into the 'ileI i' you are a active guy)gal type it all by yoursel'I 'inally you 0ill en/ up 0ith
the sa$e thing.
# square_class.rb
class Square
attr_accessor :side_length
def initialize side_length = 0
@side_length = side_length
end
def area
@side_length * @side_length
end
def perimeter
4 * @side_length
end
end
2nce the s:uare class is rea/yI 0e 0ill use it in t0o /i''erent places. %he 'irst one is co$ing right
145
I Love Ruby 2015 Beta
no0. .e create a progra$ calle/ pstore_write.rb I type the content given belo0 in it
#!/usr/bin/ruby
# pstore_write.rb
require 'square_class.rb'
s1 = Square.new
s1.side_length = 4
s2 = Square.new
s2.side_length = 7
require 'pstore'
store = PStore.new('my_squares')
store.transaction do
store[:square] ||= Array.new
store[:square] << s1
store[:square] << s2
end
.e 0ill 0al! thru the progra$ no0. %he 'irst line require 'square_class.rb' inclu/es the co/e
o' the s:uare class into the progra$I by /oing so 0e can 0rite co/e as though the s:uare class co/e
is type/ into the sa$e 'ileI this re/uces lot o' typing an/ $a!es the co/e loo! neat.
In the ne#t 'our lines sho0n belo0I 0e /eclare t0o s:uares s1 an/ s2I 0e assign s17s side length
to be 4 units an/ that o' s2 to be 7. In the ne#t line 0e inclu/e the co/e nee/e/ to rea/ an/ 0rite the
pstore 'ile 'or$at. .e /on7t nee/ to 0rite that co/e as its alrea/y 0ritten 'or usI all 0e nee/ to /o is
to type require 'pstore' an/ that 0ill inclu/e the co/e.
Ne#t 0e create pstore 'ile using the co$$an/ store = Pstore.new('my_squares') . %his
creates a pstore 'ile calle/ my_squares an/ passes on the 'ile han/le to the variable na$e/ storeI
0ith this variable store 0e can rea/I $anipulate the 'ile my_squares. %o start 0riting into the 'ile
0e nee/ to start a transaction 0hich is acco$plishe/ by the 'ollo0ing bloc! o' co/e
store.transaction do
end
No0 0e can /o transactions 0ith the pstore 'ile 0ithin the do an/ end bloc!. .ithin the bloc! 0e
a// the co/e thats highlighte/ belo0
store.transaction do
store[:square] ||= Array.new
store[:square] << s1
store[:square] << s2
end
%he 'irst line creates a array na$e/ store[:square]I the ||= $eans that i' alrea/y a variable
na$e/ store[:square] e#ists then there is no nee/ to create that variable as its alrea/y there. I'
146
I Love Ruby 2015 Beta
such a variable /oesn7t e#istI the 0e nee/ to create it. B'ter creating an array 0e 0e a// square
obFects ) instance variables s1 an/ s2 into the$ using the 'ollo0ing lines
store[:square] << s1
store[:square] << s2
2nce /one 0e close the transaction using the en/ co$$an/. Kust vie0 your 0or!ing /irectoryI you
0ill be able to see a 'ile na$e/ my_squares in it as sho0n in i$age belo0A
4o no0 0e have success'ully 0ritten into the pstore 'ile na$e/ my_square . Bll 0e nee/ to /o is
rea/ it an/ con'ir$ 0hat 0e have /one is right. %o rea/ the /ata 0ritten into it 0e 0ill 0rite a
progra$ pstore_read.rb .
Create a 'ile na$e/ pstore_read.rb an/ store the progra$ 0ritten belo0 in itI e#ecute an/ 0atch
the output.
#!/usr/bin/ruby
# pstore_read.rb
require 'square_class.rb'
require 'pstore'
store = PStore.new('my_squares')
squares = []
store.transaction do
squares = store[:square]
end
squares.each do |square|
puts "Area = #{square.area}"
147
I Love Ruby 2015 Beta
puts "Perimeter = #{square.perimeter}"
puts "==============================="
end
2utput
Area = 16
Perimeter = 16
===============================
Area = 49
Perimeter = 28
===============================
Bs you see the area an/ peri$eter o' the t0o s:uares are printe/. I' you 'eel I a$ tric!ing you
chec! 'or our sel' 0ith a calculator. .ell to un/erstan/ 0hat happens in pstore_write.rb lets
0al!thru the co/e. In the 'irst t0o lines
require 'square_class.rb'
require 'pstore'
0e inclu/e the co/e in square_class.rb an/ co/e 'or rea/ing an/ 0riting pstore 'iles into our
progra$. Kust li!e the previous e#a$ple 0e open the pstore 'ile my_squares an/ store the 'ile
han/le into the variable na$e/ store in the 'ollo0ing line
store = PStore.new('my_squares')
No0 0e create a array na$e/ s:uares in the 'ollo0ing line
squares = []
.ith the store variable +0hich is the my_squares han/le, 0e open a transaction as sho0n
store.transaction do
squares = store[:square]
end
In the transaction as sho0n in the highlighte/ co/e above 0e trans'er the obFects in variable
store[:squares] to the /eclare/ variable s:uaresI so by this ti$e the variable s:uare $ust contain
the content o' t0o s:uare obFects 0hich 0e /e'ines in previous e#a$ple pstore_write.rb
2nce 0e have ta!en out the values 0e can close the transaction using the end !ey 0or/.
In the 'ollo0ing co/e
squares.each do |square|
puts "Area = #{square.area}"
puts "Perimeter = #{square.perimeter}"
puts "==============================="
end
0e ta!e each each obFect in array squares an/ loa/ it into variable calle/ square an/ 0e print out
the peri$eter an/ area.
14"
I Love Ruby 2015 Beta
<#=L
HBM* stan/s 'or HBM* ain7t MM*. HBM* is a $ar!up language in 0hich 0e can store so$ething
li!e /ata containe/ in Ruby obFects. *ets 0rite a progra$ in 0hich 0e store the /ata o' the s:uare
obFects into HBM* an/ retrieve it. Note that in this progra$ 0e are not saving the output HBM*
/ata into a 'ileI 0hy so@ 4i$ply because I a$ laGy enough. %ype the co/e yaml_write.rb into te#t
e/itor an/ e#ecute it
#!/usr/bin/ruby
# yaml_write.rb
require 'yaml'
require 'square_class'
s = Square.new 17
s1 = Square.new 34
squares = [s, s1]
puts YAML::dump squares
.hen e#ecute/I the progra$ 0ill pro/uce the 'ollo0ing output
---
- !ruby/object:Square
side_length: 17
- !ruby/object:Square
side_length: 34
*ets no0 0al!thru the progra$. %he 'irst t0o lines
require 'yaml'
require 'square_class'
I$ports the co/e nee/e/ to rea/ an/ 0rite into HBM* 'iles. %he ne#t one loa/s the co/e in the
square_calss.rb so that you can progra$ 0ith s:uare obFects.
In the 'ollo0ing lines
s = Square.new 17
s1 = Square.new 34
.e /eclare t0o 4:uare obFects. 2ne has e/ge or si/e length o' 17 units an/ other has si/e length o'
64 units. In the ne#t line
squares = [s, s1]
.e pac! the obFects s an/ s1 into an array calle/ s:uares. In the 'ollo0ing line
puts YAML::dump squares
0e /u$p the 'or$e/ array into HBM* an/ print it onto the screen using puts state$ent.
Copy the stu'' that co$es in as output. It 0ill be use/ to 0rite the ne#t progra$ yaml_read.rb I
type the co/e yaml_read.rb thats sho0n belo0 into the te#t e/itor an/ e#ecute it
14&
I Love Ruby 2015 Beta
# yaml_read.rb
require 'yaml'
require 'square_class'
yaml = <<END
---
- !ruby/object:Square
side_length: 17
- !ruby/object:Square
side_length: 34
END
squares = YAML::load(yaml)
squares.each do |square|
puts "Area = #{square.area}"
puts "Perimeter = #{square.perimeter}"
puts "==============================="
end
*oo! at the output
Area = 289
Perimeter = 68
===============================
Area = 1156
Perimeter = 136
===============================
%he 'irst set o' area an/ peri$eter thats been /isplaye/ is o' 4:uare s an/ secon/ set is o' 4:uare
s1. *ets 0al!thru the co/e un/erstan/ 0hat is happening. Bs usual these linesA
require 'yaml'
require 'square_class'
i$ports the co/e nee/e/ 'or HBM* an/ secon/ one i$ports co/e in square_class.rb 0hich
enables us to /eal 0ith Square obFects. Ne#t 0e have a $ulti line string yaml
yaml = <<END
---
- !ruby/object:Square
side_length: 17
- !ruby/object:Square
side_length: 34
END
%he content o' yaml is enclose/ bet0een <<END an/ END I note that the content o' yaml is the output
o' the previous progra$. Concentrate on this line
squares = YAML::load(yaml)
Its here all $agic happens. Cere the Ruby $agically 'in/s out 'ro$ the HBM* that 0e are loa/ing
/ata store/ in an arrayI this array consists o' t0o obFects o' class Square an/ 'irst one has si/e
length 17 units an/ another o' 64 units. 4o the YAML::load phrases it into array o' 4:uare7s an/
15-
I Love Ruby 2015 Beta
stores it into variable squares.
In the 'ollo0ing co/eA
squares.each do |square|
puts "Area = #{square.area}"
puts "Perimeter = #{square.perimeter}"
puts "==============================="
end
.e loa/ each ele$ent o' array into a variable s:uare an/ print its area an/ peri$eter. I' I have got
$oo/ enough I 0ill be putting e#a$ples o' storing HBM* into 'iles an/ rea/ing it bac!I but 'or no0
'orgive $y laGiness.
151
I Love Ruby 2015 Beta
+roc, ambdas and -locks
I' you have !no0 so$e progra$$ing languagesI you $ight have hear/ about closures. ;roc an/
Jloc!s are si$ilar !in/ o' thing. Hou can ta!e a piece o' co/eI stic! it in bet0een a do endI assign it
to a variable. %his variable contains the piece o' co/e an/ can be $anipulate/ li!e obFectsI passe/
aroun/ an/ blah blah.
;roc is li!e a 'unctionI but its an obFect. *ets see an e#a$ple to !no0 0hat an ;roc is. %ype in the
progra$ proc.rb into the te#t e/itor an/ e#ecute it.
#!/usr/bin/ruby
# proc.rb
say_hello = Proc.new do
puts "Hello world!"
end
say_hello.call
say_hello.call
%his is ho0 the output 0ill loo! li!e
Hello world!
Hello world!
*ets no0 0al!thru the co/e to un/erstan/ it. %a!e a loo! at the 'ollo0ing lines
say_hello = Proc.new do
puts "Hello world!"
end
In this case you are ta!ing a single Ruby state$ent puts Hello World! an/ putting it bet0een
an do an/ end. Hou are $a!ing this co/e a ;roc by appen/ing Proc.new be'ore the do +the start o'
the bloc!,. Hou are assigning the ;roc obFect to a variable na$e/ say_hello. No0 say_hello can
be thought as so$ething that contains a piece o' progra$.
No0 ho0 to call or e#ecute the co/e@ .hen 0e nee/ to call the piece o' ;roc na$e/ say_hello 0e
0rite the 'ollo0ing co$$an/
say_hello.call
In the proc.rb 0e call say_hello t0ice an/ hence 0e get t0o Hello World! as output.
155
I Love Ruby 2015 Beta
,assing parameters
*i!e 'unctions you can pass para$eters to a ;roc. %o see ho0 it 0or!sI type the progra$
proc_hello_you.rb an/ e#ecute it.
#!/usr/bin/ruby
# proc_hello_you.rb
hello_you = Proc.new do |name|
puts "Hello #{name}"
end
hello_you.call "Peter"
hello_you.call "Quater"
.hen e#ecute/ the progra$ gives the 'ollo0ing output.
Hello Peter
Hello Quater
%a!e a loo! at the bol/ ) highlighte/ ) /ar!ene/ co/e in above progra$. Notice that 0e are
capturing so$e thing a'ter the do !ey0or/I by giving do |name| 0e are putting so$ething thats
been passe/ to the ;roc bloc! into the variable name. %his variable can no0 be use/ any0here in the
;roc bloc! to /o so$ething.
In puts "Hello #{name}" I 0e print hello 'ollo0e/ by the passe/ para$eter +name,. 4o 0e have
0ritten a ;roc that can accept so$e thing passe/ to it. Co0 /o 0e call an/ pass so$ething to it@
.ellI notice the state$ents a'ter the endI loo! at the 'irst oneI it says
hello_you.call "Peter"
hello_you.call calls the ;roc co/e to be e#ecute/. %o the ;roc 0e pass the string Peter, this
string gets copie/ in to the variable name in the ;roc an/ hence 0e get the output Hello Peter.
In a si$ilar 0ay 0hen Ruby interpreter co$es across hello_you.call "Quarter" I it prints
Hello Quater.
,assing ,roc to metho#s
Kust li!e any obFectI 0e can pass ;roc to $etho/s. %a!e a loo! at the co/e belo0 +
proc_to_method.rb ,. 4tu/y itI co/e it an/ e#ecute it
#!/usr/bin/ruby
# proc_to_method.rb
# An exampleof passing a proc to method
156
I Love Ruby 2015 Beta
def execute_proc some_proc
some_proc.call
end
say_hello = Proc.new do
puts "Hello world!"
end
execute_proc say_hello
%his is ho0 the output 0ill loo! li!e.
Hello world!
*ets no0 analyGe the co/e o' execute_proc 'unctionI its co/e is as 'ollo0s
def execute_proc some_proc
some_proc.call
end
.e ta!e in one argu$ent calle/ some_proc 0hich 0e assu$e it as ;roc. .e then e#ecute it by using
its o0n call $etho/I i.e. in 'unction 0e Fust call some_proc.call 'or the passe/ ;roc to be
e#ecute/. I' you loo! at ne#t 'e0 lines 0e create a ;roc calle/ say_hello
say_hello = Proc.new do
puts "Hello world!"
end
Bll 0e /o in say_hello ;roc is to print Hello world! Bn/ thats it. No0 0e call the $etho/
execute_proc an/ pass say_hello in the 'ollo0ing piece o' co/e
execute_proc say_hello
Caving passe/ the ;rocI it gets copie/ to some_proc argu$ent an/ 0hen some_proc is e#ecute/I it
prints Hello world! 'aith'ully.
Returning ,roc from function
I ha/ 0ritten earlier that ;roc can be treate/ Fust li!e obFects. In 'act ;roc is an obFect. .e can pass
it to 'unctionsI 0hich 0e have seen in the previous subsectionI no0 0e can see an e#a$ple in 0hich
;roc is returne/ 'ro$ a 'unction. %a!e a goo/ loo! at co/e given belo0 + proc_returning_it.rb ,.
#!/usr/bin/ruby
# proc_returning_it.rb
# Function that returns a proc
def return_proc
Proc.new do |name|
puts "The length of your name is #{name.length}"
end
end
154
I Love Ruby 2015 Beta
name_length = return_proc
name_length.call "A.K.Karthikeyan"
.hen e#ecute/I the progra$ thro0s the 'ollo0ing output
The length of your name is 15
*oo! at the 'unction return_proc . In it 0e create a ne0 ;roc 0hich accepts a para$eter calle/
name. Bssu$ing that name is a stringI 0e si$ply print the length o' it. No0 consi/er the co/e that
co$es a'ter this 'unction 0hich is as 'ollo0sA
name_length = return_proc
name_length.call "A.K.Karthikeyan"
In the 'irst line name_length = return_proc I the name_length gets assigne/ 0ith 0hat ever the
return_proc $etho/ returns. In this case since Proc.new is the last state$ent ) bloc! in the
return_proc $etho/I it returns a ne0 ;roc 0hich gets assigne/ to name_proc. 4o no0 name_proc
can accept a para$eter. Bll 0e /o no0 is to call name_proc 'ollo0e/ by a na$e
name_length.call "A.K.Karthikeyan"
Cence name_length accepts $y na$e as para$eterI calculates its length an/ prints it. Cence this
e#a$ple sho0s that its possible to return a ;roc 'ro$ a 'unction.
,roc an# /rrays
*ets no0 see ho0 ;roc can be use/ 0ith Brrays to 'ilter the$. %a!e a loo! at the progra$
procPan/Parray.rb belo0. In it 0e have /eclare/ a ;roc calle/ getPproc 0hich ta!es one argu$ent
nu$. In the ;roc 0e return nu$ i' its even 0hich is ensure/ by the 'ollo0ing state$ent num unless
num*+ ,, - as highlighte/ belo0. Run the progra$ an/ note the output.
# proc_and_array.rb
get_odd = Proc.new do |num|
num unless num%2 == 0
end
numbers = [1,2,3,4,5,6,7,8]
p numbers.collect(&get_odd)
p numbers.select(&get_odd)
p numbers.map(&get_odd)
2utput
[1, nil, 3, nil, 5, nil, 7, nil]
[1, 3, 5, 7]
[1, nil, 3, nil, 5, nil, 7, nil]
155
I Love Ruby 2015 Beta
No0 lets consi/er the 'ollo0ing three state$ents
p numbers.collect(&get_odd)
p numbers.select(&get_odd)
p numbers.map(&get_odd)
In itI lets Fust consi/er the 'irst line p numbers$collect./get0odd1 I so 0e are having a array o'
nu$bers store/ in available calle/ nu$bers I 0e call collect on nu$bers to it 0e pass the argu$ent
EgetPo// that i/ EWna$ePo'PprocV I this 0ill call the ;roc 'or each an/ every ele$ent in the arrayI
0hat ever thats returne/ by ;roc 0ill be collecte/ into a ne0 array. %he p ensures that the values get
printe/ out 'or us to veri'y.
I' you observe closely both p numbers$collect./get0odd1 an/ p numbers$map./get0odd1 returns
arrays 0ith nil values in the$ 0hereas select 'ilters out the nil7s an/ returns 0hat that re$ains
Lamb#a
*a$b/as are Fust li!e ;rocs. %here is al$ost no /i''erence e#pect t0o. I 0ill e#plain one o' the$
here an/ the other one you $ust 'in/ out yoursel'
56
.
2!ay lets see a s$all progra$ no0
# lambda.rb
print_hello = lambda do
puts "Hello World!"
end
print_hello.call
2utput
Hello World!
%o !no0 ho0 this progra$ 0or!sI rea/ ;rocI *a$b/as an/ Jloc!s .
,assing /rgument to Lamb#a
.ellI e#ecute the progra$ belo0.
# lambda_passing_argment.rb
odd_or_even = lambda do |num|
if num % 2 == 0
puts "#{num} is even"
else
puts "#{num} is odd"
56 2ut o' 0hich I sure /on7t !no0 0hat the other one is
156
I Love Ruby 2015 Beta
end
end
odd_or_even.call 7
odd_or_even.call 8
2utput
7 is odd
8 is even
%o !no0 ho0 it 0or!s chec!out ;assing para$eters section in this chapter.
,roc an# Lamb#as $ith 'unctions
2!ayI so 0hats the /i''erence bet0een ;roc an/ *a$b/a. I rea/ so$e0here that there are t0o $ain
/i''erences bet0een the$I here is oneI the other one I 'orgot. I' you happen to !no0 please $ail it
to 77$in/sOg$ail.co$
4o so in the e#a$ple belo0 callingPprocPan/Pla$b/aPinP'unction.rb 0e have t0o 'unctions
na$ely callingPla$b/a an/ callingPproc I type an/ run this 'ile on your $achine
# calling_proc_and_lambda_in_function.rb
def calling_lambda
puts "Started calling_lambda"
some_lambda = lambda{ return "In Lambda" }
puts some_lambda.call
puts "Finished calling_lambda function"
end
def calling_proc
puts "Started calling_proc"
some_proc = Proc.new { return "In Proc" }
puts some_proc.call
puts "In calling_proc function"
end
calling_lambda
calling_proc
2utput
Started calling_lambda
In Lambda
Finished calling_lambda function
Started calling_proc
Hou 0ill see an output as sho0n above. 4o lets 0al!thru its e#ecution. .hen calling_lambda
'unction is calle/ 'irst the progra$ prints Started calling_lambda by e#ecuting puts [4tarte/
157
I Love Ruby 2015 Beta
callingPla$b/a[ . Ne#t 0e /e'ine a ne0 la$b/a some_lambda an/ call it using the 'ollo0ing lines
o' co/e
some_lambda = lambda{ return "In Lambda" }
puts some_lambda.call
4o 0hen so$ePla$b/a is calle/I it returns >In *a$b/a? 0hich gets printe/ in line puts
some_lambda.call
Bn/ then the 'inal state$ent in the 'unction puts [3inishe/ callingPla$b/a 'unction[ is e#ecute/
giving us the 'ollo0ing output
Started calling_lambda
In Lambda
Finished calling_lambda function
0hen the 'unction 'inishes.
Ne#t 0e call the 'unction calling_proc I 0e e#pect it to behave li!e call_lambdaI but it /oes not<
4o hat happens. Bll 0e !no0 'ro$ the output is the puts [4tarte/ callingPproc[ gets e#ecute/I a'ter
that@
.ell see the ne#t line some_proc = Proc.new { return "In Proc" } I notice that it has got a
return state$ent. .hen a proc is calle/ in a 'unctionI an/ it has a return state$entI it ter$inates that
'unction an/ returns the value o' the return as though the 'unction itsel' is returning it< .hereas
la$b/a /oes not /o it. 1ven i' a la$b/a calle/ in a 'unction an/ the calle/ la$b/a has a return
state$entI it passes the control to ne#t line in the 'unction a'ter it callsI in a proc call its not soI it
si$ply e#its out o' the 'unction returning its o0n value out +as tough the 'unction ha/ returne/ it,.
Lamb#a an# /rrays
1#ecute the progra$ belo0
# lambda_and_array.rb
get_odd = lambda do |num|
num unless num%2 == 0
end
numbers = [1,2,3,4,5,6,7,8]
p numbers.collect(&get_odd)
p numbers.select(&get_odd)
p numbers.map(&get_odd)
2utput
15"
I Love Ruby 2015 Beta
[1, nil, 3, nil, 5, nil, 7, nil]
[1, 3, 5, 7]
[1, nil, 3, nil, 5, nil, 7, nil]
%o !no0 ho0 it 0or!s rea/ ;roc an/ Brrays section in this chapter.
7locks an# 'unctions
.e have seen ;rocs an/ ho0 to pass the$ to $etho/s an/ 'unctions. *ets no0 see about Jloc!s an/
ho0 to pass the$ to 'unctions. %ype the e#a$ple blocks_in_methods.rb an/ e#ecute it
# blocks_in_methods.rb

def some_method *args, &block
p args
block.call
end
some_method 1, 3, 5, 7 do
puts "boom thata"
end
2utput
[1, 3, 5, 7]
boom thata
4o lets no0 see the co/e. In the co/e 0e have /e'ine/ a $etho/ na$e/ some_method in the
'ollo0ing line def some_method *args, &block . Notice that 0e are ta!ing in all argu$ents in
*args an/ 0e have so$ething ne0 calle/ &block that 0ill ta!e in the bloc! o' co/e. Hou can
replace &block 0ith so$e other variable li!e &a or &something I or 0hat ever you pre'er.
Right no0 'orget about 0hats there in the 'unction bo/y. No0 lets see the calling o' the 'unctionI
0hich is sho0n belo0
some_method 1, 3, 5, 7 do
puts "boom thata"
end
4o 0e call so$eP$etho/ an/ pass on argu$ents 1I 6I 5I 7. %his 0ill be collecte/ in *args
57
variable
as an array. No0 see the part that has been bol/I its starts 0ith do an/ en/s 0ith end an/ in bet0een
you can have as $any state$ents as you 0antI in other 0or/s its a bloc! o' co/e. .e Fust have a
state$ent puts "boom thata" ( an/ thats is. %his bloc! o' co/e 0ill go into the &block variable.
No0 note the 'ollo0ing highlighte/ state$ent in some_method
57 4ee 8ariable nu$ber o' argu$ents
15&
I Love Ruby 2015 Beta
def some_method *args, &block
p args
block.call
end
.e call the bloc! using Fust block.call an/ not &block.call I this is i$portant. .hen 0e use
call $etho/ on a bloc! the bloc! gets e#ecute/ an/ 0e get the output >boo$ thata? printe/ out.
No0 lets see another e#a$ple 0here 0e can pass a variable to a bloc!s call. %ype in the e#a$ple
belo0 an/ e#ecute it.
# blocks_in_methods_1.rb
def some_method *args, &block
p args
block.call 7
end
some_method 1, 3, 5, 7 do |number|
puts "boom thata\n" * number
end
2utput
[1, 3, 5, 7]
boom thata
boom thata
boom thata
boom thata
boom thata
boom thata
boom thata
Note that in the so$eP$etho/ /e'initionI 0e have calle/ the Jloc! by using block.call 7 I 0here
/oes the nu$ber 7 go@ .ellI see the 'ollo0ing lines
some_method 1, 3, 5, 7 do |number|
puts "boom thata\n" * number
end
B'ter the /o 0e capture the variable using |number| I so 7 actually gets store/ in number. Insi/e the
bloc! 0e $ultiply "boom thata\n" by number an/ print it out.
16-
I Love Ruby 2015 Beta
Multi *hreading
(sually a progra$ is rea/ line by line an/ is e#ecute/ step by step by the co$puter. Bt any given
point o' ti$e the co$puter e#ecutes only one instruction
5"
. .hen technology beca$e a/vance/ it
beca$e possible to e#ecute $any instructions at onceI this process o' /oing $any things at the sa$e
ti$e is calle/ $ulti processing or parallel processing.
I$agine that you are tas!e/ 0ith eating 5 piGGas. It 0oul/ ta!e a long ti$e 'or you to /o it. I' you
coul/ bring your 'rien/s tooI then you people can share the loa/. I' you can 'or$ a group o' 5-
peopleI eating 5 piGGas beco$es as easy as having a si$ple snac!. %he ti$e re:uire/ to co$plete
the assigne/ tas! gets re/uce/ /rastically.
In your Ruby progra$ing you can $a!e the interpreter e#ecute co/e in a parallel 'ashion. %he
process o' e#ecuting co/e parallel is calle/ $ulti threa/ing. %o sho0 ho0 $ultithrea/ing 0or!s
type the progra$ belo0 in te#t e/itor an/ e#ecute it.
#!/usr/bin/ruby
# multithreading.rb
a = Thread.new{
i = 1;
while i<=10
sleep(1)
puts i
i += 1
end
}
puts "This code comes after thread"
a.join
Cere is the progra$s output
This code comes after thread
1
2
3
4
5
6
7
8
5" Many co$puters no0 have $ore than one processing unit +a!a core, an/ hence true $iltithrea/ing is possible no0.
4ince you are a Ruby progra$$er there is no nee/ 'or you to 0orry about it.
161
I Love Ruby 2015 Beta
9
10
(nli!e other progra$s this progra$ 0ill ta!e 1- secon/s to e#ecute. %a!e a loo! at the progra$ an/
output. %he puts "This code comes after thread" co$es a'ter
a = Thread.new{
i = 1;
while i<=10
sleep(1)
puts i
i += 1
end
}
Het it gets printe/ 'irst. In the state$ents sho0n above 0e create a ne0 threa/ na$e/ a in 0hich 0e
use a while loop to print 'ro$ 1 to 1-. Notice that 0e call a 'unction calle/ sleep(1) 0hich $a!es
the process sleep or re$ain i/le 'or one secon/. B threa/ 0as create/I 0hile the threa/ is runningI
the Ruby interpreter chec!s the $ain threa/ an/ its co$es across puts "This code comes after
thread" an/ hence it prints out the string an/ in parallel as it e#ecutes the ne0 threa/ a create/ by
usI so 1 to 1- gets printe/ as 0e have inserte/ sleep(1) each loop ta!es about 1 secon/ to e#ecute.
4o a'ter 1- secon/s the threa/ a is 'inishe/.
%he a.join tells the Ruby interpreter to 0ait till the threa/ 'inishes e#ecution. 2nce the e#ecution
o' threa/ a is over the state$ents a'ter a.join +i' any, gets e#ecute/. 4ince there is no state$ent
a'ter it the progra$ ter$inates.
Cere is another progra$ that I too! out 'ro$ a 0ebsite
5&
that clearly e#plains about $ultithrea/ing.
othru the progra$ care'ullyI try to un/erstan/ ho0 it 0or!sI I 0ill e#plain it in a $o$ent
#!/usr/bin/ruby
# multithreading_1.rb
def func1
i=0
while i<=2
puts "func1 at: #{Time.now}"
sleep(2)
i=i+1
end
end
5& I' you thin! I have in'ringe/ a copyrightI please in'or$ $e at 77$in/sOg$ail.co$
165
I Love Ruby 2015 Beta
def func2
j=0
while j<=2
puts "func2 at: #{Time.now}"
sleep(1)
j=j+1
end
end
puts "Started At #{Time.now}"
t1=Thread.new{func1()}
t2=Thread.new{func2()}
t1.join
t2.join
puts "End at #{Time.now}"
*oo! at the highlighte/ co/eI 0e have create/ t0o threa/s t1 an/ t2. Insi/e threa/ t1 0e call the
$etho/ func1() an/ in threa/ t2 0e call the $etho/ func2()I by /oing so 0e are e#ecuting both
func1() an/ func2() in parallel. .hen e#ecute/ this is ho0 the output 0ill loo! li!e
6-

Started At Sun Apr 25 09:37:51 +0530 2010
func1 at: Sun Apr 25 09:37:51 +0530 2010
func2 at: Sun Apr 25 09:37:51 +0530 2010
func2 at: Sun Apr 25 09:37:52 +0530 2010
func1 at: Sun Apr 25 09:37:53 +0530 2010
func2 at: Sun Apr 25 09:37:53 +0530 2010
func1 at: Sun Apr 25 09:37:55 +0530 2010
End at Sun Apr 25 09:37:57 +0530 2010
Bs you can see 'ro$ the outputI the outputs printe/ by func1 an/ func2 are interlace/ 0hich
proves that they have been e#ecute/ in parallel. Note that in 'unc1 0e have $a/e the threa/ sleep
'or 5 secon/s by giving sleep(2) an/ in func2 0e have $a/e the threa/ sleep 'or 1 secon/ by
giving sleep(1).
I have $a/e s$all changes in multithreading_1.rb to pro/uce multithreading_2.rb 0hich
gives al$ost the sa$e result o' $ultithrea/ingP1.rbI so here is its co/eA
#!/usr/bin/ruby
# multithreading_2.rb
def func name, delay
i=0
while i<=2
puts "#{name} #{Time.now}"
sleep delay
i=i+1
end
end
puts "Started At #{Time.now}"
6- Hou $ay get a /i''erent output as you $ay be e#ecuting the progra$ at a /i''erent ti$e
166
I Love Ruby 2015 Beta
t1=Thread.new{func "Thread 1:", 2}
t2=Thread.new{func "Thread 2:", 3}
t1.join
t2.join
puts "End at #{Time.now}"
Instea/ o' using t0o 'unctions func1 an/ func2I I have 0ritten a single 'unction calle/ func 0hich
accepts a name an/ ti$e /elay as input. B loop in it prints out the na$e passe/ an/ the ti$e instant
at 0hich the state$ent gets e#ecute/. Notice the highlighte/ state$entsI 0e create t0o threa/s t1
an/ t2. In threa/ t1 I call the 'unction func an/ pass along the na$e Thread 1: an/ tell it to sleep
'or 5 secon/s. In threa/ t2 I call the sa$e func an/ pass na$e as Thread 2: an/ tell it to sleep 'or
6 secon/s in each loop iteration. Bn/ 0hen e#ecute/ the progra$ pro/uces the 'ollo0ing output
Started At Sun Apr 25 09:44:36 +0530 2010
Thread 1: Sun Apr 25 09:44:36 +0530 2010
Thread 2: Sun Apr 25 09:44:36 +0530 2010
Thread 1: Sun Apr 25 09:44:38 +0530 2010
Thread 2: Sun Apr 25 09:44:39 +0530 2010
Thread 1: Sun Apr 25 09:44:40 +0530 2010
Thread 2: Sun Apr 25 09:44:42 +0530 2010
End at Sun Apr 25 09:44:45 +0530 2010
.hich very si$ilar to output pro/uce/ by multithreading_1.rb.
*cope of threa# variables
B threa/ can access variables that are in the $ain process ta!e the 'ollo0ing progra$
+thread_variables.rb, as e#a$ple
#!/usr/bin/ruby
# thread_variables.rb
variable = 0
puts "Before thread variable = #{variable}"
a = Thread.new{
variable = 5
}
a.join
puts "After thread variable = #{variable}"
2utput
Before thread variable = 0
After thread variable = 5
%ype the progra$ an/ run it. It 0ill pro/uce the result sho0n above. Bs you can see 'ro$ the
progra$ 0e initialiGe a variable na$e/ variable to 0 be'ore 0e create the threa/. Insi/e the threa/
0e change the value o' the variable to 5. B'ter the threa/ bloc! 0e print variables value 0hich is
164
I Love Ruby 2015 Beta
no0 5. %his progra$ sho0s us that you can access an/ $anipulate a variable thats been /eclare/ in
the $ain threa/.
*ets no0 see i' a variable create/ insi/e a threa/ can be accesse/ outsi/e the scope o' it@ %ype in
the 'ollo0ing progra$ +thread_variables_1.rb, an/ e#ecute it
#!/usr/bin/ruby
# thread_variables_1.rb
variable = 0
puts "Before thread variable = #{variable}"
a = Thread.new{
variable = 5
thread_variable = 72
puts "Inside thread thread_variable = #{thread_variable}"
}
a.join
puts "=================\nAfter thread\nvariable = #{variable}"
puts "thread_variable = #{thread_variable}"
2utput
Before thread variable = 0
Inside thread thread_variable = 72
=================
After thread
variable = 5
thread_variables_1.rb:13: undefined local variable or method `thread_variable'
for main:Object (NameError)
In the progra$ above 0e see that 0e have create/ a variable na$e/ thread_variable in the threa/
aI no0 0e try to access it in the 'ollo0ing lineA
puts "thread_variable = #{thread_variable}"
Bs you can see the output that the progra$ ) Ruby interpreter spits an error as sho0nA
thread_variables_1.rb:13: undefined local variable or method `thread_variable'
for main:Object (NameError)
It says there is an un/e'ine/ local variable or $etho/ na$e/ thread_variable. %his $eans that the
state$ent in $ain threa/ is unable to access variable /eclare/ in the threa/ a. 4o 'ro$ the previous
t0o e#a$ples its clear that a threa/ can access a variable /eclare/ in the $ain threa/ 0hereas a
variable /eclare/ in the threa/7s scope cannot be accesse/ by state$ent in $ain scope.
Threa# &xclusion
*ets say that there are t0o threa/s that share a sa$e resourceI let the resource be a variable. *ets
say that the 'irst threa/ $o/i'ies the variableI 0hile its $o/i'ying the secon/ threa/ tries to access
165
I Love Ruby 2015 Beta
the variableI 0hat 0ill happen@ %he ans0er is si$ple an/ straight 'or0ar/I though the progra$
appears to run 0ithout errors you $ay not get the /esire/ result. %his concept is /i''icult to graspI
let $e try to e#plain it 0ith an e#a$ple. %ype an/ e#ecute thread_exclusion.rb
#!/usr/bin/ruby
# thread_exclusion.rb
x = y = 0
diff = 0
Thread.new {
loop do
x+=1
y+=1
end
}
Thread.new {
loop do
diff += (x-y).abs
end
}
sleep(1) # Here main thread is put to sleep
puts "difference = #{diff}"
2utput
difference = 127524
Rea/ the progra$ care'ully. Je'ore 0e start any threa/I 0e have three variables x, y an/ diff that
are assigne/ to value 0. %hen in the 'irst threa/ 0e start a loop in 0hich 0e incre$ent the value o' x
an/ y. In another threa/ 0e 'in/ the /i''erence bet0een x an/ y an/ save it in a variable calle/
diff. In the 'irst threa/ x an/ y are incre$ente/ si$ultaneouslyI hence the state$ent diff += (x-
y).abs shoul/ a// nothing to variable diff as x an/ y are al0ays e:ual an/ their /i''erence shoul/
al0ays be GeroI hence the absolute value o' their /i''erence 0ill also be Gero all the ti$e.
In this progra$ 0e /on7t 0ait 'or the threa/s to Foin +as they contain in'inite loop,I 0e $a!e the
$ain loop sleep 'or one secon/ using the co$$an/ sleep+1, an/ then 0e print the value o' diff in
the 'ollo0ing state$ent
puts "difference = #{diff}"
2ne 0oul/ e#pect the value to be Gero but 0e got it as 157554I in your co$puter the value coul/ be
/i''erent as it /epen/s on $achine spee/I 0hat process its running an/ blah blah. Jut the $oral is
diff that shoul/ be Gero has so$e valueI ho0 co$e@
.e see in the 'irst loop that x is incre$ente/ an/ then y is incre$ente/I lets say that at an instant x
value is 5 an/ y value is 4. x ha/ Fust got incre$ente/ in the state$ent x += 1 an/ no0 the Ruby
interpreter is about to rea/ an/ e#ecute y +=1 0hich 0ill $a!e y 'ro$ 4 to 5. Bt this stage the
secon/ threa/ is e#ecute/ by the co$puter. 4o in the state$ent
166
I Love Ruby 2015 Beta
diff += (x-y).abs
putting x as 5 an/ y as 4 0ill $ean that diff 0ill get incre$ente/ by 1. In si$ilar 'ashion 0hile the
$ain loop sleeps 'or one secon/I the t0o threa/ 0e have create/ 0oul/ have 'inishe/ thousan/s o'
loop cyclesI hence the value o' diff 0oul/ increase/ signi'icantly. %hats 0hy 0e get the value o'
diff as a large nu$ber.
.ellI 0e have seen ho0 not to 0rite the progra$ in a 0rong 0ayI lets no0 see ho0 to 0rite it in the
right 0ay. 2ur tas! no0 is to synchroniGe the t0o threa/s that 0e have create/ so that one threa/
/oes not access other threa/s resources 0hen the other is in $i//le o' so$e busy process. %o /o so
0e 0ill be using a thing calle/ Mute# 0hich $eans Mutual 1#clusion. %ype the 'ollo0ing progra$
thread_exclusion_1.rb in te#t e/itor an/ e#ecute it
#!/usr/bin/ruby
# thread_exclusion_1.rb
require 'thread'
mutex = Mutex.new
x = y = 0
diff = 0
Thread.new {
loop do
mutex.synchronize do
x+=1
y+=1
end
end
}
Thread.new {
loop do
mutex.synchronize do
diff += (x-y).abs
end
end
}
sleep(1) # Here main thread is put to sleep
puts "difference = #{diff}"
2utput
difference = 0
Bs you see aboveI 0e get output as difference = 0 I 0hich $eans that diff variable is Gero.
4o$e thing prevente/ the secon/ threa/ 'ro$ accessing x an/ y in the 'irst threa/ 0hile the 'irst one
0as busy. 4o$e ho0 the t0o threa/s have learne/ to share their resources. 4tu/y the co/e care'ullyI
0e see that 0e have inclu/e/ a threa/ pac!age by typing
require 'thread'
167
I Love Ruby 2015 Beta
Ne#t 0e have create/ a Mute# variable na$e/ mutex using the 'ollo0ing co$$an/
mutex = Mutex.new
.ell then the co/e is as usual e#cept insi/e the threa/s. *ets loo! into the 'irst threa/
Thread.new {
loop do
mutex.synchronize do
x+=1
y+=1
end
end
}
.e see that the state$ents x += 1 an/ y += 1 are enclose/ in mutex.synchronize bloc!. In
si$ilar 0ay the co/e co$puting the /i''erence o' x an/ y is also enclose/ in mutex.synchronize
bloc! as sho0nA
Thread.new {
loop do
mutex.synchronize do
diff += (x-y).abs
end
end
}
Jy /oing so that 0e tell the co$puter that there is a co$$on resource is share/ by these t0o
threa/s an/ one threa/ can access the resource only i' other releases it. Jy /oing soI 0hen ever the
/i''erence +diff, is calculate/ in diff += (x-y).abs I the value o' x an/ y 0ill al0ays be e:ualI
hence diff never gets incre$ente/ an/ stays at Gero 'orever.
Dea#locks
Cave you ever stoo/ in a :ueueIor 0aite/ 'or so$ething. 2ne place 0e all 0ait is in airport 'or our
luggages to be scanne/ an/ cleare/. *ets say that the luggage scanning $achine gets out o' or/er
an/ you are stuc! in airport. Hou are e#pecte/ to atten/ an i$portant co$pany $eeting an/ you
have the !ey presentation an/ you $ust give an i$portant tal!. 4ince your baggage scanner 'aile/
the resource nee/e/ by you is not available to youI an/ you have the !ey !no0le/ge to tal! in the
$eeting an/ hence the $eeting gets scre0e/ up. 2ne a$ong the $eeting $ight have pro$ise/ to
ta!e his 'a$ily to a $ovieI he $ight return late a'ter the /elaye/ $eeting an/ hence all scre0 up.
I$agine that the baggage scannerI youI a person 0ho $ust listen to your $eeting are threa/s o' a
Ruby progra$. 4ince the baggage scanner 0ont release a resource +your bag, your process gets
16"
I Love Ruby 2015 Beta
/elaye/ an/ since you are /elaye/ $any other processes that /epen/s on you are /elaye/. %his
situation is calle/ /ea/ loc!. It happens in Ruby progra$s too.
.hen ever situation li!e this arises people 0ait rather than to rush 'or0ar/. Hou 0ait 'or your bag to
be release/I your co$pany 0aits 'or your arrival an/ the $ans 'a$ily 0aits 'or hi$ to ta!e the$ to
$ovie. Instea/ o' 0aiting i' people rush up it 0ill result in chaos.
Ruby has a $echanis$ to avoi/ this chaos an/ to han/le this /ea/loc!. .e use a thing calle/
con/ition variable. %a!e a loo! at the progra$ + thread_condition_variable.rb , belo0I type it
an/ e#ecute it.
#!/usr/bin/ruby
# thread_condition_variable.rb
require 'thread'
mutex = Mutex.new
c = ConditionVariable.new
a = Thread.new {
mutex.synchronize {
puts "Thread a now waits for signal from thread b"
c.wait(mutex)
puts "a now has the power to use the resource"
}
}
puts "(Now in thread b....)"
b = Thread.new {
mutex.synchronize {
puts "Thread b is using a resource needed by a, once its done it will
signal to a"
sleep(4)
c.signal
puts "b Signaled to a to acquire resource"
}
}
a.join
b.join
2utput
Thread a now waits for signal from thread b
(Now in thread b....)
Thread b is using a resource needed by a, once its done it will signal to a
b Signaled to a to acquire resource
a now has the power to use the resource
4tu/y the progra$ an/ output care'ully. *oo! at the output. 3irst the state$ent in %hrea/ a gets
16&
I Love Ruby 2015 Beta
e#ecute/ an/ it prints that threa/ a is 0aiting 'or %hrea/ b to signal it to continue. 4ee in threa/ a
0e have 0ritten the co/e c.wait(mutex) I 0here c is the Con/ition 8ariable /eclare/ in the co/e
as 'ollo0sA
c = ConditionVariable.new
4ee the highlighte/ co/e in thread_condition_variable.rb . 4o no0 threa/ a 0aitsI no0 the
e#ecution 'ocuse/ on threa/ b 0hen the 'ollo0ing line is encountere/ in %hrea/ b
puts "Thread b is using a resource needed by a, once its done it will signal to
a"
it prints out that threa/ b is using so$e resource nee/e/ by aI ne#t threa/ b sleeps 'or 4 secon/s
because 0e have given sleep(4) in it. %his sleep state$ent can be avoi/e/I I have given a sleep
because 0hile the rea/er e#ecutes the progra$ it $a!e hi$ 0ait an/ gives a 'eel that ho0 really
con/ition variable 0or!s.
%hen a'ter 4 secon/sI %hrea/ b signals to %hrea/ a I its 0ait can en/ using the state$ent c.signal .
No0 %hrea/ a receives the signal an/ can e#ecute its rest o' its state$entsI i.e a'ter c.signal
%hrea/ a an/ %hrea/ b can e#ecute si$ultaneously.
Threa# &xception
.hen ever there is an e#ception 0hen the progra$ is runningI an/ i' the e#ception isn7t han/le/
properly the progra$ ter$inates. *ets see 0hat happens 0hen there is a e#ception in a threa/. %ype
the co/e thread_exception_true.rb in te#t e/itor an/ e#ecute it.
#!/usr/bin/ruby
# thread_exception_true.rb
t = Thread.new do
i = 5
while i >= -1
sleep(1)
puts 25 / i
i -= 1
end
end
t.abort_on_exception = true
sleep(10)
puts "Program completed"
2utput
5
6
17-
I Love Ruby 2015 Beta
8
12
25
thread_exception_true.rb:8:in `/': divided by 0 (ZeroDivisionError)
from thread_exception_true.rb:8
from thread_exception_true.rb:4:in `initialize'
from thread_exception_true.rb:4:in `new'
from thread_exception_true.rb:4
Notice in the progra$ 0e create a threa/ na$e/ tI an/ i' you are :uiet alert 0e haven7t got t.join
in the progra$. Instea/ o' 0aiting 'or the threa/ to Foin 0e 0ait long enough 'or the threa/ to
co$plete. 3or the threa/ to co$plete 0e 0ait 'or 1- secon/s by using the state$ent sleep(10).
Notice the line t.abort_on_exception = true 0here 0e set that i' there raises an e#ception in
the threa/ tI the progra$ $ust abort. *ets no0 analyGe 0hats in threa/ t. %hrea/ t contains the
'ollo0ing co/e
t = Thread.new do
i = 5
while i >= -1
sleep(1)
puts 25 / i
i -= 1
end
end
Notice that 0e /ivi/e 55 by i an/ put out the result o' the /ivision. i is /ecre$ente/ by 1 in each
loop iterationI so 0hen i beco$es Gero an/ 0hen 55 is /ivi/e/ by itI it 0ill raise an e#ception. 4o at
the si#th iteration o' the loopI 55 is /ivi/e/ by GeroI an e#ception is raise/ an/ the progra$ stops by
spiting out the 'ollo0ing
thread_exception_true.rb:8:in `/': divided by 0 (ZeroDivisionError)
from thread_exception_true.rb:8
from thread_exception_true.rb:4:in `initialize'
from thread_exception_true.rb:4:in `new'
from thread_exception_true.rb:4
%his happens because 0e have set t.abort_on_exception to true +see the highlighte/ co/e,.
.hat happens i' 0e set it as false. %a!e a loo! at the progra$ thread_exception_false.rb. In
the progra$ 0e have set t.abort_on_exception as false. %ype the progra$ in te#t e/itor an/ run
it
#!/usr/bin/ruby
# thread_exception_false.rb
171
I Love Ruby 2015 Beta
t = Thread.new do
i = 5
while i >= -1
sleep(1)
puts 25 / i
i -= 1
end
end
t.abort_on_exception = false
sleep(10)
puts "Program completed"
%a!e a loo! at output
5
6
8
12
25
Program completed
Bs you can see 'ro$ the output there is no trace o' e#ception occurrence
61
. %he co/e that co$es
a'ter threa/ t gets e#ecute/ an/ 0e get output that says ;rogra$ Co$plete/. %his is because 0e
have set abort_on_exception to be false.
Hou can see 'ro$ the last t0o progra$s that 0e haven7t use/ t.join I instea/ 0e have 0aite/ long
enough 'or the threa/ to ter$inate. %his is so because once 0e Foin threa/ +that causes, e#ception
0ith the parent +in this case the $ain, threa/I the e#ception that arises in the chil/ threa/ gets
propagate/ to the parent ) 0aiting threa/ so abort_on_exception has no e''ect even it set to true
or false. 4o 0hen ever e#ception raises it gets re'lecte/ on our ter$inal.
Threa# )lass %etho#s
%here are certain threa/ $etho/s 0hich you can use to $anipulate the properties o' the threa/.
%hose are liste/ belo0. I' you can7t un/erstan/ a bit o' itI never 0orry.
$no8 =etho% 7hat it %oe&

Thread.abort_on_exceptio
n
Return& the &tatu& of the g*oba* abort on exception con%ition8
,he %efau*t i& false8 7hen &et to true /i** cau&e a** threa%& to
abort (the proce&& /i** e:it(0)) if an e:ception i& rai&e% in any
threa%8

Thread.abort_on_exceptio
n=
7hen &et to true a** threa%& /i** abort if an e:ception i& rai&e%8
Return& the ne/ &tate8
61 1#ception has occurre/ but its not reporte/ ) aborte/.
175
I Love Ruby 2015 Beta

Thread.critical
Return& the &tatu& of the g*oba* thread critical con%ition8

Thread.critical=
$et& the &tatu& of the g*oba* thread critical con%ition an%
return& it8 7hen &et to true prohibit& &che%u*ing of any
e:i&ting threa%8 )oe& not b*oc" ne/ threa%& fro( being
create% an% run8 Certain threa% operation& (&uch a& &topping
or "i**ing a threa% &*eeping in the current threa% an% rai&ing
an e:ception) (ay cau&e a threa% to be &che%u*e% even /hen
in a critica* &ection8

Thread.current
Return& the current*y e:ecuting threa%8

Thread.exit
,er(inate& the current*y running threa% an% &che%u*e&
another threa% to be run8 If thi& threa% i& a*rea%y (ar"e% to be
"i**e% exit return& the Thread. If thi& i& the (ain threa% or the
*a&t threa% e:it the proce&&8

Thread.fork { block }
$ynony( for ,hrea%8ne/

Thread.kill( aThread )
Cau&e& the given aThread to e:it

Thread.list
Return& an array of Thread ob>ect& for a** threa%& that are
either runnab*e or &toppe%8 ,hrea%8

Thread.main
Return& the (ain threa% for the proce&&8

Thread.new( [ arg ]* )
{| args | block }
Create& a ne/ threa% to e:ecute the in&truction& given in
b*oc" an% begin& running it8 #ny argu(ent& pa&&e% to
Thread.new are pa&&e% into the b*oc"8

Thread.pass
Invo"e& the threa% &che%u*er to pa&& e:ecution to another
threa%8

Thread.start( [ args ]
* ) {| args | block }
Ba&ica**y the &a(e a& Thread.new 8 .o/ever if c*a&& Thread i&
&ubc*a&&e% then ca**ing start in that &ubc*a&& /i** not invo"e
the &ubc*a&&'& initialize (etho%8

Thread.stop
$top& e:ecution of the current threa% putting it into a sleep
&tate an% &che%u*e& e:ecution of another threa%8 Re&et& the
critical con%ition to fa*&e8
Threa# Instance %etho#s
4ince everything in Ruby is an obFectI ia threa/ too is an obFect. *i!e $any obFectsI threa/s have
'unctions or $etho/s 0hich can be calle/ to access or set a property in threa/. 4o$e o' the
'unctions an/ their uses are liste/ belo0 +thr is an instance variable o' the %hrea/ class, A
$no8 =etho% 7hat it %oe&
1
thr.alive?
,hi& (etho% return& true if the threa% i& a*ive or &*eeping8 If
the threa% ha& been ter(inate% it return& fa*&e8
2
thr.exit
!i**& or e:it& the threa%
176
I Love Ruby 2015 Beta
3
thr.join
,hi& proce&& /ait& for the threa% to >oin /ith the proce&& or
threa% that create% the chi*% threa%8 ?nce the chi*% threa% ha&
fini&he% e:ecution the (ain threa% e:ecute& the &tate(ent
after thr8>oin
@
thr.kill
$a(e a% thr8e:it
5
thr.priority
Aet& the priority of the threa%8
B
thr.priority=
$et& the priority of the threa%8 .igher the priority higher
preference /i** be given to the threa% having higher nu(ber8
C
thr.raise( anException )
Rai&e& an e:ception fro( thr8 ,he ca**er %oe& not have to be
thr8
D
thr.run
7a"e& up thr (a"ing it e*igib*e for &che%u*ing8 If not in a
critica* &ection then invo"e& the &che%u*er8
10
thr.wakeup
=ar"& thr a& e*igib*e for &che%u*ing it (ay &ti** re(ain b*oc"e%
on IE? ho/ever8
11
thr.status
Return& the &tatu& of thrF sleep if thr i& &*eeping or /aiting on
IE? run if thr i& e:ecuting fa*&e if thr ter(inate% nor(a**y an%
nil if thr ter(inate% /ith an e:ception8
12
thr.stop?
7ait& for thr to co(p*ete via Thread.join an% return& it& va*ue8
13
thr[ aSymbol ]
#ttribute Reference - Return& the va*ue of a threa%-*oca*
variab*e u&ing either a &y(bo* or a aSymbol na(e8 If the
&pecifie% variab*e %oe& not e:i&t return& nil8
1@
thr[ aSymbol ] =
#ttribute #&&ign(ent - $et& or create& the va*ue of a threa%-
*oca* variab*e u&ing either a &y(bo* or a &tring8
15
thr.abort_on_exception
Return& the &tatu& of the abort on exception con%ition for thr8
,he %efau*t i& false8
1B
thr.abort_on_exception=
7hen &et to true cau&e& a** threa%& (inc*u%ing the (ain
progra() to abort if an e:ception i& rai&e% in thr8 ,he proce&&
/i** effective*y exit(0)8
174
I Love Ruby 2015 Beta
.'ception "andling
In In/iaI la0 /oes not apply to the rich an/ political class. %hey can /o any thing an/ get a0ay 'ro$
it. %hough our la0s says bribes are illegalI there is al$ost no In/ian 0ho hasn7t pai/ bribe. 3ree
speech an/ bloggers are ruthlessly targete/. 1verything is a e#ception here an/ la0 is $ostly Fus in!
on paper. .e $ay not be able to /o anything about the corrupt rich an/ politicianI but 0e can
han/le e#ceptions in Ruby< .ellI let $e e#plain to ho0 to han/le e#ceptions in Ruby progra$$ing
*ets 0rite a progra$ calle/ division_exception.rb 0hich 0ill brea! /ue to /ivision by Gero.
2pen your te#t e/itorI type the given co/e belop0 in it an/ run it
# division_exception.rb
puts 67 / 0
2utput
division_exception.rb:3:in `/': divided by 0 (ZeroDivisionError)
from division_exception.rb:3:in `<main>'
Bs you seeI you get a e#ception as output. 4ee that the constant ZeroDivisionError is in bol/. .e
0ill see the use o' in Fust a 'e0 e#a$ples. 4o 0hen the Ruby interpreter notices that it can7t han/le
so$ethingI t raises an e#ception.
No0 it 0ill not be great i' 0e thro0 out the e#ception tot our client 0ho has pai/ $illions 'or us to
pro/uce a piece o' progra$. .e 0oul/ rather try to put out so$ething thats un/erstan/able to the$.
4o in the e#a$ple sho0n belo0 rescue.rb 0e see ho0 to han/le this e#ception. %ype the progra$
belo0 in an te#t e/itor an/ run it
# rescue.rb
begin
puts 67 / 0
rescue
puts "We are unable to proceed due to unavoidable reasons :("
end
2utput
We are unable to proceed due to unavoidable reasons :(
175
I Love Ruby 2015 Beta
Bs you can see instea/ o' the nasty ZeroDivisionError output I you see a 'rien/ly $essage that its
unable to procee/ /ue to unavoi/able reasons. %he tric! is i' you thin! so$e e#ception can occur in
co/e surroun/ it 0ith begin an/ en/ bloc!s as sho0n belo0
begin
puts 67 / 0
end
%hen the co/e that nee/s to be han/le/ 0hen there is a e#ception is put a'ter a !ey 0or/ calle/
rescue as sho0n
begin
puts 67 / 0
rescue
puts "We are unable to proceed due to unavoidable reasons :("
end
0hen there is an e#ceptionI the co/e belo0 rescue starts e#ecutingI. %hats it< .ell you no0 ho0 to
/eal 0ith e#ceptions in a cru/e 0ay.
*et no0 see a re'ine/ 0ay to catch or rescue 'ro$ an e#ception. 4ee the co/e belo0 rescue_1.rbI
type it an/ e#ecute it
# rescue_1.rb
begin
puts 67 / 0
rescue ZeroDivisionError
puts "Oh nooo! boom thata has cursed us!!!!!"
end
2utput
Oh nooo! boom thata has cursed us!!!!!
Hou see the out put that you are curse/ by Joo$ %hata +o/ o' o/s,. Don7t 0orry $uch about
thatI Joo$ %hata is $y 'rien/ an/ 0ill tal! to hi$ to reverse it. 4ee the highlighte/ ) bol/ co/e.
Cere 0e have put the co/e li!e this rescue ZeroDivisionError in it 0e are telling it to rescue i'
an/ only Gero /ivision error occurs. I' so$e other things happenI li!e i' you are in ;a!istan an/ a
$issile 'ro$ (.4 /rone stri!es youI it 0on7t be the ruby interpreter but possibly Joo$ thata $ust
rescue you.
*ets say that you 0ant to print out an e#ception. 4ay 'or your /ebugging purpose or so$ething. 4o
176
I Love Ruby 2015 Beta
ho0 to /o that. %he 'ollo0ing progra$ sho0s you that. %ype the progra$
printing_exception.rb an/ run it
# printing_exception.rb
begin
puts 67 / 0
rescue => e
puts "The following exception has occured:"
p e
end
2utput
The following exception has occured:
#<ZeroDivisionError: divided by 0>
4o as you can seeI you can print an e#ception. Kust note the highlighte/ line p e I its there 0here
0e are printing an e#ception. e is the e#ception obFect an/ p is !in/ o' short 'or$ 'or puts
65
. .ish
you have notice/ that this co/e rescue => e pushe/ the e#ception into an variable e. %hats ho0 e
hol/s the e#ception.
In the ne#t e#a$pleI 0e are going to see ho0 to bac! trace an e#ception. %hat is e#ception thats
been thro0n in real 0orl/ progra$s coul/ be burie/ un/er $ultiple levels. %o 'in/ that out you
better nee/ to bac! trace it. %ype the progra$ belo0 into te#t e/itor an/ run it.
# backtracing_exception.rb
begin
puts 67 / 0
rescue => e
p e.backtrace
end
2utput
["backtracing_exception.rb:4:in `/'", "backtracing_exception.rb:4:in `<main>'"]

%h co/e 0here the bac! tracing occurs is highlighte/ i' you can see. .e are printing it using p
e.backtrace. I' you can notice the outputI it sho0s that e#ception has occurre/ in line 4I i' you
have line nu$bers /isplaye/ in your te#t e/itor you can i/enti'y the line i$$e/iately an/ /ebug it.
Ne#t +the secon/ piece o' output, it says the e#ception has occurre/ in $ain. Hou $ay 0on/er 0hat
is $ain@ Its the progra$ in your te#t e/itor that is 'irst run is calle/ the $ain.
65 actually not really
177
I Love Ruby 2015 Beta
&xception an# Threa#s
.e have seen e#ception in or/inary progra$s that are single threa/e/I but Ruby is a $ulti threa/e/
progra$$ing language. *ets see ho0 ho0 e#ceptions an/ threa/s $i# an/ behave. %ype the
progra$ thread_exception_true.rb an/ run it
#!/usr/bin/ruby
# thread_exception_true.rb
t = Thread.new do
i = 5
while i >= -1
sleep(1)
puts 25 / i
i -= 1
end
end
t.abort_on_exception = true
sleep(10)
puts "Program completed"
2utput
5
6
8
12
25
thread_exception_true.rb:8:in `/': divided by 0 (ZeroDivisionError)
from thread_exception_true.rb:8:in `block in <main>'
Bs you see the progra$ thro0s out an ZeroDivisionError e#ceptionI this happens in while loop
0hen the value o' i beco$es Gero an/ 55 nee/s to be /ivi/e/ by it. Notice the line in bol/
t.abort_on_exception = true I here 0e tell the progra$ to abort or stop 0hen there is an
e#ception. %his hence 0ill stop all other threa/s i' they are running in parallel. *ets say that you
have a $ultithrea/e/ progra$ 0here it is a $ust that all threa/s $ust run 0ithout an e#ceptionI an/
threa/s are !in/ o' /epen/ent on each otherI then its better to 0rite co/e in such a 0ay that the
progra$ aborts 0hen e#ception is raise/ in one o' the threa/s.
*ets say that a progra$ 0e 0rite is such that e#ception on a threa/ can be ignore/ an/ other threa/s
can run $errily then see the highlighte/ line in progra$ belo0 thread_exception_false.rb.
Cere 0e speci'y t.abort_on_exception = false I so the progra$ runsI 0hen an e#ception
occursI the particular threa/ stops runningI 0hereas other threa/s continue to run as though nothing
happene/.
17"
I Love Ruby 2015 Beta
#!/usr/bin/ruby
# thread_exception_false.rb
t = Thread.new do
i = 5
while i >= -1
sleep(1)
puts 25 / i
i -= 1
end
end
t.abort_on_exception = false
sleep(10)
puts "Program completed"
2utput
5
6
8
12
25
Program completed
Raising &xpceptions
.e have seen ho0 to catch an e#ception an/ /eal 0ith it. Jut 0hat i' 0e 0ant to raise our o0n
e#ceptions@ %ype the progra$ raise.rb in te#t e/itor an/ e#ecute it.
# raise.rb
puts "Enter a number 1 - 10:"
num = gets.to_i
raise "You did not enter right num" unless (1..10).include? Num
2utput
Enter a number 1 - 10:
25
raise.rb:5:in `<main>': You did not enter right num (RuntimeError)
Bs you can see 'ro$ the output the progra$ raises e#ception i' any nu$ber entere/ /oes not lie
'ro$ 1 to 1-. 4ee the highlighte/ piece o' co/e raise "You did not enter right num" I thats
all it ta!es to raise an e#ception in Ruby. %he !ey 0or/ raise 'ollo0e/ by an obFect. In this case 0e
put out a stringI but it 0oul/ be nice i' 0e put out a constant 0hich is the nor$ o' raising
e#ceptions. %he progra$ belo0 raise02$rb sho0s ho0 to /eal 0ith your o0n e#ceptions 0hich is
no /i''erent 'ro$ rescue progra$s you have 0ritten be'ore.
17&
I Love Ruby 2015 Beta
# raise_1.rb
def number_thing(num)
raise "You did not enter right num" unless (1..10).include? num
puts "You entered #{num} :)"
end
puts "Enter a number 1 - 10:"
num = gets.to_i
begin
number_thing(num)
rescue
puts "You may have not entered number in valid range"
end
2utput
Enter a number 1 - 10:
25
You may have not entered number in valid range
1"-
I Love Ruby 2015 Beta
Regular .'pressions
Hou are 0ith your girl 'rien/ in a Fe0el shopI she chooses one o' the 'inest /ia$on/ rings an/ gives
you %CB% *22K... 4ure you !no0 that you 0ill 'all into $ore cre/it car/ /ebt. Hou are in another
/ay an/ having a tal! 0ith your boss to get $ore salary 0hen he stares at you. %CB% *22K. Hou
no0 !no0 that 0hat ever thing you say that you /i/ goo/ to the co$panyI it 0ill be ignore/ an/
0oul/ be 'utile. .e all see 'or e#pressions in others 'ace an/ 0e try to pre/ict 0hat ne#t 'ro$ it.
*ets say that you are on chat 0ith your 'rien/ an/ he types AL, I you !no0 he is happyI this AL+ $eans
he7s sa/. 4o its :uiet evi/ent that 0e can see e#pressions even in te#tual /ata Fust as 0e see in each
others 'ace. Ruby7s regular e#pression provi/es you 0ith a 0ay to /etect these patterns in a given
te#t an/ e#tract the$ i' you 0ish. %his can be use/ 'or so$e thing goo/. 4o this chapter is about
that. .hat Ruby /oes not /o is to tell you ho0 to i$press your girl 0ithout getting into /ebt AL+ .
.ish to report this as a bug an/ hope they 0ill 'i# it in ruby 5.# NL,
4o 'ire up your irbI lets begin
)reating a empty regexp
2!ay 0e 0ill try to create a e$pty regular e#pression. In your ter$inal type irb -simple-
prompt an/ in it type the 'ollo0ing +0ithout the >> I 0hich is irb7s pro$pt,
>> //.class
=> Regexp
Hou see //.class is Rege#p. In other 0or/s any thing bet0een those / an/ / is a rege#p
66
. Rege#p
is not a stringI but it /enotes a pattern. Bny string can $atch or $ay not $atch the pattern.
Detecting ,atterns
*ets no0 see ho0 to /etect patterns in a regular e#pressions. *ets say that you 0ant to see that abc
is in a given string. Kust punch the co/e belo0
>> /abc/.match "This string contains abc"
=> #<MatchData "abc">
abc is present in the given string hence you get a $atch. In the co/e snippet belo0I there is no abc
in the string an/ hence it returns nil.
66 .ill be using rege#p instea/ o' Regular e#pression 'ro$ no on
1"1
I Love Ruby 2015 Beta
>> /abc/.match "This string contains cba"
=> nil
Hou can use the $atch 'unction on a rege#p as sho0n above or u can use it on a stringI as sho0n
belo0. Joth gives you the sa$e result.
>> "This string contains abc".match(/abc/)
=> #<MatchData "abc">
Bnother 0ay o' $atching is sho0n belo0. Hou can use the =~ operator.
>> "This string contains abc" =~ /abc/
=> 21
>> /abc/ =~ "This string doesn't have abc"
=> 25
%he =~ tells you the location 0here the 'irst occurrence o' the $atch occurs.
Things to remember
%here are so$e things you nee/ to re$e$berI or at least re'er 'ro$ ti$e to ti$e. %hose are
$entione/ in table belo0
64
.
3hing 4hat it means
. Bny single character
\w Bny 0or/ character +letterI nu$berI un/erscore,
\W Bny nonL0or/ character
\d Bny /igit
\D Bny nonL/igit
\s Bny 0hitespace character
\S Bny nonL0hitespace character
\b Bny 0or/ boun/ary character
^ 4tart o' line
$ 1n/ o' line
\A 4tart o' string
\z 1n/ o' string
[abc] B single character o'A aI b or c
[^abc] Bny single character e#ceptA aI bI or c
[a-z] Bny single character in the range aLG
[a-zA-Z] Bny single character in the range aLG or BLU
(...) Capture everything enclose/
64 I got this list 'ro$ httpA))rubular.co$)
1"5
I Love Ruby 2015 Beta
3hing 4hat it means
(a|b) a or b
a? Uero or one o' a
a* Uero or $ore o' a
a+ 2ne or $ore o' a
a{3} 1#actly 6 o' a
a{3,} 6 or $ore o' a
a{3,6} Jet0een 6 an/ 6 o' a
i case insensitive
$a!e /ot $atch ne0lines
! ignore 0hitespace in rege#
" per'or$ _Y...Z substitutions only once
Don7t panic i' you /on7t un/erstan/ thisI as I $ysel' !no0 nothing o' it.
The #ot
%he /ot in a regular e#pression $atches any thingI. %o illustrate it lets try so$e e#a$ples in our irb
>> /.at/.match "There is rat in my house"
=> #<MatchData "rat">
in the above co/e snippetI 0e try to $atch /.at/ 0ith a stringI an/ it $atches. %he reasonI the
string contains a 0or/ calle/ rat. %a!e a loo! at another t0o e#a$ples belo0I the /.at/ $atches
cat an/ bat 0ithout any 'uss.
>> /.at/.match "There is cat in my house"
=> #<MatchData "cat">
>> /.at/.match "There is bat in my house"
=> #<MatchData "bat">
Its not a rule that the /ot shoul/ be at the start o' the 0or/ or so$ethingI it can be any 0here. B
rege#p /f.y/ coul/ co$'ortably $atch fry an/ fly. Bh< I 0ish I have a chic!en 'ry no0. Bny 0ay
chic!ens /o 'ly.
)haracter classes
*ets say tat 0e 0ant to 'in/ that 0eather there is a bat or a rat or a cat is present in a given string. I'
there I 0ill print that there is a ani$al in the houseIelse 0e 0on7t print a thing. Hou $ight be
thin!ing that 0e nee/ to have three rege#p li!e /bat/ I /cat/ an/ /rat/ I but thats not the case. .e
1"6
I Love Ruby 2015 Beta
!no0 'ro$ those three rege#p that only the 'irst character varies. 4o 0hat about /.at/ li!e the
previous one. .ell that 0on7t 0or! either. Jecause i' you eat too $uch an/ /on7t e#ercise 0ellI that
0oul/ $atch even 'at D. AL,, It 0ill also $atch $at an/ tat an/ any other un0ante/ stu'' too.
4o this ti$e strictly 0e 0ant to $atch only bat rat an/ catI so 0e co$e up 0ith a rege#p li!e thisA /
[bcr]at/ I this 0ill only $atch those three ani$al 0or/s an/ nothing else. ;unch in the 'ollo0ing
e#a$ple an/ run it in your co$puter
#!/usr/bin/ruby
# regexp_character_classes.rb
puts "There is a animal in your house" if /[bcr]at/.match "There is bat in my
house"
puts "There is a animal in your house" if /[bcr]at/.match "There is rat in my
house"
puts "There is a animal in your house" if /[bcr]at/.match "There is cat in my
house"
puts "There is a animal in your house" if /[bcr]at/.match "There is mat in my
house"
2utput
There is a animal in your house
There is a animal in your house
There is a animal in your house
Bs you can see 'ro$ the output aboveI the string >%here is a ani$al in your house? gets printe/
thrice an/ not the 'ourth ti$e 0here the $atch 'ails 'or [%here is $at in $y house[.
Character classes can also accept ranges. ;unch in the co/e belo0 an/ run it.
#!/usr/bin/ruby
# regexp_character_classes_1.rb
print "Enter a short string: "
string = gets.chop
puts "The string contains character(s) from a to z" if /[a-z]/.match string
puts "The string contains character(s) from A to Z" if /[A-Z]/.match string
puts "The string contains number(s) from 0 to 9" if /[0-9]/.match string
puts "The string contains vowels" if /[aeiou]/.match string
puts "The string contains character(s) other than a to z" if /[^a-z]/.match
string
puts "The string contains character(s) other than A to Z" if /[^A-Z]/.match
string
puts "The string contains number(s) other than 0 to 9" if /[^0-9]/.match string
puts "The string contains characters other than vowels" if /[^aeiou]/.match
string
2utput
Enter a short string: fly
The string contains character(s) from a to z
The string contains character(s) other than A to Z
1"4
I Love Ruby 2015 Beta
The string contains number(s) other than 0 to 9
The string contains characters other than vowels
2utput 1
Enter a short string: Burgundy 32
The string contains character(s) from a to z
The string contains character(s) from A to Z
The string contains number(s) from 0 to 9
The string contains vowels
The string contains character(s) other than a to z
The string contains character(s) other than A to Z
The string contains number(s) other than 0 to 9
The string contains characters other than vowels
2KI 0hat you in'er 'ro$ the output@ .hen you give 'ly these rege#p7s $atchA
/[a-z]/ since it contains a character 'ro$ a to G
/[^A-Z]/ since it contains a character that /oes not belong any 0here 'ro$ B to UI hence
you co$e to !no0 ^ insi/e a capture $eans negation. %here are also other uses 'or ^ 0hich
i' I a$ not laGy you 0ill be 0riting about it.
/[^0-9]/ since it /oes not contain any nu$bers 'ro$ - to &
/[^aeiou]/ since it /oes not contain a vo0el +a or e or i or o or u,
Bccor/ing to that the $essages in the puts state$ents gets printe/.
No0 loo! at the 2utput 1I I have given the progra$ a string Jurgun/y 57 I chec! i' your
assu$ptions ) logic tally 0ith it NL,
*canning
I love this scan $etho/ in 4tring Class. It lets us search a huge array o' string 'or so$ething. Kust
li!e nee/le in a haystac!I since co$puters are getting 'aster an/ 'aster you can scan $ore an/ $ore.
%hey are goo/ 'or searching. %hey are :uiet unli!e the police in In/iaI 0ho 0oul/ only con/uct a
search only i' the person 0ho has been burgle/ gives bribe.
4o punch in the progra$ belo0. It scans 'or 0or/s in a string.
#!/usr/bin/ruby
# regexp_scan.rb
string = """ There are some words in this string and this program will
scan those words and tell their word count """
1"5
I Love Ruby 2015 Beta
words = string.scan(/\w+/)
puts "The words are:"
p words
puts # prints a empty line
puts "there are #{words.count} words in the string"
puts "there are #{words.uniq.count} unique words in string"
2utput
The words are:
["There", "are", "some", "words", "in", "this", "string", "and", "this",
"program", "will", "scan", "those", "words", "and", "tell", "their", "word",
"count"]
there are 19 words in the string
there are 16 unique words in string
Note the /\w+/ 0hat /oes it $ean@ Re'er this table by clic!ing here. Hou can see that \w $eans any
character li!e letterI nu$berI un/erscore an/ + $ean one or $any. In other 0or/s I have assu$e/
that 0or/s consists o' any letterI nu$ber an/ un/erscore co$binations an/ a 0or/ contains atLleast
one letter or $ore. 4o the state$ent string.scan(/\w+/) 0ill scan all 0or/s an/ put into into a
variable calle/ words 0hich 0e use in this progra$.
%he state$ent p words prints out the array an/ in the 'ollo0ing line
puts "there are #{words.count} words in the string"
0e are counting the nu$ber o' ele$ents in the array 0or/s using the co$$an/ word.count an/
e$be//ing in a string using #{words.count} an/ printing it out to the user.
In the ne#t state$ent
puts "there are #{words.uniq.count} unique words in string"
0e are 'in/ing ho0 $any uni:ue 0or/s are there in the given string using words.uniq.count an/
printing that too to the user. 3or e#a$ple i' you scan a large boo! o' t0o authors an/ 'ee/ it to this
progra$I the person 0ho has $ore nu$ber o' uni:ue 0or/s can be assu$e/ to have better
vocabulary.
*ets no0 see another progra$. 3or e#a$ple ta!e a t0eet you 0ill /o on t0itter an/ you 0ant to 'in/
out i' the t0eet contains t0itter user na$es. 4o lets analyGe a t0itter user na$eI it 'irst contains an
O sy$bol 'ollo0e/ by a 0or/. In other 0or/s it $ust $atch the rege#p /@\w+/ I 0ell si$ple. In
the 'ollo0ing progra$ 0e scan all the users $entione/ in a t0eet
#!/usr/bin/ruby
# regexp_scan_twitter_users.rb
1"6
I Love Ruby 2015 Beta
string = """ There is a person @karthik_ak who wrote ilr. Its about a
language called @ruby invented by @yukihiro_matz """
users = string.scan(/@\w+/)
puts "The users are:"
p users
2utput
The users are:
["@karthik_ak", "@ruby", "@yukihiro_matz"]
Notice the highlighte/ state$ent in the progra$ above. It scans all 0or/s that is perpen/e/ 0ith an
O sy$bolI collects the$ an/ returns the$ as an array. Bns 0e Fust /isplay that array using p users
.
)aptures
.e have seen ho0 use'ul regular e#pressions coul/ be. No0 let say 0e 'oun/ a $atch 0ith a
regular e#pression an/ 0e Fust 0ant to capture a s$all part o' itI say a user na$e in a e$ailI or a
$oth in so$e ones /ate o' birthI ho0 to /o that@
.e use roun/ brac!ets 'or that an/ 0e call the$ captures +technically,. Jelo0 is a progra$ that
as!s birth/ay o' a person an/ e#tracts the $onth out o' it.
#!/usr/bin/ruby
# regexp_capture.rb
print "Enter Birthday (YYYY-MM-DD) :"
date = gets.chop
/\d{4}-(\d{2})-\d{2}/.match date
puts "You were born on month: #{$1}"
2utput
Enter Birthday (YYYY-MM-DD) :1982-11-22
You were born on month: 11
Notice this line /\d{4}-(\d{2})-\d{2}/.match date I here 0e chec! i' the /ate $atches the
'ollo0ingA %hat isI it $ust have 'our /igits /\d{4}/ I then it $ust be 'ollo0e/ by a hyphen
/\d{4}-/ then it $ust be 'ollo0e/ by t0o /igits /\d{4}-\d(2}/ an/ it $ust be 'ollo0e/ a
hyphen an/ another t0o /igits /\d{4}-\d{2}-\d{2}/ .
No0 0e nee/ to capture Fust the $onth thats in the $i//le. Cence 0e put braces aroun/ it li!e
sho0n /\d{4}-(\d{2})-\d{2}/ I 0e stic! this rege#p in the progra$ aboveI in this line
/\d{4}-(\d{2})-\d{2}/.match date
1"7
I Love Ruby 2015 Beta
No0 0here this capture (\d{2}) gets store/@ It gets store/ in a global variable $1I i' there is
another captureI it gets store/ in another variable $2I $3 an/ so on..... 4o 0e no0 !no0 $1 has the
$onth an/ 0e use it in the 'ollo0ing line to print out the result
puts "You were born on month: #{$1}"
In the co$ing e#a$ple regexp_capture_1.rb I 0e try three captures 0here 0e 0ant to capture
HearI Month an/ Date in one go. Cence 0e use the 'ollo0ing rege#p /(\d{4})-(\d{2})-
(\d{2})/ . %ype the progra$ belo0 an/ e#ecute it.
#!/usr/bin/ruby
# regexp_capture_1.rb
print "Enter Birthday (YYYY-MM-DD) :"
date = gets.chop
/(\d{4})-(\d{2})-(\d{2})/.match date
puts "Year: #{$1} \n Month: #{$2} \n Date: #{$3}"
2utput
Enter Birthday (YYYY-DD-MM) :1997-12-67
Year: 1997
Month: 12
Date: 67
Cere the 'irst capture starting 'ro$ le't is store/ in $1I the secon/ is store/ in $2 an/ the thir/ in $3
an/ so on +i' 0e ha/ given $ore,. I' you are 0on/ering 0hat $0 isI 0hy /on7t you give a puts $0
state$ent at the en/ o' the progra$ an/ see 0hat happens@
In the ne#t progra$I 0e have /esigne/ it to tolerate so$e errors in user input. %he user $ay not
al0ays give 1990-04-17 I he $ight give it as say 1990 04- 17 or so$e thing li!e that that
$ight have spaces aroun/ nu$bers. %ype int the progra$ an/ e#ecute it
#!/usr/bin/ruby
# regexp_capture_2.rb
print "Enter Birthday (YYYY-MM-DD) :"
date = gets.chop
/\s*(\d{4})\s*-\s*(\d{2})\s*-\s*(\d{2})\s*/.match date
puts "Year: #{$1} \n Month: #{$2} \n Date: #{$3}"
2utput
Enter Birthday (YYYY-MM-DD) :1947- 07 - 14
Year: 1947
Month: 07
Date: 14
Bs you can seeI the progra$ rightly 'in/s $onthI /ate an/ year< .ell i' you note the rege#p 0e are
1""
I Love Ruby 2015 Beta
using /\s*(\d{4})\s*-\s*(\d{2})\s*-\s*(\d{2})\s*/ 0e have pa//e/ /igits 0ith \s*I no0
0hats that. 2nce again re'er the rege#p table by clic!ing here. as $eans space an/ T $eans Gero or
$oreI so say \s*\d{4} $eans $atch in such a 0ay that the rege#p has 4 /igits an/ is perpen/e/
0ith Gero or $ore spaces an/ \s*\d{4}\s* $atch a 4 /igit nu$ber 0hich is perpen/e/ an/
'ollo0e/ by Gero or $ore spaces. Cence no $atter ho0 $uch pa//ing you give 0ith spaceI it
rightly 'in/s out the /ates.
!ested apture
4o$eti$es so$e 0ise crac! progra$$er Fust out o' sheer luncticity
65
or Fust to $a!e 'un o' your
rege#p s!ills or to challenge youI or 'or so$e other reason $ight per'or$ a neste/ capture. %hat is a
capture 0ithin a capture.
I haven7t /one it so 'ar $y sel'I but 0ish to /o it in practical applications 'or the 'un o' it. No0 I
have 0or!e/ out a neste/ capture e#a$ple here on irb an/ i' you li!eI try it
>> /(a(c(b)))/.match "This sting contains acb ao it has match"
=> #<MatchData "acb" 1:"acb" 2:"cb" 3:"b">
>> $1
=> "acb"
>> $2
=> "cb"
>> $3
=> "b"
4ee the highlighte/ partI the rege#p is li!e this /(a(c(b)))/ I /oes it $a!es any sense to you@ .ell
then ho0 to rea/ it@ 3irst re$ove all brac!ets an/ rea/ it li!e /acb/ . acb is present in the string
an/ hence its $atche/ so 0e get the highlighte/ part in output as sho0n belo0
=> #<MatchData "acb" 1:"acb" 2:"cb" 3:"b">
No0 apply the outer $ost brac!et 'ro$ le't an/ 0e get a capture as sho0n /(acb)/ I this $atches
an/ captures acb 0hich appears in highlighte/ part in output as sho0n belo0
=> #<MatchData "acb" 1:"acb" 2:"cb" 3:"b">
%his capture s store/ in $1 global variable. No0 'orget the outer brac!et an/ $ove 'ro$ le't to the
secon/ pair o' brac!ets an/ you get the 'ollo0ing rege#p /a(cb)/ I this $atches acb an/ captures
cb in the stringI this is caught in variable $2 an/ is also sho0n in highlighte/ part o' the $atche/
/ata belo0
=> #<MatchData "acb" 1:"acb" 2:"cb" 3:"b">
65 I li!e to create ne0 english 0or/s AL,,
1"&
I Love Ruby 2015 Beta
In si$ilar 0ay the inner $ost brac!et pairI 'or$s this rege#p /ac(b)/ an/ its capture/ in variable
$3 is sho0e/ in $atche/ output belo0
=> #<MatchData "acb" 1:"acb" 2:"cb" 3:"b">
%atchData class
4o you have $atche/ stu'' an/ capture/ it. .ell i' you have notice/ in the irbI 0hen ever u $atch a
thingI a obFect gets returne/. .ell all is a obFect in RubyI yupI but this is not 4tring type obFectI but
a ne0 type calle/ MatchData. 4o lets play 0ith it an/ see 0hat it can /o. 4o see the e#a$ple belo0
0here 0e $atch a rege#p /abc/ 0ith a string an/ 0e store it in a variable m
>> m = /abc/.match "This stuff has abc and something after it"
=> #<MatchData "abc">
%o see 0hat 0as $atche/I 0e give the co$$an/ m.match an/ its thro0s an error as sho0n belo0<
>> m.match
NoMethodError: undefined method `match' for #<MatchData "abc">
from (irb):2
from /home/webtoday/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in `<main>'
4o ho0 to get the $atch@ .ellI it loo!s li!e the MatchData is an array 0here the 'irst ele$ent is the
$atche/ piece o' te#t so Fust type m[0] to get the $atche/ /ata as sho0n belo0
>> m[0]
=> "abc"
so$e ti$es you $ight be intereste/ 0hat co$es be'ore an/ a'ter a $atch. %he pre_match 'unction
gets the piece o' te#t that is prior to the $atch as sho0n belo0
>> m.pre_match
=> "This stuff has "
*i!e pre_matchI post_match /oes the oppositeI it gets the piece o' te#t that co$es a'ter the $atch.
>> m.post_match
=> " and something after it"
I' you 0ant to see 0eather you have any capturesI you can call the captures 'unction as sho0n.
>> m.captures
=> []
2' course you have no captures this ti$eI hence the captures 'unction returns an e$pty array.
.ellI tal!ing about captures in MatchData obFect I ta!e a loo! at the piece o' co/e belo0. .e have
given a rege#p 0ith capture as sho0n /((ab)c)/ . %his rege#p in the the string "This stuff has
1&-
I Love Ruby 2015 Beta
abc and something after it" 0ill $atch abc an/ 0ill capture abc an/ ab +i' you have
un/erstoo/ 0hat capture is in the previous sections,. .ell ho0 to to get captures in MatchData
obFectI 'irst let us $atch the rege#p 0ith string an/ store it variable m as sho0n belo0
>> m = /((ab)c)/.match "This stuff has abc and something after it"
=> #<MatchData "abc" 1:"abc" 2:"ab">
No0 to see capturesI use the capture 'unction on MatchData obFect as sho0n belo0
>> m.captures
=> ["abc", "ab"]
4o you get captures as Brray 0hich can be treate/ as an Brray obFect. Ho can get the captures
/irectly 'ro$ MatchData too as sho0n belo0I the secon/ ele$ent on0ar/s in the MatchData array
stores the captures 0hich can be accesse/ by m[1]I m[2] D... m[n] as sho0n in the case belo0
>> m[1]
=> "abc"
>> m[2]
=> "ab"
.ellI I have tol/ that m belongs to MatchData classI an/ haven7t o''ere/ proo' yet. .ell here is it
>> m.class
=> MatchData
/nchors an# /ssertions
#nchor&
Bnchors are re'erence points in Ruby. *ets say that 0e 0ant to chec! i' a line i$$e/iately begins
0ith a =begin
66
I then I can chec! it 0it a rege#p li!e this /^=begin/ I 0here the ^ sign is a anchor
that represents beginning o' the lineA
/^=begin/.match "=begin"
=> #<MatchData "=begin">
*ets say li!e 0e have $ultiple line string an/ 0e 0ant to e#tract a line +the 'irst one,. 4o the content
o' the 'irst line coul/ be any thingI so 0e get a rege#p as /.+/I no0 it $ust be bet0een beginning
o' line ^ an/ en/ o' line $ I so 0e get a rege#p as sho0n /^.+$/ I s this 0ill $atch anything thats
bet0een line anchors. Bn e#a$ple is sho0n belo0.
>> /^.+$/.match "Boom \n Thata"
=> #<MatchData "Boom ">
In the above e#a$pleI note that \n splits the string into t0o lines as \n stan/s 'or ne0line character.
66 =begin represents start o' bloc! co$$ent in RubyI but it $ust start at the line beginning
1&1
I Love Ruby 2015 Beta
4o the rege#p 'aith'ully $atches the 'irst line contentI that is >Joo$ ?.
%he ne#t type o' Bnchors 0e have are \A that stan/s 'or start o' a string an/ \z that stan/s 'or en/
o' a string. In the e#a$ple belo0I 0e chec! i' the string starts 0ith so$e thing by using the
'ollo0ing rege#p /\ASomething/
>> /\ASomething/.match "Something is better than nothing"
=> #<MatchData "Something">
Bn/ 0e get a $atch. In the e#a$ple belo0 0e get a nil $atch because the string /oes not start 0ith
4o$ething.
>> /\ASomething/.match "Everybody says Something is better than nothing"
=> nil
No0 lets chec! i' nothing is 'ollo0e/ by en/ o' stringI hence 0e 'or$ a rege#p as sho0n
/nothing\z/
>> /nothing\z/.match "Everybody says Something is better than nothing"
=> #<MatchData "nothing">
Bs e#pecte/ 0e get a $atch o' nothing. 2ne shoul/ not that anchors 0ill not be re'lecte/ in $atch
/ataI anchor is not a characterI but Fust a sy$bolic representation o' position. 4o i' you are
e#pecting a $atch o' nothing\z I 'orget it.
>> /nothing\z/.match "Everybody says Something is better than nothing\n"
=> nil
*oo! at the e#a$ple aboveI the \z $atches a string 0ithout a line en/ing+\n, character. I' you 0ant
to chec! 'or line en/ingsI you $ust use capital U li!e the e#a$ple sho0n belo0.
>> /nothing\Z/.match "Everybody says Something is better than nothing\n"
=> #<MatchData "nothing">
4o AL, it $atches<
In the e#a$ple belo0I 0e $atch all the stu'' thats in a string 0ith an as its en/ing.
>> /\A.+\Z/.match "Everybody says Something is better than nothing\n"
=> #<MatchData "Everybody says Something is better than nothing">
#&&ertion&
*ets say that you are searching 'or this $an Davi/ Copper'iel/I perhaps to $a!e your nagging girl
'rien/ or 0i'e to /isappear so that you can get a ne0 one. Hou have a huge /irectory o' na$es an/
you 0ant to $atch his na$e. .e can /o those !in/ o' $atches using assertions
67
. 4o you 0ant to
67 I' you are thin!ing that this can be searche/ in $uch si$ple 0ayI then ur rightI but 'or the ti$e being /on7t thin! too
$uch. Hour brain $ight overheat an/ burn.
1&5
I Love Ruby 2015 Beta
search so$ething that co$es be'ore Copper'iel/I 'or that 0e use loo! ahea/ assertions. %a!e the
e#a$ple belo0
>> /\w+\s+(?=Copperfield)/.match "David Copperfield"
=> #<MatchData "David ">
*oo! at the co/e thats been $a/e bol/. It has (?=Copperfield) I that is its loo!ing 'or0ar/ 'or
so$ethingI this ti$e its Copper'iel/. .ant to beco$e rich soonI then search 'or (?=Goldfield) an/
0ant so$e goo/ $usicI search 'or (?=Oldfield)
6"
. 2!ay I a$ typing too $uch.
Cere is the thingI 0hat ever you give bet0een (?= an/ ) 0ill be loo! 'or0ar/ an/ i' there is
so$ething be'ore itI it 0ill be $atche/. 4o there is Davi/ be'ore Copper'iel/I hence it 0as $atche/.
Note that I ha/ given \w+\s+ 0hich $eans that I 0ant to $atch a rege#p o' one or $ore lettersI
'ollo0e/ by one or $ore space/ that prece/es be'ore Copper'iel/. 4o here 0e have another
e#a$pleI that gives a positive $atchA
>> /\w+\s+(?=Copperfield)/.match "Joan Copperfield"
=> #<MatchData "Joan ">
*ets say that 0e 0ant to $atch all those na$es 0hich /oes not en/ 0ith Copper'iel/I 0e 0ill use
loo! ahea/I negative assertion. 3or this 0e put Copperfield in bet0een (?! an/ )I so in the
'ollo0ing e#a$ple it 0ill return a negative $atch
>> /\w+\s+(?!Copperfield)/.match "Joan Copperfield"
=> nil
Jut in the ne#t e#a$ple it 0ill return a positive $atchI because Koan is not be'ore Copper'iel/
>> /\w+\s+(?!Copperfield)/.match "Joan Kansamy"
=> #<MatchData "Joan ">
.e have seen loo! 'or0ar/ assertion. No0 lets loo! at loo! bac!0ar/ assertion. *ets say that 0e
0an to $atch last na$e o' person 0ho7s 'irst na$e is Davi/. %hen 0e can loo! bac!0ar/s 'ro$ last
na$e an/ see i' its Davi/. Chec!out the co/e belo0
>> /(?<=David)\s+\w+/.match "Joan Kansamy"
=> nil
4ee the highlighte/ part. .e have put David bet0een (?<= an/ )I so thats ho0 you speci'y loo!
bac! assertion. %he above co/e returns nil because 0e have no Davi/ in it.
>> /(?<=David)\s+\w+/.match "David Munsamy"
=> #<MatchData " Munsamy">
%he above e#a$ple $atches > Munsa$y?
6&
because 0e have Davi/ be'ore the pattern \s+\w+
4a$e 0ay li!e 0e ha/ negative loo! 'or0ar/I 0hy can7t 0e have it in loo! bac!0ar/s@ Kut replace
6" Mi!e 2l/'iel/ is $y 'avorite $usician
6& Notice the space too 0hich has been $atche/.
1&6
I Love Ruby 2015 Beta
= 0ith a ! an/ you 0ill get a negative assertion. 4o the e#a$ple belo0 0ill not $atch because you
have Davi/ in 'ront o' Munsa$y.
>> /(?<!David)\s+\w+/.match "David Munsamy"
=> nil
No0 ta!e this e#a$ple belo0I 0e 0ill have a $atch because there is no Davi/ in 'ront o' the 'irst
\s+\w+ I that is in the e#a$ple belo0 it is a space 'ollo0e/ by >in?.
>> /(?<!David)\s+\w+/.match "All in all Munsamy"
=> #<MatchData " in">
Ignoring )ases
2!ayI lets say 0hat the /i''erence bet0een these e$ails 77$in/sOg$ail.co$ an/
77MIND4OMBI*.C2M I in short nothingI both a//ress /elivers $ail to $eI so i' at all 0e are
scanning a string 'or a particular e$ailI 0e 0oul/ li!e to ignore cases. 4o consi/er the e#a$ple
belo0
>> /abc/i.match "There is ABC in string"
=> #<MatchData "ABC">
Int the above e#a$ple 0e have a rege#p /abc/ but it $atches ABC in the given string. I' you have
notice/ the highlighte/ ) bol/ partI you $ay notice that I have put an i a'ter the rege#pI that i
stan/s 'or ignore case. .ell see the e#a$ple belo0I the i ruthlessly $atches anything an/ /oes not
care about cases.
>> /abc/i.match "There is AbC in string"
=> #<MatchData "AbC">
Cope this e#planation su''ice.
Ignore *paces
I /on7t really !no0 0here to use this x . x Fust li!e i shoul/ be use at the rear o' rege#p. It ignores
0hite spaces in rege#p an/ $atches the string. 4ee e#a$ple belo0
>> /ab c/x.match "There is abc in string"
=> #<MatchData "abc">
Jut this /oes not $ean that it ignores 0hite spaces in $atche/ stringI in the e#a$ple belo0 0e have
a rege#p /ab c/ +ab space c, but it /oes not $atch ab c +ab space c, in the string< %hat coul/ be
surprisingI but 0hen x is appen/e/I it $ean it re$oves all spaces 'ro$ rege#p.
>> /ab c/x.match "There is ab c in string"
1&4
I Love Ruby 2015 Beta
=> nil
1&5
I Love Ruby 2015 Beta
Gems
e$ is a pac!age $anage$ent stu'' 'or ruby. 3or e#a$ple you $ight 0ant to /o a stu'' in rubyI li!e
say co$paring t0o hashesI rather than 0riting a co/e by your sel' you can search ruby ge$s
repository locate/ at httpA))rubyge$s.org
*earching a gem
4o you 0ant to co$pare t0o hashesI 0hy@ Jecause I have 0ritten here so. 4o so$e angel
/escen/e/ 'ro$ s!y an/ tol/ you that there is a ge$ calle/ hashPco$pare 'or co$paring hashes.
No0I you can goto httpA))rubyge$s.org an/ search 'or hashPco$pare
Hou 0ill be getting a page as sho0n belo0I clic! on the hash co$pare lin! an/ you 0ill be /irecte/
to this page httpsA))rubyge$s.org)ge$s)hashPco$pare
1&6
I Love Ruby 2015 Beta
4o thats ho0 you search
7-
'or a ge$.
Installing gem
No0 that you have 'oun/ out the ge$I ho0 to install it. I' you are in the ge$s pageI
httpsA))rubyge$s.org)ge$s)hashPco$pare in this case you 0ill get the instruction to install it on
your co$puter. Hou can install hashPco$pare ge$ by typing the 'ollo0ing
$ gem install hash_compare
This will spit out the following stuff indicating that it has installed
Fetching: hash_compare-0.0.0.gem (100%)
Successfully installed hash_compare-0.0.0
1 gem installed
Installing ri documentation for hash_compare-0.0.0...
Installing RDoc documentation for hash_compare-0.0.0...
(ie$ing Documentation
Right so you have installe/ a ge$ success'ullyI no0 you $ust !no0 ho0 to use itI 0here else is a
great place to learn about a piece o' ruby co/e than its /ocu$entation. I' ou are not sure about r/oc
or ruby /ocu$entationI Fust rea/ the chapter R/oc .
7- I' you can7t 'in/ it outI see! help o' local police
1&7
I Love Ruby 2015 Beta
%o see /ocu$entation 'or installe/ ge$I you nee/ to start a thing calle/ ge$ serverI 0hich can be
achieve/ by typing the 'ollo0ing co$$an/ in ter$inal.
$ gem server
Server started at http://0.0.0.0:8808
%he above co$$an/ 0ill spit a output saying that the server has been starte/. %o !no0 about hash
co$pare ge$ goto this a//ress httpA))-.-.-.-A""-" in your bro0ser an/ search 'or hashPco$pareI
else i' you nee/ to have a shorter 0ay clic! this lin! httpA))-.-.-.-A""-")_hashPco$pare I 0hen you
clic! on hashPco$pare you 0ill be /irecte/ here httpA))-.-.-.-A""-")/ocProot)hashPco$pareL
-.-.-)r/oc)in/e#.ht$l I this is the /ocu$entation page 'or hashPco$pare ge$.
%here in that pageI you 0ill have su''icient /etails +possibly, about hashPco$pare ge$.
Using gem
2KI to use the ge$
71
0e in our ter$inal log in into irb using the 'ollo0ing co$$an/
$ irb --simple-prompt
Ne#t 0e 0ill re:uire hash co$pare co$$an/ using the 'ollo0ing co$$an/
>> require 'hash_compare'
=> true
Bn/ since the ge$ has been installe/ it says true. No0 lets buil/ t0o hashes a an/ be as sho0n
belo0
>> a = { a: 1, b: 2}
=> {:a=>1, :b=>2}
>> b = { a: 1, b: 3, c: 2}
=> {:a=>1, :b=>3, :c=>2}
No0 0e a// these to hashPco$pare obFect
>> h = HashCompare.new a,b
Bn/ 'in/ 0hats ne0ly a//e/ using the ne0lyPa//e/ 'unction as sho0n belo0
>> h.newly_added
=> {:c=>2}
.ellI thats it. Hou $ight have learne/ ho0 to use a ge$.
)reating a gem
Hou $ight have learne/ so$ething about Ruby rea/ing $y boo!. Its not enough i' you Fust !eep
using the great contributions others have /one to $a!e your progra$$ing li'e easierI you $ust
71 I 0ill use it in irbI I /on7t have the patience to use it in a ruby 'ile.
1&"
I Love Ruby 2015 Beta
contribute bac! to the co$$unity. In this section I 0ill be telling you ho0 to create a ge$
75
'or your
sel' an/ publish it in httpA))rubyge$s.org . %o create a ge$ I 0ill be using the 'ollo0ing co/eA
require 'net/http'
# Converts currency from one format to another, for example from USD to
# EUR
# from_curr the code for the currency that needs to be converted
# to_curr the code for the currency that needs to be converted to
# amount amount of money in from_curr
def convert_currency(from_curr = "INR", to_curr = "USD", amount = 1000)
host = "www.google.com"
http = Net::HTTP.new(host, 80)
url = "/finance/converter?a=#{amount}&from=#{from_curr}&to=#{to_curr}"
response = http.get(url)
# puts response.body
result = response.body
regexp = Regexp.new("(\\d+\\.{0,1}\\d*)\\s+#{to_curr}")
regexp.match result
return $1.to_f
end
%his co/eI by using so$e $agic converts currency +it re:uires Internet to /o it,. I a$ going to call
this ge$ $oneyL$in/ so let $e create a 'ol/er calle/ money-mind an/ another 'ol/er in it calle/
lib an/ let $e put this co/e insi/e the 'ile calle/ money-mind.rb I so no0 I have a 'ile in location
money-mind/lib/money-mind.rb
%he ne#t step is the $ost i$portant oneI 0e create a 'ile na$e/ money-mind.gemspec in the 'ol/er
$oneyL$in/I a/ put this stu'' into it
Gem::Specification.new do |s|
s.name = 'money-mind'
s.version = '0.0.0'
s.date = '2012-11-05'
s.summary = "Money Mind"
s.description = "A simple currency conversion code in Ruby"
s.authors = ["Karthikeyan A K"]
s.email = '77minds@gmail.com'
s.files = ["lib/money-mind.rb"]
end
I' at all you 0ant to have a testing thing 'or the $oneyL$in/ ge$ create a 'ol/er na$e/ test an/ put
the co/e belo0 in currency_test.rb
require '../lib/money-mind.rb'
puts convert_currency("USD", "EUR", 1000)
%he test stu'' is optionalI no0 navigate to the money-mind 'ol/er in your ter$inal an/ punch out the
75 %he truth is you coul/ 0rite any crap Ruby progra$ an/ can call it a ge$. Isn7t that great. Hou can7t /o this stu'' in
an other language<<
1&&
I Love Ruby 2015 Beta
'ollo0ing co/e an/ press enter.
$ gem build money-mind.gemspec
Bs you $ay have in'erre/ you use the ge$spec 'ile to create a ge$. I 0ish $ost stu'' in ge$spec
'ile 0ill be 'airly straight'or0ar/I Fust ta!e note o' this line s.files = ["lib/money-mind.rb"] I
its here 0e a// the 'iles that nee/ to inclu/e/ in the ge$. 2K 0hen you press enter you 0ill get
so$e stu'' li!e as sho0n belo0.
WARNING: no homepage specified
Successfully built RubyGem
Name: money-mind
Version: 0.0.0
File: money-mind-0.0.0.gem
Kust ignore the 0arning $essage 'or the ti$e being. %he $oral o' the story is gem build
<path_to_gemspec_file>/<gemspec_file_name> buil/s the ge$ so$eho0. 4o Hahooooooo<
ooooooooogle< .e have create/ our o0n ge$<<< %i$e to celebrate. I' you see $oneyL$in/ 'ol/er
you 0ill see ane0 'ile na$e/ money-mind-0.0.0.gem I no0 thats the ge$ 'ile. Coping that you
are in the 'ol/er 0here the ge$ 'ile isI no0 punch in the 'ollo0ing co/e in ter$inal
$ gem install money-mind-0.0.0.gem
It shoul/ spit a output as sho0n
Successfully installed money-mind-0.0.0
1 gem installed
Installing ri documentation for money-mind-0.0.0...
Installing RDoc documentation for money-mind-0.0.0...
4o the $oral o' the story here is gem install <path_to_gem_file>/<gems_file_name> installs
the ge$ 'ile so$e ho0. No0 i' you ha/ rea/ this chapterI you 0ill !no0 ho0 to use itI an/ 0e in the
irb e#a$ple belo0 covert 5- (4 Dollars to In/ian Rupee an/ 1 (4 Dollar to In/ian Rupee
$ irb --simple-prompt
>> require 'money-mind'
=> true
>> convert_currency("USD", "INR", 50)
=> 2710.0
>> convert_currency("USD", "INR", 1)
=> 54.2
Uninstalling a Gem
3inally to uninstall a ge$ Fust type ge$ uninstall Wge$na$eV I so by typing
5--
I Love Ruby 2015 Beta
$ gem uninstall money-mind
Hou 0ill get a output as sho0n
Successfully uninstalled money-mind-0.0.0
.hich in/icates the ge$ has been uninstalle/ success'ully.
5-1
I Love Ruby 2015 Beta
Meta +rogramming
Meta ;rogra$$ing is a art o' $a!ing progra$s 0rite progra$s. %hat is in run ti$e a progra$ can
$o/i'y itsel' /epen/ing on the situation. *ets see about it in this chapter.
*en#
Ruby has got a po0er'ul $etho/ calle/ sen/. %hat is i' a obFect p has got a $etho/ na$e I in ruby
0e can call it using p.na$e or there is another 0ay to call it to. .e call call it using p.sen/+Ana$e,
or p.sen/+>na$e?, . .ell 0hats the use o' that@ %he use is thisI you can /eter$ine 0hat 'unction to
call 'ro$ the user input or so$e other input you receive.
*ets see a basic e#a$ple. %ype the progra$ belo0 into a te#t e/itor an/ run it.
#send.rb
class Person
attr_accessor :name
def speak
"Hello I am #{@name}"
end
end
p = Person.new
p.name = "Karthik"
puts p.send(:speak)
2utput
Hello I am Karthik
.ellI as you see in the part o' the co/e highlighte/ p.send(:speak) I 0e are calling the spea!
'unction o' instance p o' class Person using the send $etho/. %hats it 'or no0 about sen/. et
e#cite/<<< %0eet that you are learning Metaprogra$$ing an/ start bragging to your colleagues.
.ellI hope you have bragge/ enoughI ha/ a piGGa or t0o. No0 lets loo! at a practical enough
e#a$ple 'or this sen/
76
'unction. %ype in the e#a$ple sen/P1.rb an/ e#ecute it
# send_1.rb
76 In 'act the sen/ 'unction 0as so practical an/ use'ul to hu$anity that the Noble co$$ittee contacte/ $e an/ begge/
$e to have its priGe. Me being hu$ble an/ re'use/ it. B$ I not hu$ble an/ great@
5-5
I Love Ruby 2015 Beta
class Student
attr_accessor :name, :math, :science, :other
end
s = Student.new
s.name = "Zigor"
s.math = 100
s.science = 100
s.other = 0
print "Enter the subject who's mark you want to know: "
subject = gets.chop
puts "The mark in #{subject} is #{s.send(subject)}"
2utput
Enter the subject who's mark you want to know: math
The mark in math is 100
4o in the progra$I 0e have a class calle/ 4tu/ent an/ 0e create a stu/ent 0ho7s $ar!s in $athI
science an/ other subFects are 1--I 1-- an/ Gero. .e as! the user to enter the subFect 0ho7s $ar!
nee/s to be !no0n an/ get it into a variable na$e/ subFect in these 'ollo0ing state$ents
print "Enter the subject who's mark you want to know: "
subject = gets.chop
now see this line:
puts "The mark in #{subject} is #{s.send(subject)}"
Kust notice the highlighte/ part s.sen/+subFect, I 0e over here instea/ o' using case or other i' or
con/itions to chec! 0hat the subFect is an/ then call the suitable $etho/ accor/ingI 0e si$ply pass
the user input to s.sen/ an/ it calls the appropriate $etho/ an/ returns the value.
Don7t you see a $agic here@
74
%etho# %issing
*ets say that you class has only certain $etho/s an/ i' the progra$$er calls so$e other craGy
$etho/I an/ you 0ant to capture it an/ see i' it can still be serve/I you can use the $etho/P$issing
$etho/ to capture the $etho/ an/ other stu''.
*ets see a progra$ about $etho/ $issing. %ype in the progra$ $etho/P$issing.rb in your test
e/itor an/ e#ecute it
# method_missing.rb
class Something
def method_missing method, *args, &block
74 I' elseI Fust visit a $agic sho0 an/ be satis'ie/
5-6
I Love Ruby 2015 Beta
puts "You called: #{method}"
p args
block.call 7
end
end
s = Something.new
s.call_method "boo", 5 do |x|
x.times{ puts "in block" }
end
2utput
You called: call_method
["boo", 5]
in block
in block
in block
in block
in block
in block
in block
*ets see ho0 this progra$ 0or!sI in the line s = Something.new 0e create a ne0 instance variable
s o' Something class. %hen in the ne#t line 0e /o this s.call_method "boo", 5 I in this line 0e
call a $etho/ calle/ call_method on sI i' you loo! at class Something I you 0ill notice that there
is no $etho/ or 'unction calle/ call_method in itI but the progra$ /oes not thro0 out errorI or
e#ception or 0hatever.
.ellI 0hat happene/@ I' you notice 4o$ething classI you 0oul/ have seen a $etho/ na$e/
method_missingI it has been i$ple$ente/ as sho0n
def method_missing method, *args, &block
puts "You called: #{method}"
p args
block.call 7
end
%his $etho/ ta!es in three argu$entsI in our co/e 0e have na$e/ these argu$ents as methodI
*args an/ &block. %he $etho/ ta!es in the $etho/ na$eI the na$e o' the $etho/ being calle/ up
sI the *args ta!es attributes that are passe/ to the $etho/I in out case its the call_method an/
attributes passe/ are boo an/ 5. %he &block ta!es in any bloc! that is been passe/. I' you see the
highlighte/ part 0here 0e call call_method on s belo0
s.call_method "boo", 5 do |x|
x.times{ puts "in block" }
end
.e are passing a bloc! to the call_method 'unction 0hich is enclose/ by /o an/ en/. Insi/e the
5-4
I Love Ruby 2015 Beta
bloc! 0e ta!e a variable x an/ /o so$e operation 0ith it. %his entire bloc! is capture/ by &block.
3inally 0e are printing the argu$ents passe/ using the state$ent p args +note that 0e are not using
*args here, an/ 0e care calling the bloc! 0ith block.call 7 +note that 0e use bloc! an/ not
&block here, in the method_missing /e'inition. %he value 7 gets passe/ to variable x in the bloc!.
No0 lets see ho0 $etho/ $issing coul/ be use/. *et say that 0e have a class calle/ ;erson 0hich
has t0o attributes na$e/ na$e an/ ageI see the co/e belo0 an/ e#ecute it
# method_missing_in_action.rb
class Person
attr_accessor :name, :age

def initialize name, age
@name, @age = name, age
end

def method_missing method_name
method_name.to_s.match(/get_(\w+)/)
eval("self.#{$1}")
end
end
person = Person.new "Zigor", "67893"
puts "#{person.get_name} is #{person.get_age} years old"
2utput
Zigor is 67893 years old
In the co/e above see the highlighte/ line puts "#{person.get_name} is #{person.get_age}
years old" 0e call the attributes not li!e person.name an/ person.ageI instea/ 0e use
person.get_name an/ person.get_age . No0 there are no get_name an/ get_age $etho/s in
person classI instea/ the co/e en/s up here
def method_missing method_name
method_name.to_s.match(/get_(\w+)/)
eval("self.#{$1}")
end
In the $etho/ $issing $etho/. *oo! at the highlighte/ co/eI 0here in this line
method_name.to_s.match(/get_(\w+)/) 0e e#tract any $etho/ that is perpen/e/ 0ith get_ I
then 0e call the e#tracte/ ter$ in this state$ent eval("self.#{$1}") . I' you can7t un/erstan/
these thingsI probably you $ust rea/ Regular 1#pressions chapter.
No0 ho0 to $a!e it use'ul practicallyI 'or e#a$ple you can have a getP/bPW$etho/ na$eV 0here
5-5
I Love Ruby 2015 Beta
you can get values 'ro$ a /atabaseI or say storeP/bPW$etho/ na$eV+values...., I 0here you can
capture it an/ store in in the /atabase. I /on7t have $oo/ to 0rite such progra$sI so help yoursel'.
Define %etho#
%his section 0e are going to see ho0 to /e'ine $etho/s insi/e a class. %ype the progra$ belo0 an/
e#ecute it
# define_method.rb
class Square
define_method :area do |side|
side * side
end
end
s = Square.new
puts s.area 5
2utput
25
2!ayI so you get 55 as the output. I' you notice the progra$ /e'ineP$etho/.rb you 0oul/ have
notice that in the highlighte/ lines above 0e are /e'ining $etho/ na$e/ area using this a0!0ar/
loo!ing state$ents
define_method :area do |side|
side * side
end
Hou $ay thin! 0hy not 0e /o it li!e thisA
def area side
side * side
end
.ellI yaI but lets ta!e a situation 0here 0e can /yna$ically /e'ine $etho/ or to put itI 0e nee/ to
/yna$ically /e'ine $etho/s.
# define_method_dynamic.rb
Book_hash = {author: "Zigor", title: "I Love Ruby", page: 95}
class Book
Book_hash.each do |key, value|
define_method key do
value
end
5-6
I Love Ruby 2015 Beta
end
end
b = Book.new
puts "#{b.author} has written a book named #{b.title}"
2utput
Zigor has written a book named I Love Ruby
4o in the above progra$ 0e have t0o highlighte/ parts the 'irst one is Book_hash = {author:
"Zigor", title: "I Love Ruby", page: 95} I over here its a constant assigne/ to a hash value.
In real 0orl/ it coul/ be a variable loa/ing so$e hash /yna$ically 'ro$ a 'ile. Bn/ insi/e the class
boo! you see these lines
Book_hash.each do |key, value|
define_method key do
value
end
end
.here 0e ta!e in each hash valueI an/ 0e /e'ine a $etho/ using its its !ey an/ the $etho/ returns
the value. 4o 0hen 0e say b = Book.new I 0e no0 have alrea/y 'unctions na$e/ author I title
an/ page 0hich returns ZigorI I Love Ruby an/ 95 respectively.
3or this state$ent puts "#{b.author} has written a book named #{b.title}" I e#plain it to
yoursel'. I /on7t have the $oo/ to 0rite.
5-7
I Love Ruby 2015 Beta
#inal /ord
'or 89:; &#ition
5-15 is the e/ition o' per'ection. Coping to !eep it 'ree as in 'ree/o$. In this e/itionI $ista!es 0ill
be i/enti'ie/ an/ patche/. %hats it. ;ossibly so$e content 0ill be a//e/ here an/ there.
'or 89:< &#ition
.ellI this boo! is still in post beta. 3or 5-14 e/ition I have a//e/ Metaprogra$$ing section
+though its not co$prehensive,I 0hich I 'eel 0ill $a!e this boo! !in/ o' co$plete. %his boo!
shoul/ be seen as $y personal notes 0hich I a$ sharing 0ith others rather than a pro'essional 0or!.
I 0oul/ love to get your 'ee/bac! 0hich can be sent to 77$in/sOg$ail.co$ an/ 0ill surely 0or!
upon to i$prove this boo!.
I' I can release another e/ition in 5-14 it $ight have e#ception han/ling chapter.
'or 89:= &#ition
Its 5-16I this e/ition is a beta release in 0hich I have a//e/ t0o ne0 chaptersI one is R/ocI ho0 to
rea/ an/ 0rite ruby /ocu$entationI an/ e$s 0here I tell the rea/er ho0 to create an/ use a ruby
ge$.
%his ti$e the 'ull source te#t o' the boo! has been launche/I $a!ing this boo! 1--Q 'ree as in
'ree/o$.
'or 89:8 &#ition
I never e#pecte/ that I 0ill be a//ing another touch to I *ove Ruby. I a$ no0 0or!ing in a
co$pany calle/ .ebto/ay JusinessI here I have 6 people un/er $e 0ho are creating 0eb apps
using Ruby on Rails. I reco$$en/e/ so$e boo!s 'or the$ to learn RubyI but 0hen I gave ilr to
the$ they sai/ it 0as goo/ an/ $ust be upgra/e/I so I starte/ the process o' touching the ol/ boo!
to give ne0 'inish.
I have a//e/ Regular 1#pressions chapter in this boo!. %his chapter is 'ar 'ro$ e#haustive. 3ro$
5-"
I Love Ruby 2015 Beta
no0 on all ilr releases 0ill be in relatively :uic! successionI 0ith little incre$ents an/
i$prove$ents to it. %hey $ay never ever be a $aFor release.
Bny 0ay i' you have been bene'ite/ by this boo!I /rop a 0or/ to $e.
'or 89:9 &#ition
%his is $y 'irst boo! on Ruby. I have Fust one person 'or help to 0rite this boo!I hence I in'er there
coul/ be $any $ista!es that coul/ irritate the rea/er. I 0oul/ be happy i' the rea/er 'orgives $e.
Cappier still 0ill be I i' the rea/er spots $ista!es an/ noti'y $y. It helps $e per'ect this boo!. I
hope this boo! one /ay 0ill be the one o' the cost e''ective an/ :uality Ruby stu/y $aterial
available on this planet. ;ractice a lotI /on7t Fust li$it 0ith Fust one stu/y $aterial 'or Ruby. .ith
con'i/ence an/ har/ 0o! I a$ sure you7ll be one o' the best Ruby progra$$ers ever. Jye<
5-&
I Love Ruby 2015 Beta
Appendix
51-
I Love Ruby 2015 Beta
0nderscore
.ellI i' you 0ant to see i' un/erscore 0or!s in ruby progra$I /o0nloa/ this progra$
underscore.rb an/ e#ecute it by typing $ ruby underscore.rb +by changing /irectory to place
0here underscore.rb e#ists,I any 0ay 'or those 0ho cant /o0nloa/ no0I here is the progra$
#!/usr/bin/ruby
# underscore.rb
# program to check if underscore can be used
# in a rb file
87*23
puts "87 X 23 X 5 = #{_*5}" # This wont work
2utput
underscore.rb:8: undefined local variable or method `_' for main:Object
(NameError)
%he progra$ shoul/ spit an error as sho0n aboveI proving that un/erscore /oes not 0or! in a ruby
'ile.
511
I Love Ruby 2015 Beta
!n important Math Discovery
I (u&t confe&& &o(eti(e& co(puter& %o go /rong8 In certain ca&e& 1 i& e2ua* to 28 ,a"e the e2uation
a
5
b
5
=ab ab
no/ put a 4 b 4 1 in it &o /e get
1
5
1
5
=1111
11=1111
11
11
=11
*ets put 11=k so 0e get
k
k
=11
Bny nu$ber /ivi/e/ by it&e*f is oneI so
k
k
=1
I so 0e get the proo' that
k
k
=1=11
1=11
1=5
Di/n7t I say that co$puters can go 0rong
75
.
75 %ell this i$portant great /iscovery to no one. Is a great secret $any $athe$aticians have 'aile/ to 'in/ out<
515
I Love Ruby 2015 Beta
516

You might also like