Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 238

ZetCode Ruby tutorial

This is a Ruby tutorial. In this tutorial you will learn the Ruby language. The tutorial is suitable for beginners.

Ruby
Ruby is a dynamic, reflective, general-purpose object-oriented programming language. The original author is a Japanese programmer Yu ihiro !atsumoto. Ruby first appeared in "##$. Ruby supports various programming paradigms. This includes object orientation, reflection, imperative and reflective programming.

Ruby
In this part of the Ruby tutorial, we will introduce the Ruby programming language.

Goal
The goal of this tutorial is to get you started with the Ruby programming language. The tutorial covers the core of the Ruby language, including variables, e%pressions, collections, control structures and other core features. It also describes some more advanced concepts li e object-oriented programming and regular e%pressions. It is not a complete coverage of the language. The tutorial was created on &buntu 'inu%.

Ruby

Ruby is a dynamic, reflective, general-purpose object-oriented programming language. The original author is a Japanese programmer Yukihiro Matsumoto. Ruby first appeared in "##$. Ruby supports various programming paradigms. This includes object orientation, reflection, imperative and reflective programming. Ruby language was influenced primarily by (erl, )malltal , *iffel, and 'isp. &nli e languages li e Java, +, or +, Ruby has no official specification. Instead the original + implementation of the Ruby language serves as a de facto reference. There are other implementations of the Ruby language li e JRuby, IronRuby or !acRuby. The official web site is ruby-lang.org.

Popularity
There are hundreds of programming languages in use today. Ruby belongs to the most popular ones. The langpop.com and tiobe sites put Ruby around the "-th place. Ruby on "

Rails, a very popular web application framewor is the first iller application created in Ruby.

Interactive interpreter
.e can run Ruby statements in a script or in an interactive interpreter. In this tutorial, we will use the interactive Ruby session to demonstrate some smaller code fragments. 'arger code e%amples are to be put in Ruby scripts.
$ irb irb(main):001:0> puts RUBY_VERSION 1.8. !> ni"

This is an e%ample of the Ruby interactive session. .e print the value of a special R&/Y01*R)I23 constant to the console. It is set to the version of the current Ruby in use.

Ruby scripts
.e will have our first simple e%ample of a Ruby script.
#$%usr%bin%rub& # 'irst.rb puts ()*is is Rub&(

In this script, we print a message to the console.


#$%usr%bin%rub&

*very script in the &3I4 starts with a shebang. The shebang is the first two characters in the script5 #!. The shebang is followed by the path to the interpreter, which will e%ecute our script. The 6usr6bin6 is the most common location for the Ruby interpreter. It could also be located in 6usr6local6bin6 or elsewhere.
# 'irst.rb

+omments in Ruby are preceded by a , character.


puts ()*is is Rub&(

The puts method prints a string to the console.


$ +*i,* rub& %usr%bin%rub&

The path to the Ruby interpreter can be found using the which command.
$ ,*m-. /0 'irst.rb $ .%'irst.rb )*is is Rub&

.e ma e the script e%ecutable with the chmod command. 8nd e%ecute it.

Sources
The following sources were used to create this tutorial5

ruby-lang.org ruby-doc.org Ruby article on wi ipedia.org ruby.runpaint.org

In this part of the Ruby tutorial, we have introduced the Ruby language.

Ruby lexical structure


+omputer languages, li e human languages, have a le%ical structure. 8 source code of a Ruby program consists of to ens. To ens are atomic code elements. In Ruby language we have various le%ical structures, such as comments, variables, literals, white spaces, operators, delimiters and eywords.

Comments
Comments are used by humans to clarify the source code. There are two types of comments in Ruby. )ingle-line and multi-line comments. )ingle-line comments begin with the , character. !ulti-line comments are put between the 9begin and 9end to ens.
#$%usr%bin%rub& !b12in ,-mm1nts.rb aut*-r 3an B-.nar 41t5-.1 6011 !1n. # prints m1ssa21 t- t*1 t1rmina" puts (5-mm1nts 10amp"1(

8n e%ample showing both types of comments. +omments are ignored by the Ruby interpreter.
!b12in ,-mm1nts.rb aut*-r 3an B-.nar 41t5-.1 6011 !1n.

This is an e%ample of a multi-line comment. The two to ens must start at the beginning of the line.

White space
.hite space in Ruby is used to separate to ens and terminate statements in the source file. It is also used to improve readability of the source code.
i' tru1 t*1n puts (7 m1ssa21( 1n.

.hite spaces are re;uired in some places. <or e%ample between the i' eyword and the tru1 eyword. 2r between the puts method and the actual string. In other places, it is forbidden. It cannot be present in variable identifiers or language eywords.
a!1 b ! 6 , ! 8

The amount of space put between to ens is irrelevant for the Ruby interpreter. =owever, it is important to have one style throughout the project.
#$%usr%bin%rub& 0 ! 9 / 8 puts 0 0 ! 9 puts 0 0 ! 9 / puts 0 8 / 8

8 new line, a form of a white space, can be used to terminate statements.


0 ! 9 / 8

In the first case, we have one statement. The sum of the addition is assigned to the % variable. The variable holds >.
0 ! 9 / 8

3ow, there are two statements. The first statement is terminated with a newline. The % variable is $. There is another statement, ?:, which has no effect.
0 ! 9 / 8

<inally, we have one statement. The newline is preceded with a ? binary operator, so the interpreter e%pects another value. It loo s on the second line. In this case, it ta es both lines as one statement. The % variable is >.
$ .%+*it1spa,1.rb

8 9 8

2utput.

Variables
8 variable is an identifier, which holds a value. In programming we say, that we assign a value to a variable. Technically spea ing, a variable is a reference to a computer memory, where the value is stored. In Ruby, a variable can hold a string, a number or various objects. 1ariables can be assigned different values over time. 1ariable names in Ruby are created from alfanumeric characters and underscore A0B character. 8 variable cannot begin with a number. The interpreter can easier distinguish between a literal number and a variable. 1ariable names cannot begin with a capital letter. If an identifier begins with a capital letter, it is considered to be a constant in Ruby.
Va"u1 :a"u16 ,-mpan&_nam1

These are valid variable names.


16Va" 100$ 'irst;nam1

These are e%amples of invalid variable names. 1ariable names may be preceded by two special characters, C and D. They are used to create a specific variable scope. The variables are case sensitive. This means, that pri,1, and pRi,1 are two different identifiers.
#$%usr%bin%rub& numb1r ! 10 numBER ! 11 puts numb1r< numBER

In our script, we assign two numeric values to two identifiers. number and num/*R are two different variables.
$ .%,as1.rb 10 11

This is the output of the script.

Constants
+onstants are value holders, which hold only one value over time. 8n identifier with a first uppercase letter is a constant in Ruby. In programming it is a convention to write all characters of a constant in uppercase. &nli e in other languages, Ruby does not enforce constants to have only one value over time. The interpreter only issues a warning if we assign a new value to an e%isting constant.
#$%usr%bin%rub& Nam1 ! (R-b1rt( 7=E ! 68 Nam1 ! (3u"i1t(

In the above e%ample, we create two constants. 2ne of the constants is redefined later.
Nam1 ! (R-b1rt( 7=E ! 68

Two constants are created. .hen the identifierEs name begins with an uppercase letter, than we have a constant in Ruby. /y convention, constants are usually written in upperacse letters.
Nam1 ! (3u"i1t(

.e redefine a constant. .hich issues a warning.


$ .%,-nstants.rb .%,-nstants.rb:>: +arnin2: a"r1a.& initia"i?1. ,-nstant Nam1

Running the e%ample.

A literal
8 literal is a te%tual representation of a particular value of a type. 'iteral types include boolean, integer, floating point, string, character, and date. Technically, a literal will be assigned a value at compile time, while a variable will be assigned at runtime.
a21 ! 6@ nati-na"it& ! (Aun2arian(

=ere we assign two literals to variables. 3umber 7# and string F=ungarianF are literals.
#$%usr%bin%rub& r1Buir1 C.at1C sn2 ! tru1 nam1 ! (3am1s( D-b ! ni" +1i2*t ! >8.9 b-rn ! Eat1.pars1((N-:1mb1r 16< 1@8>()

puts (Ais nam1 is #Fnam1G( i' sn2 !! tru1 puts (A1 is sin2"1( 1"s1 puts (A1 is in a r1"ati-ns*ip( 1n. puts (Ais D-b is #FD-bG( puts (A1 +1i2*s #F+1i2*tG Hi"-2rams( puts (A1 +as b-rn in #Fb-rnG(

In the above e%ample, we have multiple literals. The bool literal may have value true or false. James is a string literal. The nil is an absense of a value. G>.$ is a floating point literal. <inally, the 3ovember "7, "#>H is a date literal.
$ .%"it1ra"s.rb Ais nam1 is 3am1s A1 is sin2"1 Ais D-b is A1 +1i2*s >8.9 Hi"-2rams A1 +as b-rn in 1@8>;11;16

This is the output of the literals.rb script.

Blocks
Ruby statements are often organiIed into bloc s of code. 8 code bloc can be delimited using J K characters or .-, 1n. eywords.
#$%usr%bin%rub& puts I6< ;1< ;J< 0K..1"1t1_i' F L0L 0 M 0 G I1< 6< 8K.1a,* .- L1L puts 1 1n.

In the e%ample, we show two code bloc s. <low control of Ruby code is often done with the i' eyword. The eyword is followed by a bloc of code. In this case a bloc of code is delimited by t*1n, 1n. eywords, where the first eyword is optional.
#$%usr%bin%rub& i' tru1 t*1n puts (Rub& "an2ua21( puts (Rub& s,ript( 1n.

In the above e%ample, we have a simple bloc of code. It has two statements. The bloc is delimited by t*1n, 1n. eywords. The t*1n eyword can be omitted.

Sigils
)igils C, D are special characters that denote a scope in a variable. The C is used for global variables, D for instance variables and DD for class variables.
$,ar_nam1 ! (N1u21-t( Os1a_nam1 ! (B"a,H s1a( OOsp1,i1s ! (5at(

)igils are always placed at the beginning of the variable identifier.

Operators
8n operator is a symbol used to perform an action on some value. Aanswers.comB
$ MM !! M /! an. / >> !!! M! Q! -r ; S ! $! P L R! Q M!> .. SS T %! QQ >! ... LL ;! % > n-t R

QQ! U:

This is a list of operators available in Ruby language. .e will tal about operators later in the tutorial.

elimiters
8 delimiter is a se;uence of one or more characters used to specify the boundary between separate, independent regions in plain te%t or other data stream. Awi ipediaB
( ) I < V C #$%usr%bin%rub& K ( F L G L

nam1 ! (3an1( -,,upati-n ! CStu.1ntC numb1rs ! I 6< 8< 9< 8< >< 6 K puts nam1V puts -,,upati-n puts numb1rsI6K numb1rs.1a,* F LiL puts i G puts ( 6 / 8 ) Q 9

In the above e%ample, we show the usage of various Ruby delimiters.


nam1 ! (3an1( -,,upati-n ! CStu.1ntC

)ingle and double ;uotes are used to delimit a string in Ruby.


numb1rs ! I 6< 8< 9< 8< >< 6 K

The s;uare brac ets are used to set boundaries for an array. The commas are used to separate items in the array. >

puts nam1V puts -,,upati-n

The semicolon is used in Ruby to separate two statements in a Ruby source code.
puts numb1rsI6K

Lelimiters can be used in different conte%ts. =ere the s;uare brac ets are used to access an item in the array.
numb1rs.1a,* F LiL puts i G

+urly brac ets are used to define a bloc of code. (ipes are used to define an element, which is filled with a current array item for each loop cycle.
puts ( 6 / 8 ) Q 9

(arentheses can be used to alter the evaluation of an e%pression.

!ey"or#s
8 eyword is a reserved word in the Ruby programming language. Meywords are used to perform a specific tas in the computer program. <or e%ample, print a value to the console, do repetitive tas s or perform logical operations. 8 programmer cannot use a eyword as an ordinary variable.
a"ias ,"ass ENE in r1.t*1n +*i"1 an. .1' 1n. m-.u"1 r1s,u1 tru1 &i1". BE=IN .1'in1.U 1nsur1 n10t r1tr& un.1' b12in .'a"s1 ni" r1turn un"1ss br1aH 1"s1 '-r n-t s1"' unti" ,as1 1"si' i' -r sup1r +*1n

This is a list of Ruby eywords. This was the Ruby le%ical structure.

Basics
In this part of the Ruby tutorial, we will cover basic programming concepts of the Ruby language. .e introduce the very basic programs. .e will wor with variables, constants and basic data types. .e will read and write to the consoleN we will mention variable interpolation. .e start with a very simple code e%ample.
#$%usr%bin%rub& puts ()*is is Rub&(

This is simple Ruby script. It will print FThis is RubyF message to the console.

#$%usr%bin%rub&

This is a path to the Ruby interpreter, which will e%ecute the script.
puts ()*is is Rub&(

The puts is a Ruby eyword, which prints its argument to the terminal. In our case the argument is a string message, delimeted by double ;outes.
$ .%'irst.rb )*is is Rub&

*%ecuting the script gives the above output.

.e can read values from the terminal. ATerminal and console are synonymsB
#$%usr%bin%rub& print (W*at is &-ur nam1U ( nam1 ! 21ts puts (A1""- #Fnam1G(

The second program will read a value from a console and print it.
print (W*at is &-ur nam1U (

The print eyword prints a message to the console. The difference between the print and puts eywords is that the print eyword does not start a new line. The puts eyword automatically starts a new line.
nam1 ! 21ts

=ere we read an input from the user and store it in the name variable. The 21ts is a method, which in our case reads a line from the terminal. It is one of the methods that we have at our disposal by default.
puts (A1""- #Fnam1G(

In this code line, we perform variable interpolation. Variable interpolation is replacing variables with their values inside string literals. 8nother names for variable interpolation are5 variable substitution and variable e%pansion.
$ .%nam1.rb W*at is &-ur nam1U 3an A1""- 3an

This is the output of the second program.

"-

Ruby code can be run from the command line. This is inspired by (erl one-liners, where small fragments of code are run to do some petit tas s.
$ rub& ;1 (puts RUBY_VERSION( 1.@.8

The -e option tells Ruby to e%ecute Ruby code specified on the line and not to search for a Ruby file name. 2ur e%ample prints the version of the Ruby interpreter to the terminal.

Ruby interpreter has a -c option which chec s the synta% of the code. If this option is used, the code is not e%ecuted. If there is no synta% error, Ruby will print F)ynta% 2MF to the standard output.
#$%usr%bin%rub& ,"ass B1in2 1n. m ! )1st.n1+ p m

In the above e%ample, there is a synta% error. If we put class and end eywords on one line, we must also use the semicolon N character.
$ rub& ;, s&nta0_,*1,H.rb s&nta0_,*1,H.rb:8: s&nta0 1rr-r< un10p1,t1. H1&+-r._1n.< 10p1,tin2 CMC -r CVC -r CXnC s&nta0_,*1,H.rb:>: s&nta0 1rr-r< un10p1,t1. $1n.< 10p1,tin2 H1&+-r._1n.

The synta% error was found. If we put a semicolon after the /eing class, the error message will disappear.

Comman# line arguments


Ruby programs can receive command line arguments. They follow the name of the program, when we run it.
#$%usr%bin%rub& puts 7R=V

+ommand line arguments specified after the file name are available to a Ruby program in the global array named 7R=V.
puts 7R=V

=ere we print all the command line arguments to the terminal.


$ .%ar2s.rb 1 6 8 1 6 8

""

.e provide three numbers as command line arguments and these are printed to the console.

In the following e%ample, we wil print all arguments and also the script name.
#$%usr%bin%rub& puts $0 puts $Q

The C- global variable contains the name of the script being e%ecuted. Olobal variables in Ruby begin with the C character. The CP is another global variable. It is a synonym for the 8RO1 variable. It contains command line arguments given for the current script.
$ .%ar2s6.rb Rub& N&t*-n N1r" .%ar2s6.rb Rub& N&t*-n N1r"

The args7.rb script receives three strings. The name of the script and the three arguments are printed to the terminal.

Variables an# constants


8 variable is a place to store data. 8 variable has a name and a data type. Lata types are different types of values. Integers, strings and floating point numbers are e%amples of data types. Ruby is a dynamic language. This means that we do not have to Aand cannotB declare a variable to be of a certain data type. Instead, the Ruby interpreter determines the data type at the moment of the assignment. !oreover, a variable can contain different values and also different types of values over time. This differs from languages that are strongly types, li e Java, + or (ascal. &nli e variables, constants AshouldB retain their values. 2nce initialiIed, they cannot be modified. In Ruby however, it is possible to change the value of a constant. In such a case a warning is issued.
#$%usr%bin%rub& ,it& ! (N1+ Y-rH( nam1 ! (Nau"(V a21 ! 89 nati-na"it& ! (7m1ri,an( puts puts puts puts ,it& nam1 a21 nati-na"it&

,it& ! (Y-n.-n( puts ,it&

In the above e%ample, we wor with four variables.


,it& ! (N1+ Y-rH(

"7

.e assign a string value to the city variable. The variable is dynamically created.
nam1 ! (Nau"(V a21 ! 89

.e create two more variables. .e can put two statements into one line. <or readability, however, each statement should be on a separate line.
puts puts puts puts ,it& nam1 a21 nati-na"it&

.e print the values of the variables to the terminal.


,it& ! (Y-n.-n(

.e assign a new value to the city variable.


$ .%:ariab"1s.rb N1+ Y-rH Nau" 89 7m1ri,an Y-n.-n

2utput of the e%ample.

Constants 8s we already said, constants store one value over the time. &nli e in other languages, this rule is however not enforced in Ruby.
#$%usr%bin%rub& WIE)A ! 100 AEI=A) ! 190 :ar ! J0 puts :ar :ar ! 90 puts :ar puts WIE)A WIE)A ! 110 puts WIE)A

In this e%ample, we declare two constants and one variable.


WIE)A ! 100 AEI=A) ! 190

+onstants in ruby begin with capital letter. It is a common practice to write all characters in uppercase letters.
:ar ! J0

":

puts :ar :ar ! 90

.e declare and initialiIe a variable. 'ater, we assign a new value to the variable. It is legal.
WIE)A ! 110

.e assign a new value to a constant. +onstants should not be modified, once they are created. 2therwise it has no meaning to create a constant. The Ruby interpreter will issue a warning.
$ .%,-nstants.rb J0 90 100 .%,-nstants.rb:18: +arnin2: a"r1a.& initia"i?1. ,-nstant WIE)A 110

2utput of the script.

Variable interpolation
Variable interpolation is replacing variables with their values inside string literals. 2ther names for variable interpolation are variable substitution and variable e%pansion.
#$%usr%bin%rub& a21 ! 8J nam1 ! (Wi""iam( puts (#Fnam1G is #Fa21G &1ars -".(

In Ruby, strings are immutable. .e cannot modify an e%isting string. 1ariable interpolation happens during string creation.
a21 ! 8J nam1 ! (Wi""iam(

=ere we declare two variables.


puts (#Fnam1G is #Fa21G &1ars -".(

The string message has double ;uotes as its boundaries. .hen we put a variable name between the ,J and K characters, the variable is interpolated5 that is, replaced with its value.
$ .%int1rp-"ati-n.rb Wi""iam is 8J &1ars -".

2utput. This chapter covered some basics of the Ruby language.

"@

Variables in Ruby
In this part of the Ruby tutorial, we will e%amine variables in more detail. 8 variable is a place to store data. *ach variable is given a uni;ue name. There are some naming conventions which apply to variable names. 1ariables hold objects. !ore precisely, they refer to a specific object located in computer memory. *ach object is of certain data type. There are built-in data types and there are custom-built data types. Ruby belongs to the family of dynamic languages. &nli e strongly typed languages li e Java, + or (ascal, dynamic languages do not declare a variable to be of certain data type. Instead of that, the interpreter determines the data type at the moment of the assignment. 1ariables in Ruby can contain different values and different types of values over time.
#$%usr%bin%rub& i ! 9 puts i i ! puts i

The term variable comes from the fact that variables, unli e constants, can ta e different values over time. In the e%ample above there is a variable called i. <irst it is assigned a value $, later a different value H.

$aming conventions
Ruby, li e any other programming language, has some naming conventions for variable indentifiers. Ruby is a case sensitive language. It means that age and 8ge are two different variable names. !ost languages are case sensitive. /8)I+ is an e%ceptionN it is a case insensitive language. .hile we can create different names by changing the case of the characters, this practice is not recommended.
#$%usr%bin%rub& i p I p ! 9 i ! I

The code e%ample defines two variables. I and i. They hold different values.
.%,as1.rb 9

2utput of the case.rb e%ample.

"$

1ariable names in Ruby can be created from alpfanumeric characters and the underscore A0B character. 8 variable cannot begin with a number. This ma es it easier for the interpreter to distinguish a literal number from a variable. 1ariable names cannot begin with a capital letter. If an identifier begins with a capital letter, it is considered to be a constant in Ruby.
#$%usr%bin%rub& nam1 ! (3an1( p"a,1O'Birt* ! (Bratis"a:a( p"a,1O'Birt* ! (Z-si,1( 'a:-rit1_s1as-n ! (autumn( n1 ! 6 n6 ! J n8 ! p nam1< p"a,1O'Birt*< 'a:-rit1_s1as-n p n1< n6< n8

In this script, we show a few valid variable names.

1ariable names should be meaning ul. It is a good programming practice to choose descriptive names for variables. The programs are more readable then.
#$%usr%bin%rub& nam1 ! (3an1( p"a,1_-'_birt* ! (Bratis"a:a( -,,upati-n ! (stu.1nt( i ! 9 +*i"1 i > 0 .puts nam1 i ;! 1 1n.

The script shows three descriptive variable names. The place0of0birth is more descriptive to a programmer than e.g. pob. It is generally considered 2M to choose simple variable names in loops.

Sigils
1ariable identifiers can start with special characters also called sigils. 8 sigil is a symbol attached to an identifier. 1ariable sigils in Ruby denote variable scope. This is in contrast to (erl, where sigils denote data type. The Ruby variable sigils are C and D.
#$%usr%bin%rub& tr11_nam1 $,ar_nam1 Os1a_nam1 OOsp1,i1s ! ! ! ! (pin1( (N1u21-t( (B"a,H s1a( (5at(

p "-,a"_:ariab"1s p 2"-ba"_:ariab"1s.in,"u.1U :$,ar_nam1

"G

p s1"'.instan,1_:ariab"1s p ObD1,t.,"ass_:ariab"1s

.e have four variables with different scopes. 8 scope is the range in which a variable can be referenced. .e use special built-in methods to determine the scope of the variables.
tr11_nam1 ! (pin1(

8 variable without a sigil is a local variable. 8 local variable is valid only locally5 e.g., inside a method, bloc or a module.
$,ar_nam1 ! (N1u21-t(

Olobal variables start with C character. They are valid everywhere. The use of global variables should be limited in programs.
Os1a_nam1 ! (B"a,H s1a(

8 variable name starting with a D sigil is an instance variable. This variable is valid inside an object.
OOsp1,i1s ! (5at(

<inally we have a class variable. This variable is valid for all instances of a specific class.
p "-,a"_:ariab"1s

The "-,a"_:ariab"1s gives an array of all local variables defined in a specific conte%t. 2ur conte%t is Ruby toplevel.
p 2"-ba"_:ariab"1s.in,"u.1U :$,ar_nam1

)imilarly, the 2"-ba"_:ariab"1s produces an array of globals. .e do not print all globals to the terminal, because there are many of them. *ach Ruby script starts with a bunch of predefined variables. Instead of that, we call the in,"u.1U method of the array to chec if our global is defined in the array. 8lso note that we are referencing variables with their symbols. A)ymbols start with a colon character.B
p s1"'.instan,1_:ariab"1s

The s1"' pseudo variable points to the receiver of the instan,1_:ariab"1s method. The receiver in our case is the main, the Ruby toplevel e%ecution area.
p ObD1,t.,"ass_:ariab"1s

<inally we have an array of class variables. The main is an instance of the ObD1,t class.
$ .%si2i"s.rb I:tr11_nam1K tru1 I:Os1a_nam1K I:OOsp1,i1sK

"H

2utput of the e%ample. .e see symbolic names of the variables.

%ocal variables
'ocal variables are variables that are valid within a local area of a Ruby source code. This area is also referred to as local scope. 'ocal variables e%ist within the definition of a Ruby module, method, class.
#$%usr%bin%rub& .1' m1t*-.1 0 ! 9 p 0 1n. m1t*-.1 p 0

.e have a method called method", which has one variable. The variable is local. This means that it is valid only within the method definition. .e can refer to the % variable only between the method name and the 1n. eyword.
.1' m1t*-.1 0 ! 9 p 0 1n.

This is the definition of the method" method. Inside the method, we create a local % variable. .e print the value of the variable to the terminal.
m1t*-.1

The method is called.


p 0

.e try to refer to a local variable outside the definition of the method. This leads to a Nam1Err-r. The Ruby interpreter cannot find such identifier.
$ .%"-,a"s.rb 9 .%"-,a"s.rb:11:in [Mmain>C: un.1'in1. "-,a" :ariab"1 -r m1t*-. [0C '-r main:ObD1,t (Nam1Err-r)

Running the e%ample gives the above output.

The following e%ample is a slight modification of a previous e%ample.


#$%usr%bin%rub& 0 ! 9

">

.1' m1t*-.1 0 ! 10 p 0 1n. m1t*-.1 p 0

.e have two % variables. 2ne is defined inside the method" and the other one is defined outside. They are two distinct local variables. They do not clash with each other.
0 ! 9

.e have created a local % variable, which holds value $. The variable is valid in the local scope of the main e%ecution area. It is not valid inside the method".
.1' m1t*-.1 0 ! 10 p 0 1n.

Inside the definition of the method" a new local variable % is defined. It has value "-. It e%ists in the body of the method" method. 8fter the 1n. eyword it ceases to e%ist.
$ .%"-,a"s6.rb 10 9

2utput.

If a method ta es parameters, a local variable is created for each of these parameters.


#$%usr%bin%rub& .1' r1,tan2"1_ar1a a< b puts "-,a"_:ariab"1s r1turn a Q b 1n. puts r1,tan2"1_ar1a 9< >

.e have a method definition, which ta es two values. The method returns the area of a rectangle.
.1' r1,tan2"1_ar1a a< b puts "-,a"_:ariab"1s r1turn a Q b 1n.

The rectangle0area method ta es two parameters. They are the sides of a rectangle, for which we calculate the area. Two local variables are automatically created for identifiers a and b. .e call the "-,a"_:ariab"1s method to see what local variables we have in the method. "#

puts r1,tan2"1_ar1a 9< >

=ere we pass two values to the method rectangle0area. The values will be assigned to two local variables, created inside the method.
$ .%param1t1rs.rb a b 80

The output shows three things. The first two are the names of the local variables within the rectangle0area method. The third is the calculated area of the given rectangle.

8 method may be defined inside another method. The inner methods have their own local variables.
#$%usr%bin%rub& .1' m1t*-.1 .1' m1t*-.6 .1' m1t*-.8 m9< m> ! 8 puts (Y1:1" 8( puts "-,a"_:ariab"1s 1n. m8< mJ ! 8 puts (Y1:1" 6( puts "-,a"_:ariab"1s m1t*-.8 1n. m1< m6 ! 8 puts (Y1:1" 1( puts "-,a"_:ariab"1s m1t*-.6 1n. m1t*-.1

In this Ruby script, we create three methods. The method7 and method: are inner methods. The method7 is defined inside the method" and the method: is defined inside method7. *ach methodEs local variables are only accessible in the method in which they were defined.
$ .%"ms.rb Y1:1" 1 m1 m6 Y1:1" 6 m8 mJ Y1:1" 8 m9

7-

m>

<rom the output we can see that method" has two local variables, m" and m7. The inner method7 has local variables m:, m@. The method:, the innermost method, has local variables m$, mG.

The last e%ample of this section will present several demonstrations of a local scope.
m-.u"1 \-.u"1\ m1< m6 ! J puts (Insi.1 m-.u"1( puts "-,a"_:ariab"1s

1n.

.1' m1t*-.1 :< + ! 8 puts (Insi.1 m1t*-.( puts "-,a"_:ariab"1s 1n. ,"ass S-m1 0< & ! 6 puts (Insi.1 ,"ass( puts "-,a"_:ariab"1s 1n. m1t*-.1 t1< t6 ! puts (Insi.1 t-p"1:1"( puts "-,a"_:ariab"1s

In the code e%ample, we create local variables inside a module, method, class and toplevel. The "-,a"_:ariab"1s is a method of the Z1rn1" module that returns all current local variables.
m-.u"1 \-.u"1\ m1< m6 ! J puts (Insi.1 m-.u"1( puts "-,a"_:ariab"1s 1n.

8 module is a collection of methods and constants. .e create two local variables m" and m7.
.1' m1t*-.1 :< + ! 8 puts (Insi.1 m1t*-.( puts "-,a"_:ariab"1s 1n.

Two local variables, v and w, are created in method". 7"

,"ass S-m1 0< & ! 6 puts (Insi.1 ,"ass( puts "-,a"_:ariab"1s 1n.

The %, y local variables are created inside the definition of the )ome class.
t1< t6 !

<inally, two local variables that belong to the Ruby toplevelEs local scope are created.
$ .%"-,a"s8.rb Insi.1 m-.u"1 m1 m6 Insi.1 ,"ass 0 & Insi.1 m1t*-. : + Insi.1 t-p"1:1" t1 t6

The output shows local variables for each local scope.

Global variables
Olobal variables are valid everywhere in the script. They start with a C sigil in Ruby. The use of global variables is discouraged. Olobal variables easily lead to many programming errors. Olobal variables should be used only when there is a reason to do so. Instead of global variables, programmers are advised to use local variables whenever possible.
#$%usr%bin%rub& $2b ! > m-.u"1 \-.u"1\ puts (Insi.1 m-.u"1( puts $2b 1n. .1' m1t*-.1 puts (Insi.1 m1t*-.( puts $2b 1n. ,"ass S-m1 puts (Insi.1 ,"ass( puts $2b 1n.

77

m1t*-.1 puts (Insi.1 t-p"1:1"( puts $2b puts 2"-ba"_:ariab"1s.in,"u.1U :$2b

In the e%ample we have a global variable Cgb. .e show that the variable can be referenced in a module, method, class and a toplevel. The global variable Cgb is valid in all these entities.
$2b ! >

8 global variable Cgb is createdN it has value G.


m-.u"1 \-.u"1\ puts (Insi.1 m-.u"1( puts $2b 1n.

Inside a moduleEs definition we print the global variableEs value.


.1' m1t*-.1 puts (Insi.1 m1t*-.( puts $2b 1n.

Inside the defition of a method we print the value of the global variable.
,"ass S-m1 puts (Insi.1 ,"ass( puts $2b 1n.

Inside the defition of a class we print the value of the global variable.
puts $2b puts 2"-ba"_:ariab"1s.in,"u.1U :$2b

<inally, in the toplevel e%ecution area we print the global variableEs value and whether the variable is in the array produced by the 2"-ba"_:ariab"1s method.
$ .%2"-ba"s.rb Insi.1 m-.u"1 > Insi.1 ,"ass > Insi.1 m1t*-. > Insi.1 t-p"1:1" > tru1

The output of the e%ample confirms that the global variable is accessible everywhere.

7:

.hen a Ruby script starts, it has access to multiple predefined global variables. These globals are not considered harmful and help solve common programming jobs.
#$%usr%bin%rub& p $YO7E_N7)A p $:

The script shows a $YO7E_N7)A global variable. The variable lists directories which are searched by "-a. and r1Buir1 methods. The $: is a short synonym for the $YO7E_N7)A name. !ore global variables will be presented in the (redefined variables section of this chapter.

Instance& class variables


In this section we will briefly cover instance and class variables. They will be described in 2bject-oriented programming chapter in more detail. !nstance variables are variables that belong to a particular object instance. *ach object has its own object variables. Instance variables start with a D sigil. Class variables belong to a specific class. 8ll objects created from a particular class share class variables. +lass variables start with DD characters.
#$%usr%bin%rub& ,"ass B1in2 OOis ! tru1 .1' initia"i?1 nm Onam1 ! nm 1n. .1' t-_s ()*is is #FOnam1G( 1n. .1' .-1s_10istU OOis 1n. 1n. b1 ! B1in2.n1+ (B1in2 1( b6 ! B1in2.n1+ (B1in2 6( b8 ! B1in2.n1+ (B1in2 8( p b1< b6< b8 p b1..-1s_10istU p b6..-1s_10istU p b8..-1s_10istU

.e create a custom /eing class. The /eing class has one class and one instance variable.

7@

,"ass B1in2 OOis ! tru1

The DDis is an class variable. This variable is shared by all instances of the /eing class. The logic of this e%ample is that /eing is and 3ot/eing is not.
.1' initia"i?1 nm Onam1 ! nm 1n.

The initia"i?1 method is a constructor. The method is called when the object is created. 8 Dname instance variable is created. This variable is specific to a concrete object.
.1' t-_s ()*is is #FOnam1G( 1n.

The t-_s method is called, when the object is a parameter of a printing method, li e p or puts. In our case, the method gives a short human readable description of the object.
.1' .-1s_10istU OOis 1n.

The does0e%istQ method returns the class variable.


b1 ! B1in2.n1+ (B1in2 1( b6 ! B1in2.n1+ (B1in2 6( b8 ! B1in2.n1+ (B1in2 8(

Three objects from the /eing class are created. *ach of the objects has a different name. The name of the object will be stored in the instance method, which is uni;ue to each object instance. This will be used in the t-_s method, which give a short description of the object.
p b1< b6< b8

The p method ta es the created objects as three parameters. It calls the t-_s method on each of these objects.
p b1..-1s_10istU p b6..-1s_10istU p b8..-1s_10istU

<inally, we call the does0e%istQ method of each of the instances and print their return values. The output of these three methods is the same, because each method returns the class variable.
$ .%i,:ars.rb )*is is B1in2 1 )*is is B1in2 6 )*is is B1in2 8 tru1 tru1

7$

tru1

2utput of the e%ample. The first three messages are uni;ue. The strings are stored in the instance variables of the objects. The true value is the value of the class variable, which is called three times.

'nvironment ( comman#)line variables


The ENV constant gives access to environment variables. It is a Ruby hash. *ach environment variable is a ey to the ENV hash. The 7R=V constant holds command-line argument values. They are passed by the programmer when the script is launched. The 7R=V is an array that stores the arguments as strings. The $Q is an alias to the 7R=V. /oth ENV and 7R=V are global constants.
#$%usr%bin%rub& 7R=V.1a,* .- LaL puts (7r2um1nt: #FaG( 1n.

In the script we loop through the 7R=V array and print each of its values.
$ .%,-mman."in1.rb 1 6 8 7r2um1nt: 1 7r2um1nt: 6 7r2um1nt: 8

.e have given three command-line arguments. They are printed to the console, each on a separate line.

The following e%ample will deal with environment variables.


#$%usr%bin%rub& puts ENVICSAEYYCK puts ENVICY7N=CK puts ENVIC)ER\CK

The script will print values of three environment variables to the terminal. The values depend on the 2) settings of our operating system.
$ .%1n:ir-nm1nt.rb %bin%bas* 1n_US.ut'8 0t1rm

8 sample output.

7G

Pseu#o variables
Ruby has a few variables which are called pseudo variables. They are different from regular variables. .e cannot assign values to pseudo variables. The s1"' is the receiver of the current method. The ni" is the sole instance of the Ni"5"ass. It represents the absense of a value. The tru1 is the sole instance of the )ru15"ass. It represents boolean true. The 'a"s1 is a sole instance of ]a"s15"ass. It represents boolean false. The true and false are values of a boolean datatype. <rom another point of view, they are instances of specific classes. This is because everything in Ruby is an object. This loo s li e unnecessarily complicated. /ut it is the conse;uence of the aforementioned Ruby idiom.
#$%usr%bin%rub& p p p p p p p p s1"' ni" tru1 'a"s1 s1"'.,"ass ni".,"ass tru1.,"ass 'a"s1.,"ass

This is an e%ample of pseudo variables. .e print all four pseudo variables with the p method. Then we find out the class name for all of them.
p s1"'

In this conte%t, the s1"' pseudo variable returns the main e%ecution conte%t.
$ .%ps1u.-.rb main ni" tru1 'a"s1 ObD1,t Ni"5"ass )ru15"ass ]a"s15"ass

*%ample output.

In the second e%ample of this section, we will further loo at the s1"'.
#$%usr%bin%rub& ,"ass S-m1 puts s1"' 1n.

7H

,"ass Ot*1r puts s1"' 1n. puts s1"'

8s we have said, the s1"' references the receiver of the current method. The above e%ample shows three e%amples of different receivers.
,"ass S-m1 puts s1"' 1n.

The receiver is the class called )ome.


,"ass Ot*1r puts s1"' 1n.

=ere is another receiver5 a class named 2ther.


puts s1"'

8nd the third receiver is the Ruby toplevel.


$ .%ps1u.-s1"'.rb S-m1 Ot*1r main

*%ample output.

The last e%ample of the section will present other three pseudo variables.
#$%usr%bin%rub& i' tru1 puts ()*is m1ssa21 is s*-+n( 1n. i' 'a"s1 puts ()*is m1ssa21 is n-t s*-+n( 1n. p $nam1 p $a21

The above e%ample shows tru1, 'a"s1 and ni" pseudo variables at wor .
i' tru1 puts ()*is m1ssa21 is s*-+n( 1n.

The tru1 is used in boolean e%pression. The message is always printed.

7>

i' 'a"s1 puts ()*is m1ssa21 is n-t s*-+n( 1n.

This message is never printed. The condition is not met. In the boolean e%pression we always get a negative value.
p $nam1 p $a21

If global values are referenced and have not been initialiIed, they contain the ni" pseudo variable. It stands for the absence of a value.
$ .%ps1u.-6.rb )*is m1ssa21 is s*-+n ni" ni"

2utput of the pseudo7.rb Ruby script.

Pre#e*ine# variables
Ruby has plenty of predefined global variables. This is a heritage of (erl language. Ruby was influenced strongly by (erl. They are accessible when the Ruby script starts. .e have a few e%amples for the predefined Ruby variables.
#$%usr%bin%rub& print (S,ript nam1: (< $0< (Xn( print (5-mman. "in1 ar2um1nts: (< $Q< (Xn( puts (Nr-,1ss numb1r -' t*is s,ript: #F$$G(

Three predefined variables have been used. C-, CP and CC. The C- stores the current script name. The CP variable stores command-line arguments. 8nd the CC stores the (IL Aprocess idB of the script.
$ .%pr1.1'in1..rb 1 6 8 S,ript nam1: .%pr1.1'in1..rb 5-mman. "in1 ar2um1nts: I(1(< (6(< (8(K Nr-,1ss numb1r -' t*is s,ript: 8166

)ample output.

The CQ global variable stores the e%it status of the last e%ecuted child process.
#$%usr%bin%rub& s&st1m C1,*- (Rub&(C puts $U R0I10it C1CK puts $U

7#

.e run two e%ternal child processes and chec their e%it status with the CQ variable.
s&st1m C1,*- (Rub&(C puts $U

.ith the use of the s&st1m method we start a child process. It is an echo bash command, which prints a message to the terminal.
R0I10it C1CK puts $U

In the second case we e%ecute the bash 10it command with status ". This time we use the R% operator which e%ecutes a command between two selected delimiters. .e have chosen ST characters.
$ .%pr1.1'in1.6.rb Rub& pi. 8181 10it 0 pi. 8188 10it 1

The first child process terminates with status -, the second with e%it status ".

The CN variable has the default separator of the sp"it method of the Strin2 class.
#$%usr%bin%rub& str ! (1<6<8<J<9<>< ( p str.sp"it $V ! (<( p str.sp"it

.e use the CN variable to control how the string is cut with the sp"it method. The method ta es a parameter, which tells where the string should be split. If the parameter is omitted, than the value from the CN is used.
$V ! (<( p str.sp"it

.e specify a delimiter for the CN variable. The split method does not ta e a parameter, so the value of CN is used.
$ .%pr1.1'in1.8.rb I(1<6<8<J<9<>< (K I(1(< (6(< (8(< (J(< (9(< (>(< ( (K

In the first case, the string was not split. In the second case, the string was split correctly, as we have intended.

In the final e%ample, we show three global predefined variables that are used with regular e%pressions.

:-

#$%usr%bin%rub& (A1r nam1 is 3an1( !P %nam1% p $[ p $S p $C

.hen we apply the 9U operator on a string, Ruby sets some variables. The CV variable has a string that matched the last last regular e%pression match. The CW has a string preceding CV and the CX has a string following the CV.
$ .%pr1.1'in1.J.rb (A1r ( (nam1( ( is 3an1(

*%ample output. In this part of the Ruby tutorial, we loo ed more deeply at the Ruby variables.

"b#ects in Ruby
In this part of the Ruby tutorial, we will briefly cover the concept of objects in Ruby language. .e will learn more about objects in 22( chapter. I have written this preliminary chapter about objects because many Ruby features might be confusing to newcomers Y especially if they already now any other programming language. Ruby is an object-oriented programming language. This means that in Ruby programs we wor with objects. <rom a language programmerEs point of view a Ruby program is a stream of to ens. These to ens are Ruby eywords, operators, various delimiters or literals. <rom a semantic point of view a Ruby program consists of objects. These objects are created and modified during the lifetime of a Ruby script. There are two inds of objects5 built-in objects and custom objects. /uilt-in objects are predefined objects that all programmers can use. They are available with the core of the Ruby language or from various libraries. +ustom objects are created by application programmers for their application domains. 8ll objects must be created before we can wor with them. .e often use a term object instantiation. It is a synonym for object creation. 2bjects consists of data and methods. Lata is a static part of an object. !ethods form a dynamic part of an object. 2bjects are modified and communicate with each other via methods.
#$%usr%bin%rub& puts (Rub& "an2ua21(

.e have a simple Ruby script. If we are familiar with some procedural language li e (ascal or +, we might see a eyword or a function named puts and its parameter FRuby languageF, which is a string.

:"

Ruby is a pure object-oriented langauge and things are a bit different. The FRuby languageF is a indeed a string, which is a common data type. /ut it is also an object. 8nd as with all objects, we can call its methods. This is a bit different from other languages. The puts is a method. 8 method is a function defined in an object. !ethods do not e%ist on their own. In fact, the puts method is a part of the Z1rn1" module.
#$%usr%bin%rub& Z1rn1".puts (Rub& "an2ua21( Z1rn1".puts (Rub& "an2ua21(.si?1

In the above script, we have two code lines.


Z1rn1".puts (Rub& "an2ua21(

In the first e%ample, we were calling the puts method without the Z1rn1" part, which may be omitted. This saves time and some typing. It is in fact a shorthand call for the Z1rn1".puts formal call. In +, we have 5-ns-"1.+rit1"n and in Java S&st1m.print"n. The idea is the same. !ethods must be associated with some object, or, in case of class methods, a class.
Z1rn1".puts (Rub& "an2ua21(.si?1

In this code line, we print the siIe of the FRuby languageF string to the console. This might be confusing to programmers who have coded in other languages. In other languages, a string is a primitive data type that cannot be modified and that lac s its own methods. In Ruby, a string is a full object and has its own methods. The si?1 method is one of them. It returns the siIe of the string in characters.
$ .%simp"16.rb Rub& "an2ua21 18

2utput of the code e%ample.

In the following e%ample, we will loo at an integer number. )imilarly to a string, an integer value is a Ruby object too.
#$%usr%bin%rub& puts >.-bD1,t_i. puts >.1:1nU puts >.?1r-U puts >.,"ass

In the e%ample, we have an integer G. .e call a few methods on the number.


puts >.-bD1,t_i.

:7

The G is an object. The -bD1,t_i. is a method. The method returns an id associated to the object. *ach object has an id. If we call a method on an object, we must always put a dot character between the two.
puts >.1:1nU puts >.?1r-U

=ere we call two methods on the G object. The 1:1nU returns true if the number is even. 8nd the ?1r-U method returns true, if the number is e;ual to Iero. 3ote that these two methods end with a ;uestion mar . This is a Ruby convention. !ethods that return a boolean value end with a ;uestion mar .
puts >.,"ass

The ,"ass method tells us what ind of object we are dealing with. In our case a G is a
]i0num $ .%-bD1,tnumb1r.rb 18 tru1 'a"s1 ]i0num

+ode e%ample output.

Ob+ect creation
.e have mentioned that Ruby objects must be created before we can wor with them. 2bjects can be created implicitly or e%plicitly. Implicit object creation is object creation by literal notation. *%plicit object creation happens with the use of the n1+ eyword. 8 custom object is always created with the n1+ eyword. +ustom objects must be created from a particular class. 8 class is a template for an object. 8 class can be used to create many objects.
#$%usr%bin%rub& ,"ass B1in2 1n. puts > puts (41t5-.1( s ! Strin2.n1+ (41t5-.1( puts s # n1 ! ]i0num.n1+ > # puts n1 b ! B1in2.n1+ puts b

The code e%ample demonstrates creation of objects in Ruby.


,"ass B1in2

::

1n.

This is a template for our custom object called /eing. The templates are created using the ,"ass eyword. The templates for custom objects are usually placed at the top of the source file or in a separate Ruby files.
puts > puts (41t5-.1(

In these two lines we wor with two objects. 8 GH object of ]i0num type and FZet+odeF string of Strin2 type. GH and F)tringF are what we call literals. 8 literal is a te%tual representation of a particular value of a type. These two objects are created behind the scenes by the Ruby interpreter. )ome objects in Ruby are created by specifying their literals in the source code.
s ! Strin2.n1+ (41t5-.1( puts s

This is the formal way of creating a Strin2 object. It is e;ual to the previous, implicit creation with the string literal.
# n1 ! ]i0num.n1+ > # puts n1

3ot all built-in objects can be created with the n1+ method. This code does not compile. <i%num numbers can be created only by the literal notation so far.
b ! B1in2.n1+ puts b

8nd here we create an instance of the custom object. The puts method gives us a short description of the object.
$ .%-,r1ati-n.rb > 41t5-.1 41t5-.1 #MB1in2:00@@JJ.@,>

2utput of the e%ample.

.e will continue with some formal object creations.


#$%usr%bin%rub& s1 ! Strin2.n1+ (Rub&( puts s1.si?1 puts s1..-+n,as1 a1 ! 7rra&.n1+ a1.pus* 1< 6< 8 puts a1.in,"u.1U 8 puts a1.1mpt&U

:@

r1 ! Ran21.n1+ 1< > puts r1.,"ass puts r1.in,"u.1U J

In the e%ample, we create three built-in objects and call a few of their methods.
s1 ! Strin2.n1+ (Rub&( puts s1.si?1 puts s1..-+n,as1

8 Strin2 object is created. .e call two methods of the object. The si?1 method returns the siIe of the string. The .-+n,as1 method downcases the characters of the string.
a1 ! 7rra&.n1+ a1.pus* 1< 6< 8 puts a1.in,"u.1U 8 puts a1.1mpt&U

=ere we create an 7rra& object and add three numbers to it. 'ater we call two array methods. The in,"u.1U method chec s if a particular value A: in our caseB is part of the array. The 1mpt&U method returns a boolean value indicating whether the array is empty.
r1 ! Ran21.n1+ 1< > puts r1.,"ass puts r1.in,"u.1U J

8n instance of the Ran21 class is created. It contains numbers from " to G. The ,"ass method returns the name of the object. The in,"u.1U method chec s if the number @ is part of the range. It is in our case.
$ .%'-rma".rb J rub& tru1 'a"s1 Ran21 tru1

Running the e%ample gives this output.

Ob+ect literals
8s we have already mentioned, some built-in objects can be created using object literals. The following e%ample shows several object literals.
#$%usr%bin%rub& J.tim1s F puts (Rub&( G puts (Rub&(.si?1 puts (Rub&(..-+n,as1 puts I1< 6< 8K.in,"u.1U 8 puts I1< 6< 8K.1mpt&U

:$

puts :nam1.,"ass puts :nam1.'r-?1nU puts (1..>).,"ass puts (1..>).in,"u.1U J

In the above e%ample we use literal notation to create a <i%num, )trings, 8rrays, )ymbols and Ranges.
J.tim1s F puts (Rub&( G

.e can immediately call a method on an integer literal. This line prints a FRubyF string four times to the terminal.
puts (Rub&(.si?1 puts (Rub&(..-+n,as1

.e call two methods on a )tring object created with a string literal.


puts I1< 6< 8K.in,"u.1U 8 puts I1< 6< 8K.1mpt&U

=ere we create two 8rray objects using array literal notations. .e chec if a specific number is part of the array with the in,"u.1U method. The 1mpt&U method chec s if the array object is empty or not.
puts :nam1.,"ass puts :nam1.'r-?1nU

Two methods of the )ymbol object are called. The symbol is created with a symbol literal, which starts with a colon.
puts (1..>).,"ass puts (1..>).in,"u.1U J

Two Range objects are created using the range literal. .e call two methods on those objects. The ,"ass method returns the name of the class and the in,"u.1U method chec s if a given number is part of the range.
$ .%"it1ra"s.rb Rub& Rub& Rub& Rub& J rub& tru1 'a"s1 S&mb-" 'a"s1 Ran21 tru1

*%ample output. :G

Ob+ect hierarchy
In many object-oriented languages objects form a hierarchy. Ruby has and object hierarchy too. It is a tree-li e hierarchy, where we have parent objects and child objects. 2bjects inherit data and behaviour from their parent objects. 8t the top of the hierarchy there is the root object. It is called the ObD1,t. *ach object in Ruby has at least one parent. In other words, every object inherits from the basic ObD1,t object. 8ccording to the official Ruby documentation, ObD1,t is the root of RubyEs class hierarchy. Its methods are available to all classes unless e%plicitly overridden.
#$%usr%bin%rub& puts puts puts puts puts J.is_aU ObD1,t (Rub&(.is_aU ObD1,t I6< 8K.is_aU ObD1,t :nam1.is_aU ObD1,t (1..6).is_aU ObD1,t

In the above code e%ample we demonstrate that all objects inherit from the root ObD1,t
puts J.is_aU ObD1,t

.e use the is_aU method to chec if a number is a specific type5 in other words, if it inherits from a given object type.
$ .%m-t*1r.rb tru1 tru1 tru1 tru1 tru1

8ll methods return true, which means that all objects inherit from the mother object.

The inheritance hierarchy may be ;uite comple% even for the very basic Ruby objects.
#$%usr%bin%rub& puts >.,"ass puts puts puts puts puts >.is_aU >.is_aU >.is_aU >.is_aU >.is_aU Basi,ObD1,t ObD1,t Num1ri, Int121r ]i0num

puts >.is_aU Bi2num puts >.is_aU Strin2

In this e%ample we shed some light on the inheritance hierarchy of a small numerical value.
puts >.,"ass

:H

.e find out what ind of object is the number value G. The line prints ]i0num to the console.
puts puts puts puts puts >.is_aU >.is_aU >.is_aU >.is_aU >.is_aU Basi,ObD1,t ObD1,t Num1ri, Int121r ]i0num

8ll the above lines return true. 3umber G is a ]i0num. <rom the Ruby documentation we find out that the four other objects are parents of the ]i0num object.
puts >.is_aU Bi2num puts >.is_aU Strin2

The above two objects are not parents for the G value.
$ .%in*1ritan,1.rb ]i0num tru1 tru1 tru1 tru1 tru1 'a"s1 'a"s1

2utput of the e%ample.

.e will finish this section with an e%ample, demonstrating inheritance of custom user objects.
#$%usr%bin%rub& ,"ass B1in2 .1' t-_s ()*is is B1in2( 1n. .1' 21t_i. @ 1n. 1n. ,"ass Yi:in2 M B1in2 .1' t-_s ()*is is Yi:in2( 1n.

1n.

" ! Yi:in2.n1+ puts " puts ".21t_i. puts ".is_aU B1in2

:>

puts ".is_aU ObD1,t puts ".is_aU Basi,ObD1,t

In the e%ample we create two objects, /eing and 'iving. The 'iving object inherits from the /eing. The first is a parent object and the second is a child object.
,"ass B1in2 .1' t-_s ()*is is B1in2( 1n. .1' 21t_i. @ 1n.

1n.

This is a definition of a custom Ruby object. The definition is placed between the ,"ass and 1n. eywords. Inside the definition, we create two methods. .hen the puts method ta es an object as a parameter, it calls its t-_s method. It usually gives a string representation6description of the object.
,"ass Yi:in2 M B1in2 .1' t-_s ()*is is Yi:in2( 1n.

1n.

.e create a definition of the Yi:in2 object. The object inherits from the B1in2 object. The [ operator is used to create inheritance relationships. The t-_s method is overwritten.
" ! Yi:in2.n1+

<rom the above 'iving object template, we create an instance of the 'iving object. The instance of a custom object is created with the n1+ eyword.
puts "

The puts method calls the t-_s method of the 'iving object. =ad the t-_s method not been defined in the 'iving class, the t-_s method of the /eing class would have been called.
puts ".21t_i.

The 'iving object has no get0id method defined. In such a case, the parent classes are chec ed, if there is such a method. In our case the /eing method has such a method and it is called.
puts ".is_aU B1in2

The line returns true. The 'iving is a type of a /eingN e.g. it inherits from the /eing class.
puts ".is_aU ObD1,t puts ".is_aU Basi,ObD1,t

:#

<or our 'iving custom object, we have not e%plicitly specified any relation to the ObD1,t or Basi,ObD1,t objects. Yet the two lines return true. This is because every object in Ruby is automatically a descendant of these two objects. This is done behind the scenes by the Ruby interpreter.
$ .%,ust-min*1r.rb )*is is Yi:in2 @ tru1 tru1 tru1

2utput of the e%ample.

Ruby toplevel
Ruby has a specific object referred to as Ruby toplevel. It is a default e%ecution environment defined outside any other conte%t li e class or module definition. The toplevelEs name is main. It is an instance of the ObD1,t type. There is a local space associated with main, where all local variables reside.
#$%usr%bin%rub& n1 ! 8 n6 ! 9 puts "-,a"_:ariab"1s Z1rn1".puts s1"' puts s1"'.,"ass

This is the first e%ample describing the Ruby toplevel.


n1 ! 8 n6 ! 9

=ere we have defined two numeric variables. These variables are local to the toplevel.
puts "-,a"_:ariab"1s

=ere we produce a list of all local variables. The "-,a"_:ariab"1s is a method of the Z1rn1" module, which is mi%ed into each ObD1,t, including the toplevel object.
Z1rn1".puts s1"'

The s1"' is a Ruby pseudo variable. It returns the current object receiver. The line prints FmainF to the console. It is the name for the Ruby toplevel. The Z1rn1" part of the Z1rn1".puts code can be omitted. /y fully specifying the name we show that the puts method belongs to the Z1rn1" module.
puts s1"'.,"ass

@-

The line prints the ,"ass of the toplevel. .e get the object type of the toplevel. It is the ObD1,t, which is the root of RubyEs class hierarchy.
$ .%t-p"1:1".rb n1 n6 main ObD1,t

This is the output of the e%ample. The n", n7 are the local variables associated with toplevel. The main is the name given for the Ruby toplevel e%ecution environment. <inally, 2bject is the type of the toplevel.

.e will have another e%ample related to the Ruby toplevel.


#$%usr%bin%rub& Onam1 ! (3an1( Oa21 ! 1 .1' in'(#FOnam1G is #FOa21G &1ars -".( 1n. puts s1"'.instan,1_:ariab"1s puts s1"'.pri:at1_m1t*-.s.in,"u.1U :in'puts in'-

.e show instance variables and methods that belong to the toplevel environment.
Onam1 ! (3an1( Oa21 ! 1

.e define two instance variables. Instance variables begin with the D character in Ruby. Instance variables belong to a specific object instance. In this case, they belong to the Ruby toplevel.
.1' in'(#FOnam1G is #FOa21G &1ars -".( 1n.

This is a method definition. *ach method must belong to some object. This method belongs to the toplevel object. 8ll toplevel methods are private. 8ccess to private methods is restricted.
puts s1"'.instan,1_:ariab"1s

The instan,1_:ariab"1s method prints all instance variables of the self, which points to the Ruby toplevel in this conte%t.
puts s1"'.pri:at1_m1t*-.s.in,"u.1U :in'-

@"

8ll toplevel methods are automatically private. The pri:at1_m1t*-.s returns all private methods of the object. )ince there are many methods, we call the in,"u.1U method to chec if the info method is among them. 3ote that we refer to the info method by its symbolic name.
$ .%t-p"1:1"6.rb Onam1 Oa21 tru1 3an1 is 1 &1ars -".

*%ample output. This chapter covered some basics of the objects in Ruby language.

Ruby data types


In this part of the Ruby tutorial, we will tal about data types. +omputer programs of all sorts, including spreadsheets, te%t editors, calculators and chat clients, wor with data. Tools to wor with various data types are essential part of a modern computer language. 8 data type is a set of values, and the allowable operations on those values. Ruby has several data types. 8ll data types are based on classes. The following are the data types recogniIed in Ruby5

/ooleans )ymbols 3umbers )trings 8rrays =ashes

In the following e%ample, we have all important Ruby data types.


#$%usr%bin%rub& * ! F :nam1 !> (3an1(< :a21 !> 1 p p p p p p p p tru1.,"ass< 'a"s1.,"ass (Rub&(.,"ass 1.,"ass J.9.,"ass 8_J>8_J9>_J9 .,"ass :a21.,"ass I1< 6< 8K.,"ass *.,"ass G

.e print their class names. 8 class is a template from each object is created.
p tru1.,"ass< 'a"s1.,"ass

@7

The boolean values are presented by true and false objects.


p (Rub&(.,"ass

This is the string.


p 1.,"ass p J.9.,"ass p 8_J>8_J9>_J9 .,"ass

These are the numbers.


p :a21.,"ass

This is a symbol, a data type specific to Ruby.


p I1< 6< 8K.,"ass p *.,"ass

These are two containers, the array and the hash.


$ .%t&p1s.rb )ru15"ass ]a"s15"ass Strin2 ]i0num ]"-at Bi2num S&mb-" 7rra& Aas*

The program lists classes that belong to Ruby data types.

Boolean values
There is a duality built in our world. There is a =eaven and *arth, water and fire, jing and jang, man and woman, love and hatred. This is the EbooleanE nature of our e%istence. In Ruby the boolean data type can have one of the two values5 true or false. /oolean is a fundamental data type5 one that is very common in computer programs. =appy parents are waiting a child to be born. They have chosen a name for both possibilities. If it is going to be a boy, they have chosen John. If it is going to be a girl, they have chosen 1ictoria.
#$%usr%bin%rub& # Hi..rb b--" ! Itru1< 'a"s1K ma"1 ! b--"Iran.(6)K

@:

i' ma"1 puts (W1 +i"" us1 nam1 3-*n( 1"s1 puts (W1 +i"" us1 nam1 Vi,t-ria( 1n.

The program uses a random number generator to simulate our case.


b--" ! Itru1< 'a"s1K

.e have a bool variable. It is an array of two boolean values. 8n array is created with s;uare brac ets.
ma"1 ! b--"Iran.(6)K

.e use a ran.() method to create a random number. The method returns either - or ". The returned number is an inde% to the bool array.
i' ma"1 puts (W1 +i"" us1 nam1 3-*n( 1"s1 puts (W1 +i"" us1 nam1 Vi,t-ria( 1n.

Lepending on the male variable, we print a message. If the male variable is set to true, we choose name John. 2therwise, we choose name 1ictoria. +ontrol structures li e if6else statements wor with boolean values.
$ .%Hi..rb W1 +i"" us1 $ .%Hi..rb W1 +i"" us1 $ .%Hi..rb W1 +i"" us1 $ .%Hi..rb W1 +i"" us1 $ .%Hi..rb W1 +i"" us1 nam1 Vi,t-ria nam1 Vi,t-ria nam1 3-*n nam1 3-*n nam1 3-*n

Running the program several times.

Symbols
)ymbols are used to represent other objects. &sing symbols instead of strings may save some resources. 8 symbol is an instance object of a S&mb-" class. )ymbols are generated by using an colon before an identifier, li e 5name. )everal objects also have t-_s&m methods. These methods convert those objects to symbols. 8 Ruby symbol cannot be changed at runtime. Ruby symbols are often used as hash eys, because we do not need full capabilities of a string objects for a ey.
#$%usr%bin%rub& p :nam1

@@

p :nam1.,"ass p :nam1.m1t*-.s.si?1 p (3an1(.m1t*-.s.si?1 p p p p :nam1.-bD1,t_i. :nam1.-bD1,t_i. (nam1(.-bD1,t_i. (nam1(.-bD1,t_i.

In the first e%ample, we show some basic operations with Ruby symbols.
p :nam1 p :nam1.,"ass

.e print a symbol and its class to the console. The class of the symbol is S&mb-".
p :nam1.m1t*-.s.si?1 p (3an1(.m1t*-.s.si?1

.e compare the number of methods associated with instances of symbols and strings. 8 string has more than twice as many methods than symbol.
p p p p :nam1.-bD1,t_i. :nam1.-bD1,t_i. (nam1(.-bD1,t_i. (nam1(.-bD1,t_i.

)ame symbols have the same id. )ame strings have different ids.
$ .%s&mb-"s.rb :nam1 S&mb-" @ 1>6 10868 10868 8JJ 90 8JJ 80

)ample output.

)ymbols may be used as flags. +onstants may be used in such situations as well. In +6+?? we would use enumerations.
#$%usr%bin%rub& "i2*t ! :-n i' "i2*t !! :-n puts ()*1 "i2*t is -n( 1"s1 puts ()*1 "i2*t is -''( 1n. "i2*t ! :-''

@$

i' "i2*t !! :-n puts ()*1 "i2*t is -n( 1"s1 puts ()*1 "i2*t is -''( 1n.

8 light is either on or off. <or both states we might define symbols.


"i2*t ! :-n

The light is on.


i' "i2*t !! :-n puts ()*1 "i2*t is -n( 1"s1 puts ()*1 "i2*t is -''( 1n.

The logic of the program depends on the state of the light variable.

)ymbols are often used as eys in hash containers. They are more efficient that strings.
#$%usr%bin%rub& .-mains ! F:sH !> (S"-:aHia(< :n- !> (N-r+a&(< :*u !> (Aun2ar&(G puts .-mainsI:sHK puts .-mainsI:n-K puts .-mainsI:*uK

In the script we have a domains hash. The eys in the hash are symbols.
puts .-mainsI:sHK puts .-mainsI:n-K puts .-mainsI:*uK

Meys are used to access values of a hash. =ere we print three values of a hash.
$ .%s&mb-"s8.rb S"-:aHia N-r+a& Aun2ar&

2utput of the e%ample.

Ruby interpreter stores some refererences internally as symbols.


#$%usr%bin%rub& ,"ass B1in2 .1' initia"i?1

@G

1n.

Ois ! tru1

.1' sa& (I am b1in2( 1n. 1n. b ! B1in2.n1+ p b.m1t*-. :sa& p b.instan,1_:ariab"1_21t :Ois

8 /eing class is defined. The class has a custom instance variable Dis and a say method. These two entities are stored using symbols by Ruby.
p b.m1t*-. :sa&

The m1t*-. method loo s up a receiver method with a given name in the b object. .e loo for a 5say symbol.
p b.instan,1_:ariab"1_21t :Ois

.e use instan,1_:ariab"1_21t to chec if Dis is an instance variable of the b object. Internally the variable is stored as an 5Dis symbol.
$ .%s&mb-"sJ.rb #M\1t*-.: B1in2#sa&> tru1

Oenerated output.

8ll symbols are stored in a symbol table. In the ne%t e%ample, we loo at the table. The a""_s&mb-"s method of a S&mb-" class returns an array of all symbols from the table.
#$%usr%bin%rub& .1' in'(in'- m1t*-.( 1n. O: ! (Rub&( OOn ! (1>( p S&mb-".a""_s&mb-"s.in,"u.1U :in'p S&mb-".a""_s&mb-"s.in,"u.1U :O: p S&mb-".a""_s&mb-"s.in,"u.1U :OOn

8 method, an instance variable and a class variable are created in a Ruby script. .e chec if these entities are stored in a symbol table.
p S&mb-".a""_s&mb-"s.in,"u.1U :in'-

.e chec if the 5info symbol is in the symbol table. The line returns true. @H

$ .%s&mb-"s9.rb tru1 tru1 tru1

8ll three symbols are present in the Ruby symbol table.

Integers
Integers are a subset of the real numbers. They are written without a fraction or a decimal component. Integers fall within a set Z 9 J..., -7, -", -, ", 7, ...K This set is infinite. In computer languages, integers are primitive data types. In practice, computers can only wor with a subset of integer values, due to computersE having finite capacity. Integers are used to count discrete entities. .e can have :, @, G humans, but we cannot have :.:: humans. .e can have :.:: ilograms. Integers are instance objects of a ]i0num or a Bi2num class in Ruby. &nli e in languages li e Java or +, integers in Ruby are objects. The two classes differ in siIe. <i%num numbers are integers up to a certain limit. The limite is machine dependent. /ignum values hold integers outside the range of the <i%num. If any operation on a <i%num e%ceeds its range, the value is automatically converted to a /ignum. The programmer usually does not need to care about the class type of the integers.
#$%usr%bin%rub& p p p p p p p p p ;6 161 1686>9 ;8J698J>J89> 8J8> 8> 8@8J>8J > 1.,"ass 68J986J>.,"ass 68J986J689>8J9>8J>.,"ass 68J986J689>868>8J>8J9>J9>8J>.,"ass

p 9 % 6 p 9..i: 6

In this e%ample, we deal with integers.


p p p p p ;6 161 1686>9 ;8J698J>J89> 8J8> 8> 8@8J>8J >

These are positive and negative integer values of various siIes.


p p p p 1.,"ass 68J986J>.,"ass 68J986J689>8J9>8J>.,"ass 68J986J689>868>8J>8J9>J9>8J>.,"ass

@>

.e print the classes of these integers. The first two integers are instances of a ]i0num class. The other two are instances of a Bi2num class.
p 9 % 6 p 9..i: 6

The two lines show integer division. .hen we divide two integers using the integer division operator6method, the result is an integer as well.
$ .%int121rs.rb ;6 161 1686>9 ;8J698J>J89> 8J8> 8> 8@8J>8J > ]i0num ]i0num Bi2num Bi2num 6 6

2utput of the e%ample.

Integers can be specified in different notations in Ruby. Lecimal, he%adecimal, octal and binary. Lecimal numbers are used normally, as we now them. =e%adecimal numbers are preceded with -% characters, octal with - character and binary with -b characters.
#$%usr%bin%rub& puts puts puts puts 166 00 a 01 6 0b1111010

In the code e%ample, we print decimal "77 in all these notation.


$ .%in-tati-ns.rb 166 166 166 166

2uput of the e%ample.

If we wor with integers, we deal with discrete entities. .e would use integers to count apples.
#$%usr%bin%rub& basH1ts ! 1> app"1s_in_basH1t ! 6J

@#

t-ta" ! basH1ts Q app"1s_in_basH1t puts ()*1r1 ar1 t-ta" -' #Ft-ta"G app"1s(

In our program, we count the total amount of apples. .e wor with integers.
$ .%app"1s.rb )*1r1 ar1 t-ta" -' 88J app"1s

The output of the program.

/ig numbers are difficult to read. If we have a number li e 7@$:@7:#$@7:@$7, we find it difficult to read ;uic ly. 2utside computers, big numbers are separated by spaces or commas. <or readability, Ruby allows integers to contain underscores. &nderscores in integers are ignored by the Ruby interpreter.
#$%usr%bin%rub& p 68J868J9>6@ p 68_J86_8J9_>6@ p 68J868J9>6@ !! 68_J86_8J9_>6@

The e%ample demonstrates this use of underscores.


p 68J868J9>6@ !! 68_J86_8J9_>6@

This line shows that the two numbers are e;ual. It prints true.
$ .%un.1rs,-r1.rb 68J868J9>6@ 68J868J9>6@ tru1

*%ample output.

,loating point numbers


<loating point numbers represent real numbers in computing. Real numbers measure continuous ;uantities li e weight, height or speed. In Ruby, decimal numbers are objects of the ]"-at or a Bi2E1,ima" class. The Bi2E1,ima" class, a Ruby core class, is part of RubyEs standard library. In addition, we can use Rati-na" objects too. .e need to understand that decimal numbers are not precise. The official Ruby documentation clearly says that float objects represent ine%act real numbers.
#$%usr%bin%rub& p 19.J p 0.8J99 p ;8J8.J9>8 p 16.9.,"ass

$-

p ;16.9.,"ass p (9.0 % 6).,"ass p 9.'.i: 6 p 16.t-_'

In the above program, we wor with floating point values.


p 19.J p 0.8J99 p ;8J8.J9>8

=ere we print three decimal values. Lecimal numbers have a decimal point character.
p 16.9.,"ass p ;16.9.,"ass p (9.0 % 6).,"ass

The above code lines show the types of the numbers. 8ll are floats. Integer division applied on at least one ]"-at produces a ]"-at too.
p 9.'.i: 6 p 16.t-_'

=ere we create floating point values by using the floating point '.i: division method and the conversion t-_' method.
$ .%.1,ima"s.rb 19.J 0.8J99 ;8J8.J9>8 ]"-at ]"-at ]"-at 6.9 16.0

2utput.

/y default, a decimal number is shown with a ma%imum "G numbers after the decimal point. .e can control the format of floating point values with the sprint' or print' methods.
#$%usr%bin%rub& p 1%8.0 p 1.'.i: 6 puts sprint' (R.J'( R (1%8.0) puts sprint' (R. '( R (9%8.0)

<ormatting decimal numbers.


p 1%8.0 p 18.'.i: J

$"

p 1.'.i: 6

The first line prints a decimal with "G places after the point. The second line prints two numbers after the point and the third one.
puts sprint' (R.J'( R (1%8.0) puts sprint' (R. '( R (9%8.0)

=ere we control the number of values after the decimal point using the sprint' method. There is a precision in the format specifier of the sprint' method. It is a number following the R character. The f is a conversion specifier that says we are dealing with floating point values.
$ .%'-rmat'"-at.rb 0.8888888888888888 8.69 0.9 0.8888 1.>>>>>>

2utput.

Ruby supports the use of scientific notation for floating point values. 8lso nown as e%ponential notation, it is a way of writing numbers too large or small to be conveniently written in standard decimal notation.
#$%usr%bin%rub& p 1.61;8 p 0.0016 p 1.9E;J p 0.00019

The e%ample shows two decimal numbers written in scientific notation.


$ .%s,i1nti'i,.rb 0.0016 0.0016 0.00019 0.00019

This is the output of the above program.

8s we have already stated, floating point values are slightly inaccurate. <or many computations, ordinary floating point numbers are sufficiently precise5 e.g., if it is not that important if our weight is G- g or G-.----7: g. <or other computations, including many scientific and engineering applications, precision is paramount. Ruby has a Bi2E1,ima" in the standard library. This class provides arbitrary precision for very large or very accurate floating point numbers.

$7

#$%usr%bin%rub& r1Buir1 Cbi2.1,ima"C sum ! 0 1000.tim1s .sum ! sum / 0.0001 1n. p sum sum ! Bi2E1,ima".n1+((0() 1000.tim1s .sum ! sum / Bi2E1,ima".n1+((0.0001() 1n. puts sum.t-_s(C]C) puts sum.t-_s(CEC)

In this simple e%ample, we compare the precision of a ]"-at compared to a Bi2E1,ima".


r1Buir1 Cbi2.1,ima"C

The Bi2E1,ima" class must be imported.


sum ! 0 1000.tim1s .sum ! sum / 0.0001 1n. p sum

.e form a loop, where we add a small floatig point value to a sum variable. In the end, there will be a small inaccuracy.
sum ! Bi2E1,ima".n1+((0() 1000.tim1s .sum ! sum / Bi2E1,ima".n1+((0.0001() 1n.

.e do the same loop with the Bi2E1,ima" values.


puts sum.t-_s(C]C) puts sum.t-_s(CEC)

The sum is printed in floting point and engineering notation.


$ .%bi2.1,ima".rb 0.1000000000000018J 0.1 0.1E0

$:

The output shows that the computing with Bi2E1,ima" is more precise than with ]"-ats.

'etEs say a sprinter for "--m ran #.>Hs. .hat is his speed in m6hQ
#$%usr%bin%rub& .istan,1 ! 0.1 tim1 ! @.8 % 8>00 sp11. ! .istan,1 % tim1 puts ()*1 a:1ra21 sp11. -' a sprint1r is #Fsp11.G Hm%*(

In this e%ample, it is necessary to use floating point values.


.istan,1 ! 0.1

"--m is -." m.
tim1 ! @.8 % 8>00

#.>Hs is #.>H6G-PG- h
sp11. ! .istan,1 % tim1

To get the speed, we divide the distance by the time.


$ .%sp11..rb )*1 a:1ra21 sp11. -' a sprint1r is 8>.J J1>J188 88> Hm%*

This is the output of the speed.rb script.

Rational $umbers
Ruby supports rational numbers. 8 rational number is an e%act number. &sing rational numbers we avoid rounding errors. In Ruby, a rational number is an object of the Rati-na" class. .e can create rational numbers with a special t-_r method from some objects. 8 rational number is any number that can be e%pressed as a fraction of two integers a6b , where b\9-. )ince b may be e;ual to ", every integer is a rational number.
#$%usr%bin%rub& puts 6.t-_r puts (68(.t-_r puts 6.>.t-_r p Rati-na" 0 p Rati-na" 1%9.0 p Rati-na" 0.9

This e%ample shows a few rational numbers.

$@

puts 6.t-_r

=ere we convert a 7 integer to 76" rational number using the t-_r method.
p Rati-na" 0.9

.e create a rational number with the Rati-na" class.


$ .%rati-na".rb 6%1 68%1 989J> @919981>J9%6691 @@818>896J8 (0%1) (8>068 @ 018@>8@ %1801J8@890@J81@8J) (1%6)

2utput of the e%ample.

-he nil value


Ruby has a special value ni". It is an absence of a value. The ni" is a singleton object of a Ni"5"ass. There is only one ni"N we cannot have more of it.
#$%usr%bin%rub& puts ni" p ni" p $:a" p I1< 6< 8KIJK p $:a"1 !! $:a"6

8n e%ample with the ni" value.


puts ni" p ni"

.e print the ni" value to the console. The puts method prints an empty stringN the p method prints EnilE string.
p $:a"

.hen we refer to a global variable that was not set, we get the ni" value.
p I1< 6< 8KI8K

In this code line, we refer to the fourth element of a three-element array. .e get ni". !any methods in Ruby return ni" for invalid values.
p $:a"1 !! $:a"6

$$

The line returns true. This is a conse;uence of the fact that the ni" value is a singleton object of a Ni"5"ass.
$ .%ni":a"u1.rb ni" ni" ni" tru1

2utput.

Strings
8 string is a data type representing te%tual data in computer programs. 8 Ruby string is a se;uence of unicode characters. 8 string is an instance of the Strin2. )tring literals are characters enclosed in double or single ;outes. 8 string is a very important data type. It deserves a dedicated chapter. =ere we include just a small e%ample.
#$%usr%bin%rub& p (Rub&( p CN&t*-nC p (Rub&(.si?1 p (Rub&(.up,as1 p 68.t-_s

In this program, we wor with Ruby strings. .e use the p method for printing because we see the data type on output.
p (Rub&( p CN&t*-nC

.e print two string literals to the terminal. The first literal is enclosed in double ;uotes, the second literal in single ;uotes.
p (Rub&(.si?1 p (Rub&(.up,as1

These two lines call two string methods. The si?1 method returns the siIe of the string5 @ characters in our case. The up,as1 returns the string in uppercase letters.
p 68.t-_s

The t-_s method converts an integer to a string.


$ .%strin2s.rb (Rub&( (N&t*-n( J

$G

(RUBY( (68(

In the output we see strings enclosed in ;uotes. This is the conse;uence of using the p method. The print and puts methods donEt do this.

Arrays an# hashes


8rrays and hashes are collections of objects. They group objects into one place. 8rrays are ordered collections of objects. =ashes are collections of ey-value pairs. .e will have a single chapter for both arrays and hashes. The following e%ample just gives a ;uic loo at both containers.
#$%usr%bin%rub& nums ! I1< 6< 8< JK puts ()*1r1 ar1 #Fnums.si?1G it1ms in t*1 arra&( nums.1a,* .- LnumL puts num 1n. .-mains ! F :.1 !> (=1rman&(< :sH !> (S"-:aHia(< :us !> (Unit1. Stat1s(< :n- !> (N-r+a&( G puts .-mains.H1&s puts .-mains.:a"u1s

This is a ;uic e%ample for a Ruby array and hash.


nums ! I1< 6< 8< JK puts ()*1r1 ar1 #Fnums.si?1G it1ms in t*1 arra&( nums.1a,* .- LnumL puts num 1n.

These lines create an array having @ items. In the second line we count the items of the array and incorporate it in the message. 'ater we go through the array with the 1a,* method and print each of the elements to the console.
.-mains ! F :.1 !> (=1rman&(< :sH !> (S"-:aHia(< :us !> (Unit1. Stat1s(< :n- !> (N-r+a&( G puts .-mains.H1&s puts .-mains.:a"u1s

=ere we create a Ruby hash. Then we print its eys and values.
$ .%arra&s*as*1s.rb )*1r1 ar1 J it1ms in t*1 arra& 1

$H

6 8 J .1 sH us n=1rman& S"-:aHia Unit1. Stat1s N-r+a&

*%ample output.

Conversions
.e often wor with multiple data types at once. +onverting one data type to another one is a common job in programming. $ype conversion or typecasting refers to changing an entity of one data type into another. There are two types of conversion5 implicit and e%plicit. Implicit type conversion, also nown as coercion, is an automatic type conversion by the compiler. Ruby has only e%plicit conversion. Ruby has built-in conversion methods li e t-_i, t-_s or t-_'. The Z1rn1" module has a few public methods for doing conversions, li e Int121r, Strin2 or ]"-at. These methods should not be confused with Ruby classes.
#$%usr%bin%rub& p p p p p p 7rra&(1..>) 5-mp"10 > ]"-at 16 Int121r (8J( Rati-na" > Strin2 66

=ere we show the Z1rn1" conversion methods.


$ .%,-n:1rtm1t*-.s.rb I1< 6< 8< J< 9< >K (>/0i) 16.0 8J (>%1) (66(

2utput of the e%ample.


#$%usr%bin%rub& p (16(.t-_i p 16.9.t-_i p ni".t-_i p 16.t-_' p (11(.t-_' p ni".t-_'

$>

In the above e%ample, we show some numerical conversions. )ome Ruby objects have t-_i and t-_' methods which convert objects to integers and floats, respectively.
p (16(.t-_i p 16.9.t-_i p ni".t-_i

In this code we convert a string, decimal and nil to integer type.


p 16.t-_' p (11(.t-_' p ni".t-_'

These three lines convert an integer, string and nil to an object of decimal data type.
$ .%,-n:1rsi-ns.rb 16 16 0 16.0 11.0 0.0

*%ample output.

The second e%ample shows some string conversions.


#$%usr%bin%rub& p p p p (16(.t-_i (18(.t-_' (16(.t-_r (18(.t-_,

p (3an1(.t-_s&m : ! (Rub& N&t*-n )," NAN N1r"(.sp"it p :.,"ass

In the above e%ample we convert strings to objects of different data types.


p p p p (16(.t-_i (18(.t-_' (16(.t-_r (18(.t-_,

=ere strings are converted to integer, decimal, rational and comple% numbers.
p (3an1(.t-_s&m

8 string becomes a symbol.


: ! (Rub& N&t*-n )," NAN N1r"(.sp"it p :.,"ass

$#

=ere we use a sp"it method of the Strin2 class to convert a string to an array.
$ .%strin2,-n:.rb 16 18.0 (16%1) (18/0i) :3an1 7rra&

8nd this is what we get.

The ne%t small e%ample shows array hash conversions.


#$%usr%bin%rub& * ! F:.1 !> (=1rman&(< :sH !> (S"-:aHia(G p *.t-_a a ! I:.1< (=1rman&(< :sH< (S"-:aHia(< :*u< (Aun2ar&(< :n-< (N-r+a&(K p Aas*IQaK

In the e%ample code, we create a hash and covert it to array. Then we create an array and convert it to a hash.
* ! F:.1 !> (=1rman&(< :sH !> (S"-:aHia(G p *.t-_a

8 hash is created and converted to an array using the t-_a method.


a ! I:.1< (=1rman&(< :sH< (S"-:aHia(< :*u< (Aun2ar&(< :n-< (N-r+a&(K p Aas*IQaK

8n array is created and converted to a hash. The asteris in this conte%t is a splat operator. It is one of the Ruby idioms ta en from (erl. It splits an array into a few variables.
$ .%*6a.rb II:.1< (=1rman&(K< I:sH< (S"-:aHia(KK F:.1!>(=1rman&(< :sH!>(S"-:aHia(< :*u!>(Aun2ar&(< :n-!>(N-r+a&(G

2utput. In this part of the Ruby tutorial, we covered data types and their conversions.

%trings in Ruby
In this part of the Ruby tutorial, we will wor with string data in more detail. )trings are one of the most important data types in computer languages. That is why we dedicate a whole chapter to wor ing with strings in Ruby. G-

8 string is a se;uence of unicode characters. It is a data type that stores a se;uence of data values in which elements usually stand for characters according to a character encoding. .hen a string appears literally in source code, it is nown as a string literal.

,irst e.ample
In Ruby string literals are enclosed by single or double ;uotes.
#$%usr%bin%rub& # 'irst.rb puts CN&t*-n "an2ua21C puts (Rub& "an2ua21(

The e%ample has two string literals. The first one is enclosed in single ;outes. The other one is enclosed in double ;uotes.
$ .%'irst.rb N&t*-n "an2ua21 Rub& "an2ua21

2utput.

/sing 0uotes
.hat if we wanted to display ;uotes, for e%ample in a direct speechQ There are basically two ways to do this.
#$%usr%bin%rub& puts ()*1r1 ar1 man& stars( puts (A1 sai.< X(W*i,* -n1 is &-ur 'a:-urit1UX(( puts C)*1r1 ar1 man& starsC puts CA1 sai.< (W*i,* -n1 is &-ur 'a:-urit1U(C

.e use the A]B character to escape additional ;uotes. 3ormally the double ;uote character is used to delimit a string literal. =owever, when escaped, the original meaning is supressed. It appears as a normal character and can be used withing a string literal. The second way to use ;uotes within ;uotes is to mi% single and double ;uotes.
$ .%Bu-t1s.101 )*1r1 ar1 man& stars. A1 sai.< (W*i,* -n1 is &-ur 'a:-urit1U(

2utput.

'scape se0uences
*scape se;uences are special characters that have a specific meaning when used within a string literal.

G"

#$%usr%bin%rub& puts (-n1 t+- t*r11 '-ur( puts (-n1Xnt+-Xnt*r11Xn'-ur(

2ne of the most common escape se;uences is the newline character ]n. It is available in many programming languages. The ne%t character after the newline will appear on the new line.
$ .%n1+"in1.rb -n1 t+- t*r11 '-ur -n1 t+t*r11 '-ur

.ords after newline characters appear on new lines in the output of the about script.

The r, b and t characters are normal alphabetical characters. .hen preceded with a ] character, they have a special meaning.
#$%usr%bin%rub& puts ( bbbXraaa( puts (3-anXbXbXban1( puts ()-+1rin2Xtin'1rn-(

In the above e%ample, we use three different escape characters.


puts ( bbbXraaa(

The carriage return ]r is a control character for end of line return to beginning of line. /efore the string is printed to the console, it is first processed. The escape se;uence causes the aaa characters to be placed before the bbb characters. The output is aaabbb.
puts (3-anXbXbXban1(

The ]b control character is a bac space. It deletes a preceding character. The string printed to the console is EJaneE not EJoanE.
puts ()-+1rin2Xtin'1rn-(

<inally, the ]t escape se;uence places a tab space between the two words.
$ .%1s,ap1s.rb aaabbb 3an1 )-+1rin2

in'1rn-

2utput of the e%ample.

The bac slash character ] is a special character used to create escape se;uences. .hen there is a need to print a bac slash itself, it is preceded with another bac slash. Its default meaning G7

is escaped and it is printed. The single and double ;uotes are used to delimit strings in Ruby. In order to print them, they are preceded by ] too.
#$%usr%bin%rub& puts ()*1 sp1,ia" ,*ara,t1r XX( puts ()*1 sp1,ia" ,*ara,t1r XC( puts ()*1 sp1,ia" ,*ara,t1r X((

In this simple script, we print all three characters to the terminal.


$ .%sp1,ia"s.rb )*1 sp1,ia" ,*ara,t1r X )*1 sp1,ia" ,*ara,t1r C )*1 sp1,ia" ,*ara,t1r (

2utput.

Accessing string elements


It is possible to access string elements in Ruby. <or this we use the s;uare brac ets ST. Inside the brac ets, we can put strings, inde%es or ranges.
#$%usr%bin%rub& ms2 ! (Rub& "an2ua21( puts ms2I(Rub&(K puts ms2I(N&t*-n(K puts ms2I0K puts ms2I;1K puts ms2I0< 8K puts ms2I0..@K puts ms2I0< ms2."1n2t*K

This code e%ample shows, how we can access parts of a string.


ms2 ! (Rub& "an2ua21(

=ere is the string, that we will be accessing.


puts ms2I(Rub&(K

In this code line we test, whether string ERubyE is a substring of the msg string. If it is true, then the string that we are loo ing for is returned.
puts ms2I0K

The characters of the string can be accessed by their inde%. The numbers start from -. In other words, the - is the inde% of the first character. The msgS-T returns the first character of the string, namely R.

G:

puts ms2I;1K

=ere we access the last character of the string. The -" stands for the last inde% of the string.
puts ms2I0< 8K

Two inde%es separated by a comma return characters starting from the first inde% and ending with the second inde%, e%cluded.
puts ms2I0..@K

8 range operator can be used as well. =ere we print the first ten characters of the msg string.
puts ms2I0< ms2."1n2t*K

This line returns the whole string. The msg.length returns the siIe of the string.
$ .%a,,1ss.rb Rub& R 1 Rub Rub& "an2u Rub& "an2ua21

2utput of the e%ample.

1ultiline strings
In many programming languages creating multiline strings re;uires additional effort. This is especially true in 1isual /asic. In Ruby, multiline strings are created easily.
#$%usr%bin%rub& puts (I 7n. t*1 7n. ICm 7n. ICm ( *1ar \aria,*i stati, -n m& ra.itub1s t*1& 2"-+ in t*1 .arH t*1r1 +it* *1r in Ens1na.a *1r1 in E,*- NarH

puts R% 5arm1"ita *-". m1 ti2*t1r I t*inH ICm sinHin2 .-+n 7n. ICm a"" strun2 -ut -n *1r-in On t*1 -utsHirts -' t-+n% puts MMS)RIN= W1""< ICm sittinC *1r1 p"a&in2 s-"itair1 Wit* m& p1ar";*an."1. .1,H )*1 ,-unt& +-nCt 2i:1 m1 n- m-r1 m1t*a.-n1 7n. t*1& ,ut -'' &-ur +1"'ar1 ,*1,H S)RIN=

G@

In the e%ample, we have lyrics of a +armelita song. .e show three ways to print multiline strings. They can be used within double ;uotes. .e can use a R character to build a multiline string. The character following the R also encloses the string. <inally, we can use the heredoc synta%. In this synta%, we use [[ followed by some string. The string encloses the multiline strings. It must also be left aligned.

Variable interpolation
1ariable interpolation is replacing variables with their values inside string literals. To substitute a variable with a value, the variable name is put between ,J and K characters inside the string literal.
#$%usr%bin%rub& nam1 ! (3an1( a21 ! 1 puts (#Fnam1G is #Fa21G &1ars -".(

In this e%ample, we substitute for two variables in the string5 name and age.
$ .%int1rp-"ati-n.rb 3an1 is 1 &1ars -".

In the substitution it is possible to use e%pressions.


#$%usr%bin%rub& 0 ! 9 & ! > puts ()*1 pr-.u,t -' #F0G an. #F&G is #F0Q&G(

This is an e%ample of the e%pression in the substitution.


$ .%int1rp-"ati-n6.rb )*1 pr-.u,t -' 9 an. > is 80

Running the e%ample.

There is another way to substitute variables in a string. It is similar to how (ython 7.% supports interpolation.
#$%usr%bin%rub& nam1 ! (3an1( a21 ! 1 m1ssa21 ! (Rs is R. &1ars -".( R Inam1< a21K puts m1ssa21

*%ample.

G$

m1ssa21 ! (Rs is R. &1ars -".( R Inam1< a21K

.e build a string before we use it. The Rs and Rd are formatting characters that e%pect a string and a number, respectively. The values are provided in s;uare brac ets after the R character.

Concatenating strings
+oncatenating strings is creating one string from multiple strings.
#$%usr%bin%rub& "an2 ! (Rub&( / ( pr-2rammin2( / ( "an2u21( puts "an2 "an2 ! (N&t*-n( ( pr-2rammin2( ( "an2ua21( puts "an2 "an2 ! (N1r"( MM ( pr-2rammin2( MM ( "an2ua21( puts "an2 "an2 ! (3a:a(.,-n,at(( pr-2rammin2().,-n,at(( "an2ua21() puts "an2

Ruby provides multiple ways of concatenating strings.


"an2 ! (Rub&( / ( pr-2rammin2( / ( "an2u21(

The plus operator is the most common operator used to add strings in computer languages. (erl and (=( use the dot A.B operator to concatenate strings.
"an2 ! (N&t*-n( ( pr-2rammin2( ( "an2ua21(

Ruby automatically concatenates subse;uent strings.


"an2 ! (N1r"( MM ( pr-2rammin2( MM ( "an2ua21(

8nother operator which can be used to concatenate strings is [[.


"an2 ! (3a:a(.,-n,at(( pr-2rammin2().,-n,at(( "an2ua21()

*ach string literal is in fact an object. .e can call various methods on each Ruby object. 2n string objects, we can call the ,-n,at method, which adds two string objects. It also returns the final object, on which we can call another method. )o we can place these methods in a chain.
$ .%,-n,at1nat1.rb Rub& pr-2rammin2 "an2u21 N&t*-n pr-2rammin2 "an2ua21 N1r" pr-2rammin2 "an2ua21 3a:a pr-2rammin2 "an2ua21

2utput.

GG

,ree2ing strings
In Java or +,, the strings are immutable. This means, that we cannot modify an e%isting string. .e can only create a new string out of an e%isting one. In Ruby, the strings are not immutable by default. )tring objects in Ruby have a 'r11?1 method, which ma es them immutable.
#$%usr%bin%rub& ms2 ! (3an1( ms2 MM ( is ( ms2 MM (1 &1ars -".( puts ms2 ms2.'r11?1 #ms2 MM (an. s*1 is pr1tt&(

In this e%ample, we demonstrate that strings can be modified. =owever, after calling the freeIe method on a string object, we cannot modify the string anymore. If we uncomment the code line, we will get EcanEt modify froIen stringE error message.

Comparing strings
+omparing strings is a common job in programming. .e can compare two strings with a 99 operator or with a 1B"U method. They return true if the strings are e;ual and false if not.
#$%usr%bin%rub& puts (16( !! (16( puts (1 ( !! (@( puts (aa( !! (ab( puts (3an1(.1B"U (3an( puts (3an1(.1B"U (3an1(

In this code e%ample, we compare some strings.


puts (16( !! (16(

These two strings are e;ual, the line returns true.


puts (aa( !! (ab(

The first two characters of both strings are e;ual. 3e%t the following characters are compared. They are different so the line returns false.
puts (3an1(.1B"U (3an(

GH

The 1B"U method is used to compare two strings. )trings are objects and all have a built-in 1B"U method. The method ta es one parameter, the string to which we are comparing our first string.
$ .%,-mparin2.rb tru1 'a"s1 'a"s1 'a"s1 tru1

2utput of the program.

Ruby has a spaceship operator [99^. The operator comes from the (erl language. &nli e the above two ways of comparing strings, which return either true or false, this operator will return ", -, or _". Lepending on the value of the left argument relative to the right argument. If the left argument is greater than the right argument, the operator returns ". If the left argument is less than the right argument, the operator returns _". If the two arguments are e;ual, the operator returns -. .hat does it mean that a character is greater than another characterQ +haracters are ordered in tables. *ach character has a position in a table. .hen comparing characters, we compare their positions in such a table. <or e%ample in a 8)+II table, the character a comes before the character b. )o comparing a [99^ b returns -", because the left argument has a lower position than b.
#$%usr%bin%rub& puts (a( M!!> (b( puts (b( M!!> (a( puts (a( M!!> (a(

+omparing characters with a spaceship operator.


$ .%spa,1s*ip.rb ;1 1 0

2utput of the e%ample.

In is possible to compare strings regardless of the case. <or this Ruby has a ,as1,mp method. The method wor s the same way as the spaceship operator.
#$%usr%bin%rub& puts (3an1(.,as1,mp (3an1( puts (3an1(.,as1,mp (Dan1( puts (3an1(.,as1,mp (3an(

*%ample.
puts (3an1(.,as1,mp (3an1(

G>

puts (3an1(.,as1,mp (Dan1(

These two lines return the same result, -. In this case we do not ta e into account whether the characters are in upper or lower case.
$ .%,as1.rb 0 0 1

2utput of the e%ample.

Strings are ob+ects


Ruby is an object-oriented language. 2bjects are basic building bloc s of an 22( program. )trings are objects too. 8n object is a combination of data and methods. In a 22( program, objects are created and they communicate among themselves.
#$%usr%bin%rub& +1bsit1 ! (2--2"1.,-m( puts +1bsit1 +1bsit1 ! Strin2.n1+ (?1t,-.1.,-m( puts +1bsit1

In the e%ample above, we show two basic ways of creating a string in Ruby.
+1bsit1 ! (2--2"1.,-m(

=ere a string literal is assigned to a website variable. &nder the hood, the Ruby interpreter creates a string object.
+1bsit1 ! Strin2.n1+ (?1t,-.1.,-m(

This is the standard way of creating string objects. =owever, the first is used in most cases because it is less verbose and it is the common way of creating strings in most computer languages.
#$%usr%bin%rub& puts (?1t,-.1(.up,as1 puts (?1t,-.1(.si?1 puts (?1t,-.1(.r1:1rs1

In this code e%ample, we call three methods on a string literal. <or people who are familiar with Java, + and similar languages, this may be cofusing. In Ruby, a string literal is transfromed into a string object upon which it is possible to call methods.
$ .%strin2-bD1,t6.rb 4E)5OEE 1.-,t1?

G#

2utput of the e%ample.

String metho#s
Ruby string objects have useful methods that can be used for wor ing with strings. .e have already seen several string methods li e ,-n,at or 1B"U.
#$%usr%bin%rub& +-r. ! (E1t1rminati-n( puts ()*1 +-r. #F+-r.G *as #F+-r..si?1G ,*ara,t1rs( puts +-r..in,"u.1U (ti-n( puts +-r..in,"u.1U (ti,( puts puts +-r..1mpt&U +-r..,"1ar puts +-r..1mpt&U

.e have a string variable. <our string methods are presented.


puts ()*1 +-r. #F+-r.G *as #F+-r..si?1G ,*ara,t1rs(

The si?1 method returns the number of characters in the string.


puts +-r..in,"u.1U (ti-n(

The in,"u.1U method determines whether a substring is present in the tested string. In this case, the code line returns true.
puts +-r..1mpt&U +-r..,"1ar

The 1mpt&U method chec s whether the string is empty. It returns a boolean true or false. The ,"1ar method ma es string empty.
$ .%basi,m1t*-.s.rb )*1 +-r. E1t1rminati-n *as 18 ,*ara,t1rs tru1 'a"s1 'a"s1 tru1

2utput.

In the ne%t e%ample, we will have methods that wor with the case of the characters.
#$%usr%bin%rub&

H-

rub& ! (Rub& pr-2rammin2 "an2ua21( puts puts puts puts rub&.up,as1 rub&..-+n,as1 rub&.,apita"i?1 rub&.s+ap,as1

Ruby has four methods for character case. The up,as1 method returns a copy of the string in which all characters are in uppercase. The .-+n,as1 method returns a copy of the string in which all characters are in downcase. The ,apita"i?1 method returns a copy of string with the first character converted to uppercase and the remainder to lowercase. <inally, the s+ap,as1 method returns a copy of the string where the uppercase letters are converted to downcase and vice versa.
$ .%rub&"an2.rb RUBY NRO=R7\\IN= rub& pr-2rammin2 Rub& pr-2rammin2 rUBY NRO=R7\\IN= Y7N=U7=E "an2ua21 "an2ua21 Y7N=U7=E

2utput.

3e%t we present two Ruby string methods5 start_+it*U and 1n._+it*U. /oth methods return a boolean true or false. They determine whether a string starts or ends with a specific string, respectively.
#$%usr%bin%rub& +s1 ! (?1t,-.1.,-m( +s6 ! (+++.2n-m1.-r2( puts +s1.start_+it*U (+++.( puts +s6.start_+it*U (+++.( puts puts +s1.1n._+it*U (.,-m( puts +s6.1n._+it*U (.,-m(

This is an e%ample for the aforementioned methods.


puts +s1.start_+it*U (+++.(

=ere we chec if a string starts with a Fwww.F prefi%. It does not, so the output to the console is a boolean false.
puts +s1.1n._+it*U (.,-m(

.e chec whether the ws" string variable ends with a F.comF suffi%. It does, so we see a true in the console.
$ .%start1n..rb 'a"s1 tru1

H"

tru1 'a"s1

2utput.

In the following e%ample, we will deal with the insp1,t method. The method returns a raw string, surrounded by ;uote mar s, with special characters not interpreted. It is useful when we want to e%amine what characters form the string.
#$%usr%bin%rub& ms2 ! (3an1Xt1 Xn)*-masXt68( puts ms2 puts ms2.insp1,t

8n e%ample of the insp1,t string method.


ms2 ! (3an1Xt1 Xn)*-masXt68(

This is a string with some special characters.


puts ms2 puts ms2.insp1,t

In the first case, the special characters are interpreted. There is a tab and a newline between string parts. In the second case, we get the string in a raw format.
$ .%insp1,tm1t*-..rb 3an1 1 )*-mas 68 (3an1Xt1 Xn)*-masXt68(

2utput of the e%ample.

The ,*-mp method returns a new string with the record separator removed from the end of the string. The default separator is the newline A]nB.
#$%usr%bin%rub& print (7r1 &-u sur1 t- .-+n"-a.U (Y1s%N-) ( r1sp-ns1 ! 21ts i' (r1sp-ns1..-+n,as1 !! (&1s() puts (E-+n"-a.1.( 1"s1 puts (E-+n"-a. ,an,1""1.( 1n. puts r1sp-ns1.insp1,t

H7

In the above script, we get an input from the user. .e react to the user response.
$ .%,*-mp.rb 7r1 &-u sur1 t- .-+n"-a.U (Y1s%N-) Y1s E-+n"-a. ,an,1""1. (Y1sXn(

The script does not wor correctly. The reason becomes clear when we consider what insp1,t returns. The input from the user is ended with an enter ey. The newline character is included in the response variable too. 8nd FyesF does not e;ual to Fyes]nF. To correct the script, we use the ,*-mp method. It removes the newline from the variable.
#$%usr%bin%rub& print (7r1 &-u sur1 t- .-+n"-a.U (Y1s%N-) ( r1sp-ns1 ! 21ts i' (r1sp-ns1..-+n,as1.,*-mp !! (&1s() puts (E-+n"-a.1.( 1"s1 puts (E-+n"-a. ,an,1""1.( 1n. puts r1sp-ns1.insp1,t

This is the corrected e%ample.


i' (r1sp-ns1..-+n,as1.,*-mp !! (&1s()

=ere we process the input before it is compared with the FyesF string. The ,*-mp method removes the newline character.
$ .%,*-mp.rb 7r1 &-u sur1 t- .-+n"-a.U (Y1s%N-) Y1s E-+n"-a.1. (Y1sXn(

3ow the e%ample wor s correctly.

,ormatting strings
Ruby has ormat speci iers. 8 format specifier determines how the string is going to loo li e. It begins with a R character. <ormat specifiers are put inside single or double ;uotes. The format specifier has the following fields5
RI'"a2sKI'i1". +i.t*KIpr1,isi-nK,-n:1rsi-n sp1,i'i1r

<ields in s;uare brac ets are optional. 8 conversion speci ier specifies how the data is going to be converted into displayable form.
#$%usr%bin%rub&

H:

puts ()*1r1 ar1 R. -ran21s in t*1 basH1t.( R 16 puts ()*1r1 ar1 R. -ran21s an. R. app"1s in t*1 basH1t.( R I16< 10K

=ere is an e%ample of some format specifiers.


puts ()*1r1 ar1 R. -ran21s in t*1 basH1t( R 16

.hen we use the Rd notation inside a string, we e%pect a number at that point. The d is a conversion specifier for decimal numbers. The number is given after the R character.
puts ()*1r1 ar1 R. -ran21s an. R. app"1s in t*1 basH1t( R I16< 10K

.e can use multiple format specifiers inside a string. *ach begins with a R character. !ultiple values are placed between ST characters and separated by comma character.
$ .%'-rmatsp1,i'i1rs.rb )*1r1 ar1 16 -ran21s in t*1 basH1t. )*1r1 ar1 16 -ran21s an. 10 app"1s in t*1 basH1t.

2utput of the e%ample.

In the following e%ample, we will cover some basic conversion specifiers.


#$%usr%bin%rub& puts puts puts puts ()*1r1 ar1 R. app"1s.( R 9 (I ,an s11 Ri -ran21s.( R 8 ()*1 +i.t* -' iN*-n1 8= is R' mm.( R >6.1 ()*is anima" is ,a""1. a Rs( R (r*in-,1r-s.(

.e have conversion specifiers for integers, floating point numbers and strings.
puts ()*1r1 ar1 R. app"1s.( R 9 puts (I ,an s11 Ri -ran21s.( R 8

/oth d an i can be used for integers.


puts ()*1 +i.t* -' iN*-n1 8= is R' mm.( R >6.1

The f is a conversion specifier for floating point values. /y default, floats have si% decimal places.
puts ()*is anima" is ,a""1. a Rs( R (r*in-,1r-s.(

The s character is used for strings.


$ .%basi,sp1,i'i1rs.rb )*1r1 ar1 9 app"1s. I ,an s11 8 -ran21s. )*1 +i.t* -' iN*-n1 8= is >6.100000 mm. )*is anima" is ,a""1. a r*in-,1r-s.

H@

2utput of the e%ample.

3e%t we have a practical e%ample of using a format specifier.


#$%usr%bin%rub& +1bsit1 ! (?1t,-.1.,-m( +1bsit1.1a,*_,*ar .- L,L print (#F,G *as 7S5II ,-.1 R.Xn( R ,.-r. 1n.

In this e%ample, we go through all characters of a string and print their 8)+II values to the terminal.
+1bsit1.1a,*_,*ar .- L,L print (#F,G *as 7S5II ,-.1 R.Xn( R ,.-r. 1n.

The 1a,*_,*ar method passes each character of a website string to the bloc , one character per cycle, with current character stored in c variable. .e get the 8)+II code of the character using the -r. method, which returns the ordinal of a one character string.
$ ? 1 t , . 1 . , m .%,*ara,t1r.rb *as 7S5II ,-.1 *as 7S5II ,-.1 *as 7S5II ,-.1 *as 7S5II ,-.1 *as 7S5II ,-.1 *as 7S5II ,-.1 *as 7S5II ,-.1 *as 7S5II ,-.1 *as 7S5II ,-.1 *as 7S5II ,-.1 *as 7S5II ,-.1 166 101 11> @@ 111 100 101 J> @@ 111 10@

2utput of the e%ample.

3umbers can be displayed in various forms. The conversion specifier can be used to format numbers.
#$%usr%bin%rub& # .1,ima" puts (R.( R 800 # *10a.1,ima" puts (R0( R 800 # -,ta" puts (R-( R 800 # binar& puts (Rb( R 800

H$

# s,i1nti'i, puts (R1( R (9%8.0)

In the above e%ample, we print numbers in decimal, he%adecimal, octal, binary and scientific formats.
# *10a.1,ima" puts (R0( R 800

The % conversion specifier is used to transform a number into a he%adecimal format.


# binar& puts (Rb( R 800

The % conversion specifier is used to transform a number into a binary format.


$ .%:ari-us.rb 800 16, J9J 100101100 1.>>>>> 1/00

2utput.

&recision is a field in the format specifier. It is specified as a number following a decimal point. It has a different meaning for an integer, a floating point number and for a string. .hen used with integers, it indicates the minimum number of digits to be printed. If the number has fewer digits than the precision, Ieros are prefi%ed. The default precision for integers is ", meaning that no Ieros are filled. .hen used with a float number, the precision is the number of digits displayed after the decimal point. <inally, with strings, the precision is the ma%imum number of characters printed.
#$%usr%bin%rub& puts CA1i2*t: R' RsC R I1 6.8< C,mCK puts CA1i2*t: R.1' RsC R I1 6.8< C,mCK puts (R.( R 1> puts (R.9.( R 1> puts (Rs( R (?1t,-.1( puts (R.9s( R (?1t,-.1(

In this e%ample, we will wor with the precision field.


puts CA1i2*t: R' RsC R I1 6.8< C,mCK puts CA1i2*t: R.1' RsC R I1 6.8< C,mCK

"H7.: is a floating point number. If no precision is specified, there will be G decimal places after a decimal point. In our case, there will be $ Ieros. The ." in the second code line is the precision. <or a floating point value, it reduces the number of decimal places to ".

HG

puts (R.( R 1> puts (R.9.( R 1>

The default precision for integers is ". In the second line, we have specified precision .$, which adds AprependsB : Ieros to the "G number.
puts (Rs( R (?1t,-.1( puts (R.9s( R (?1t,-.1(

The first line prints all characters of the string. The second line prints only five of them. Two characters are dropped.
$ .%pr1,isi-n.rb A1i2*t: 1 6.800000 ,m A1i2*t: 1 6.8 ,m 1> 0001> ?1t,-.1 ?1t,-

2utput.

Field width specifies the minimum width of the data to display. It is a number, which comes before the decimal point, if it is present. If the output is shorter, then it is padded with spaces and it is right aligned. If we put a minus sign before the field width, it is left aligned. If the output is longer than the field width, it is displayed in full.
#$%usr%bin%rub& puts puts puts puts puts puts puts puts puts puts (R.( (R.( (R.( (R.( (R.( R R R R R 1 1> 1>9 1>9> 1>9> R R R R R 1 1> 1>9 1>9> 1>9>

(R10.( (R10.( (R10.( (R10.( (R10.(

In the first case, we print five numbers without specifying the field width. The width of the output is e;ual to the number of the characters being displayed. In the second case we have a field width of "-. *ach of the $ outputs has a minimum length of "- characters. The numbers are right aligned.
puts (R.( R 1 puts (R.( R 1>

.e print two numbers. The width of the output has ", 7 characters, respectively.
puts (R10.( R 1 puts (R10.( R 1>

HH

=ere the length in both cases is "- characters. The two numbers are padded with # and > spaces in the given order.
$ .%'i1".+i.t*.rb 1 1> 1>9 1>9> 1>9> 1 1> 1>9 1>9> 1>9>

.e can see that in the second case the numbers are right aligned.

The flag ;ualifier modifies the formatEs behaviour. The , flag adds a -b, -, and -% prefi% to binary, octal and he%adecimal formats respectively. It adds a decimal point to the floating point values, even if the number of decimal places have been restricted by the precision.
#$%usr%bin%rub& puts (R#b( R 681 puts (R#0( R 681 puts (R#-( R 681 puts (R.01( R 681 puts (R#.01( R 681 puts (R.0'( R 681 puts (R#.0'( R 681

In the code e%ample, we use the % flag.


puts (R#b( R 681 puts (R#0( R 681 puts (R#-( R 681

The decimal 7:" is printed in binary, octal, and he%adecimal formats. The , flags adds a prefi% for them.
puts (R.01( R 681 puts (R#.01( R 681

=ere, the .- precision supresses the decimal places of a number. =owever, when used with a , flag, the decimal point is displayed, even though there are no decimal digits.
$ .%'"a2s1.rb 001 0b11100111 08J

H>

61/06 6.1/06 681 681.

2utput.

The ? flag adds a plus sign for positive decimal numbers. <or binary, octal and he%adecimal negative numbers it adds a minus sign and uses an absolute value.
#$%usr%bin%rub& puts puts puts puts (R.( R 681 (R/.( R 681 (R.( R ;681 (R/.( R ;681

puts (Rb( R ;681 puts (R-( R ;681 puts (R0( R ;681 puts (R/b( R ;681 puts (R/-( R ;681 puts (R/0( R ;681

8n e%ample demonstrating the ? flag of the format specifier.


puts (R.( R 681 puts (R/.( R 681

&sually, positive numbers have their sign omitted. If we want to show a plus sign for positive numbers, we specify the ? flag.
puts (R.( R ;681 puts (R/.( R ;681

The ? flag has no effect on negative numbers. The output is the same.
puts (Rb( R ;681 puts (R-( R ;681 puts (R0( R ;681

/inary, octal and he%adecimal numbers have their own way to create negative numbers.
puts (R/b( R ;681 puts (R/-( R ;681 puts (R/0( R ;681

If we specify the ? flag for these negative numbers, we transform a number to a different format and add a minus sign. There is no special way of representing negative numbers.
$ .%'"a2s6.rb 681 /681

H#

;681 ;681 ..100011001 .. J81 ..'1@ ;11100111 ;8J ;1

2utput of the e%ample.

=ere we introduce the - flag and the - flag. The - flag causes the number to be padded with Ieros instead of spaces. The - flag ma es the output left aligned.
#$%usr%bin%rub& puts puts puts puts puts puts puts puts puts puts (R010.( (R010.( (R010.( (R010.( (R010.( (R;10.( (R;10.( (R;10.( (R;10.( (R;10.( R R R R R R R R R R 1 1> 1>9 1>9> 1>9> 1 1> 1>9 1>9> 1>9>

*%ample.
puts (R010.( R 1 puts (R010.( R 1>

3umbers will be padded with Ieros.


puts (R;10.( R 1 puts (R;10.( R 1>

The number, being shorter than the field width, is aligned. 8nd the - flag ma es it left aligned.
$ .%'i1".+i.t*6.rb 0000000001 000000001> 00000001>9 0000001>9> 000001>9> 1 1> 1>9 1>9> 1>9>

2uput of the e%ample.

>-

The P flag can be used for the precision and for the width. .henever we use the P flag, we have to specify the precision or the width as an argument.
#$%usr%bin%rub& puts (R.Q'( R I8< 1.1111111K puts (R0Q.( R I10< 6K puts (R0Q.Q'( R I10< 8< 1.1111K

*%ample for the P flag.


puts (R.Q'( R I8< 1.1111111K

=ere we use the P flag for the precision. The first number, :, is the argument for the precision. It says only three decimal digits will be displayed for the ".""""""" float number.
puts (R0Q.( R I10< 6K

In this code line, we use the P flag for the width. .e have to add the width between the ST brac ets. The first number is the width and the second number is the value for the conversion specifier.
puts (R0Q.Q'( R I10< 8< 1.1111K

The P flag can be used for both the width and the precision. .e have to specify them both in the ST brac ets.
$ .%'"a2s8.rb 1.111 0000000006 000001.111

2utput of the e%ample. This part of the Ruby tutorial covered strings.

'xpressions in Ruby
In this part of the Ruby tutorial, we will tal about e%pressions. *%pressions are constructed from operands and operators. The operators of an e%pression indicate which operations to apply to the operands. The order of evaluation of operators in an e%pression is determined by the precedence and associativity of the operators. 8n operator is a special symbol which indicates a certain process is carried out. 2perators in programming languages are ta en from mathematics. (rogrammers wor with data. The operators are used to process data. 8n operand is one of the inputs AargumentsB of an operator. The following table shows common Ruby operators ordered by precedence Ahighest precedence firstB5 >"

Category Resolution, access operators 8rray operators *%ponentiation 3ot, complement, unary plus, minus !ultiply, divide, modulo 8ddition, substraction )hift operators /itwise and /itwise or, logical or Relational operators /itwise or, logical or *;uality, pattern match operators 'ogical and 'ogical or Range operators Ternary 8ssignment operators 8lternate negation 8lternate logical or, and

%ymbol
:: . I K I K! QQ $ P / ; Q % R / ; MM >> S T L > >! M M! T L M!> !! !!! $! !P $P SS LL .. ... U: ! /! ;! Q! QQ! %! R! S! L! T! MM! >>! LL! SS! n-t -r an.

2perators on the same row of the table have the same precedence. 8n operator usually has one or two operands. Those operators that wor with only one operand are called unary operators. Those who wor with two operands are called binary operators. There is also one ternary operator AQ5B, which wor s with three operands. +ertain operators may be used in different conte%ts. <or e%ample the ? operator. <rom the above table we can see that it is used in different cases. It adds numbers, concatenates strings, indicates the sign of a number. .e say that the operator is overloaded.

Sign operators
There are two sign operators. ? and -. They are used to indicate or change the sign of a value.
#$%usr%bin%rub& puts /6 puts ;6

The ? and - signs indicate the sign of a value. The plus sign can be used to indicate that we have a positive number. It can be omitted and it is mostly done so.

In the following e%ample, we will wor with a minus sign.


#$%usr%bin%rub& a ! 1

>7

puts a puts ;(a) puts ;(;(a))

The minus sign changes the sign of a value.


$ .%si2n.rb 1 ;1 1

This is the output of the e%ample.

-he assignment operator


The assignment operator 9 assigns a value to a variable. 8 variable is a placeholder for a value. In mathematics, the 9 operator has a different meaning. In an e;uation, the 9 operator is an e;uality operator. The left side of the e;uation is e;ual to the right one.
0 ! 1 puts 0 # prints 1

=ere we assign a number to the % variable.


0 ! 0 / 1 puts 0 # prints 6

The previous e%pression does not ma e sense in mathematics. /ut it is legal in programming. The e%pression adds " to the % variable. The right side is e;ual to 7 and 7 is assigned to %.
8 ! 0V

This code e%ample results in synta% error. .e cannot assign a value to a literal.

Resolution& member access operators


These two operators have the highest precedence level in the hierarchy of the operators. .hich means, that they are always evaluated first.
#$%usr%bin%rub& ,"ass \&\at* Ni ! 8.1J19@6>989 1n. m-.u"1 N1-p"1 Nam1 ! (N1-p"1( 1n. puts \&\at*::Ni puts N1-p"1::Nam1

>:

In the first e%ample, we present the 55 namespace resolution operator. It allows to access a constant, module, or class defined inside another class or module. It is used to provide namespaces so that method and class names donEt conflict with other classes by different authors.
,"ass \&\at* Ni ! 8.1J19@6>989 1n. m-.u"1 N1-p"1 Nam1 ! (N1-p"1( 1n.

.e have a simple module and a class. *ach has one constant defined.
puts \&\at*::Ni puts N1-p"1::Nam1

.e use the 55 operator to access constants from both.


$ .%r1s-"uti-n.rb 8.1J19@6>989 N1-p"1

This is the output of the resolution.rb program.

The dot . operator is a member access operator. It is used to call methods of objects.
#$%usr%bin%rub& ,"ass N1rs-n .1' initia"i?1 nam1< a21 Onam1 ! nam1 Oa21 ! a21 1n. .1' in'(#FOnam1G is #FOa21G &1ars -".( 1n. 1n. p ! N1rs-n.n1+ (3an1(< 1 puts p.in'puts (41t5-.1(.r1:1rs1

In our e%ample, we have two objects. 2ne user defined and one predefined. .e use the dot operator to wor with these objects.
p ! N1rs-n.n1+ (3an1(< 1 puts p.in'-

In these two lines, the dot operator calls two methods5 new and info. >@

puts (41t5-.1(.r1:1rs1

8 string is a built-in object, which has a reverse method. This is being called.
$ .%m1mb1ra,,1ss.rb 3an1 is 1 &1ars -". 1.-5t14

This is the output of the e%ample.

Concatenating strings
In Ruby the ? operator is also used to concatenate strings. .hen an operator is used in different conte%ts differently, we say that it is overloaded.
#$%usr%bin%rub& puts (R1turn ( / (-' ( / (t*1 ( / (Zin2( puts (R1turn (./(-' (./ (t*1 (./(Zin2(

.e join three strings together using string concatenation operator.


puts (R1turn ( / (-' ( / (t*1 ( / (Zin2(

.e join four strings using ? operator.


puts (R1turn (./(-' (./ (t*1 (./(Zin2(

&nder the hood, the ? operator is a Ruby method. The string literal is an object. .e call a method of an object using the access A.B operator.
$ .%,atstrin2s.rb R1turn -' t*1 Zin2 R1turn -' t*1 Zin2

8nd this is what we get, when we run the catstrings.rb program.

Increment& #ecrement operators


Ruby has no such operators.
0//V 0 ! 0 / 1V ... &;;V & ! & ; 1V

These are increment, decrement operators in +. If you are familiar with Java, +, +??, you now these operators. They are not available in Ruby. (ython language does not have them too.

>$

Arithmetic operators
The following is a table of arithmetic operators in Ruby. %ymbol (ame ? 8ddition )ubtraction P !ultiplication 6 Livision R Remainder PP (ower In the ne%t e%ample, we use arithmetic operations.
#$%usr%bin%rub& a ! 10 b ! 11 , ! 16 puts puts puts puts puts puts a , a , , , / b / , ; a Q b % 8 R a QQ a

In the preceding e%ample, we use addition, subtraction, multiplication, division and remainder operations. This is all familiar from the mathematics.
puts , R a

The R operator is called the remainder or the modulo operator. It finds the remainder of division of one number by another. <or e%ample, # R @, # modulo @ is ", because @ goes into # twice with a remainder of ".
$ .%arit*m1ti,.rb 88 6 110 J 6 >1@1 8>J66J

This is the output of the e%ample.

3e%t we will show the distinction between integer and floating point division.
#$%usr%bin%rub& puts 9 % 6

>G

puts 9 % 6.0 puts 9.0 % 6 puts 9.t-_' % 6

In the preceding e%ample, we divide two numbers.


puts 9 % 6

/oth operands in the e%pression are integers. .e have done integer division. The returned value of the division operation is an integer. .hen we divide two integers the result is an integer.
puts 9 % 6.0 puts 9.0 % 6 puts 9.t-_' % 6

If one of the values is a a float Aor bothB, we perform a floating point division. 8 floating point value has a decimal point. .e can also call a t-_' method to convert an integer to a float.
$ .%.i:isi-n.rb 6 6.9 6.9 6.9

=ere we see the result of the division.rb program.

Ruby has other ways to perform divisions. These are available as method calls.
#$%usr%bin%rub& puts puts puts puts 9..i: 6.0 9.'.i: 6 9.Bu- 6 9.0.Bu- 6.0

In the above e%ample, we have a .i:, a '.i: and a Bu- methods.


puts 9..i: 6.0

The .i: method always performs integer division. *ven if the operands are floting point values.
puts 9.'.i: 6

The '.i: method always performs float division.


puts 9.Bu- 6 puts 9.0.Bu- 6.0

>H

The Bu- method performs the most accurate division. It returns a float if either operand is float, otherwise rational.
$ .%-t*1r.i:isi-n.rb 6 6.9 9%6 6.9

Boolean operators
In Ruby, we have the following logical operators. /oolean operators are also called logical. %ymbol (ame VV logical and `` logical or \ negation /oolean operators deal with truth values. Ruby has additional alternative boolean operators. These are an., -r V n-t. They do the same e%cept for the thing that they have a lower precedence level. This duplicity is ta en from the (erl language, where there was a need for boolean operators with a lower precedence.
#$%usr%bin%rub& 0 ! 8 & ! 8 puts 0 !! & puts & > 0 i' & > 0 t*1n puts (& is 2r1at1r t*an 0( 1n.

!any e%pressions result in a boolean value. /oolean values are used in conditional statements.
puts 0 !! & puts & > 0

Relational operators always result in a boolean value. These two lines print false and true.
i' & > 0 t*1n puts (& is 2r1at1r t*an 0( 1n.

The body of the i' statement is e%ecuted only if the condition inside the parentheses is met. The % ^ y returns true, so the message Fy is greater than %F is printed to the terminal.

The ne%t e%ample shows the logical an. operator.

>>

#$%usr%bin%rub& puts puts puts puts tru1 SS tru1 tru1 SS 'a"s1 'a"s1 SS tru1 'a"s1 SS 'a"s1

The an. operator evaluates to true only if both operands are true.
$ .%an.-p1rat-r.rb tru1 'a"s1 'a"s1 'a"s1

2nly one of the e%pressions results in true.

The logical or `` operator evaluates to true if either of the operands is true.


#$%usr%bin%rub& puts puts puts puts tru1 LL tru1 tru1 LL 'a"s1 'a"s1 LL tru1 'a"s1 LL 'a"s1

If one of the sides of the operator is true, the outcome of the operation is true.
$ .%-r-p1rat-r.rb tru1 tru1 tru1 'a"s1

Three e%pressions result in a boolean true.

The negation operator \ ma es true false and false true.


#$%usr%bin%rub& puts puts puts puts $0 $1 $tru1 $'a"s1

puts $ (JM8) puts $ (Rub&(.in,"u.1U((a()

The e%ample shows the negation operator in action.


$ .%n-t.rb 'a"s1 'a"s1 'a"s1

>#

tru1 tru1 tru1

This is the output of the e%ample.

The LL, and SS operators are short circuit evaluated. Short circuit evaluation means that the second argument is only evaluated if the first argument does not suffice to determine the value of the e%pression5 when the first argument of the logical and evaluates to false, the overall value must be falseN and when the first argument of logical or evaluates to true, the overall value must be true. )hort circuit evaluation is used mainly to improve performance. 8n e%ample may clarify this a bit more.
#$%usr%bin%rub& .1' -n1 puts (Insi.1 -n1( 'a"s1 1n. .1' t+puts (Insi.1 t+-( tru1 1n. puts (S*-rt ,ir,uit( i' -n1 SS t+puts (Nass( 1n. puts (##############################( i' t+- LL -n1 puts (Nass( 1n.

.e have two methods in the e%ample. They are used as operands in boolean e%pressions. .e will see if they are called or not.
i' -n1 SS t+puts (Nass( 1n.

The one method returns false. The short circuit VV does not evaluate the second method. It is not necessary. 2nce an operand is false, the result of the logical conclusion is always false. 2nly FInside oneF is only printed to the console.
puts (##############################( i' t+- LL -n1 puts (Nass( 1n.

#-

In the second case, we use the `` operator and use the two method as the first operand. In this case, FInside twoF and F(assF strings are printed to the terminal. It is again not necessary to evaluate the second operand, since once the first operand evaluates to true, the logical or is always true.
$ .%s*-rt,ir,uit.rb S*-rt ,ir,uit Insi.1 -n1 ############################## Insi.1 t+Nass

.e see the result of the shortcircuit.rb program.

Relational Operators
Relational operators are used to compare values. These operators always result in boolean value. %ymbol Meaning [ less than [9 less than or e;ual to ^ greater than ^9 greater than or e;ual to Relational operators are also called comparison operators.
#$%usr%bin%rub& p 8 M J p 8 > 9 p 8 >! 8

The 8 M J e%pression returns true, since : is smaller than @. The 8 > 9 e%pression returns false because it is not true that : is greater than $.

Bit"ise operators
Lecimal numbers are natural to humans. /inary numbers are native to computers. /inary, octal, decimal or he%adecimal symbols are only notations of the same number. /itwise operators wor with bits of a binary number. %ymbol Meaning U bitwise negation a bitwise e%clusive or V bitwise and ` bitwise or [[ left shift ^^ right shift

#"

/itwise operators are seldom used in higher level languages li e Ruby.


#$%usr%bin%rub& puts P puts P ;8 puts > S 8 puts 8 S > puts > T 8 puts 8 T > puts > L 8 puts 8 L > puts > MM 1 puts 1 MM > puts > >> 1 puts 1 >> > # prints ;8 # prints # prints 6 # prints 6 # prints 9 # prints 9 # prints # prints # prints 16 # prints >J # prints 8 # prints 0

In the above code e%ample, we show all G operators.


puts P puts P ;8 # prints ;8 # prints

The bitwise negation operator changes each " to - and - to ". The operator reverts all bits of a number H. 2ne of the bits also determines, whether the number is negative or not. If we negate all the bits one more time, we get number H again.
puts > S 8 puts 8 S > # prints 6 # prints 6

The bitwise and operator performs bit-by-bit comparison between two numbers. The result for a bit position is " only if both corresponding bits in the operands are ".
puts > T 8 puts 8 T > # prints 9 # prints 9

The bitwise exclusive or operator performs bit-by-bit comparison between two numbers. The result for a bit position is " if one or the other Abut not bothB of the corresponding bits in the operands is ".
puts > L 8 puts 8 L > # prints # prints

The bitwise or operator performs bit-by-bit comparison between two nubmers. The result for a bit position is " if either of the corresponding bits in the operands is ".
puts > MM 1 puts 1 MM > puts > >> 1 puts 1 >> > # prints 16 # prints >J # prints 8 # prints 0

#7

The bitwise shift operators shift bits to the right or left. These operators are also called arithmetic shift.

Compoun# assignment operators


The compound assignment operators consist of two operators. They are shorthand operators.
#$%usr%bin%rub& a ! 0 a ! a / 1 a /! 1 puts a b ! 0 b ! b ; 8 b ;! 8 puts b

The ?9 and -9 compound operators are one of these shorthand operators. They are less readable than the full e%pressions but e%perienced programmers often use them.
a ! a / 1 a /! 1

These two lines do the sameN they add " to the a variable. 2ther compound operators are5
;! Q! QQ! %! R! S! L! MM! >>!

Operator prece#ence
The operator precedence tells us which operators are evaluated first. The precedence level is necessary to avoid ambiguity in e%pressions. .hat is the outcome of the following e%pressionQ 7> or @-Q
8 / 9 Q 9

'i e in mathematics, the multiplication operator has a higher precedence than addition operator. )o the outcome is 7>.
(8 / 9) Q 9

To change the order of evaluation, we can use parentheses. *%pressions inside parentheses are always evaluated first.
#$%usr%bin%rub& puts 8 / 9 Q 9

#:

puts (8 / 9) Q 9 puts $ tru1 L tru1 puts $ (tru1 L tru1)

In this code e%ample, we show some common e%pressions. The outcome of each e%pression is dependent on the precedence level.
puts 8 / 9 Q 9

This line prints 7>. The multiplication operator has a higher precedence than addition. <irst the product of $P$ is calculated. Then : is added.
puts $ tru1 L tru1

In this case, the negation operator has a higher precedence. <irst, the first true value is negated to false, than the ` operator combines false and true, which gives true in the end.
$ .%pr1,1.1n,1.rb 68 J0 tru1 'a"s1

Associativity
)ometimes the precedence is not satisfactory to determine the outcome of an e%pression. There is another rule called associativity. The associativity of operators determines the order of evaluation of operators with the same precedence level.
@ % 8 Q 8

.hat is the outcome of this e%pressionQ # or "Q The multiplication, deletion and the modulo operator are left to right associated. )o the e%pression is evaluated this way5 (@ % 8) Q 8 and the result is #. 8rithmetic, boolean, relational and bitwise operators are all left to right associated. 2n the other hand, the assignment operator is right associated.
a ! b ! , ! . ! 0 print a< b< ,< . # prints 0000

If the association was left to right, the previous e%pression would not be possible. The compound assignment operators are right to left associated.
D ! 0 D Q! 8 / 1 puts D

#@

You might e%pect the result to be ". /ut the actual result is -, because of the associativity. The e%pression on the right is evaluated first and then the compound assignment operator is applied.

Range operators
Ruby has two range operators. They are used to ;uic ly create a range of objects. !ost often a range of numbers or letters. The .. range operator Atwo dotsB creates an inclusive range. The ... operator Athree dotsB creates an e%clusive range, where the high value of the range is e%cluded.
#$%usr%bin%rub& p (1..8).t-_a p (1...8).t-_a p (CaC .. C"C).t-_a

In the e%ample, we use both range operators to create a range of numbers and characters.
p (1..8).t-_a p (1...8).t-_a

These two lines create two ranges using both range operators. The range objects are converted to arrays. The first range has values ", 7 and : while the second range has values " and 7.
p (CaC .. C"C).t-_a

=ere we use the .. range operator to create an array of letters from EaE to ElE.
$ .%ran21.rb I1< 6< 8K I1< 6K I(a(< (b(< (,(< (.(< (1(< ('(< (2(< (*(< (i(< (D(< (H(< ("(K

This is the e%ample output.

-he ternary operator


The ternary operator AQ5B is a conditional operator. It is a convenient operator for cases where we want to pic up one of two values, depending on the conditional e%pression.
,-n.;10p U 10p1 : 10p6

If cond-e%p is true, e%p" is evaluated and the result is returned. If the cond-e%p is false, e%p7 is evaluated and its result is returned.
#$%usr%bin%rub& a21 ! 86

#$

a.u"t ! a21 >! 18 U tru1 : 'a"s1 i' a.u"t t*1n puts (7.u"t( 1"s1 puts (N-t a.u"t( 1n.

In most countries the adulthood is based on your age. You are adult if you are older than a certain age. In such a situation we can use a ternary operator.
a.u"t ! a21 >! 18 U tru1 : 'a"s1

<irst, the e%pression on the right side of the assignment operator is evaluated. The first phase of the ternary operator is the condition e%pression evaluation. )o if the age is greater or e;ual to ">, the value following the Q character is returned. If not, the value following the 5 character is returned. The returned value is then assigned to the adult variable.
$ .%t1rnar&.rb 7.u"t

8 :7 years old person is adult.

Calculating prime numbers


.e are going to calculate prime numbers.
#$%usr%bin%rub& nums ! (J..90).t-_a puts (Nrim1 numb1rs:( print (6 8 ( nums.1a,* .- LiL n-t_prim1 ! 'a"s1 (6..\at*.sBrt(i).,1i").1a,* .- LDL n-t_prim1 ! tru1 i' i R D !! 0 1n. print i< ( ( un"1ss n-t_prim1 1n. puts

In the above e%ample, we deal with several operators. 8 prime number Aor a primeB is a natural number that has e%actly two distinct natural number divisors5 " and itself. .e pic up a number and divide it by numbers, from 7 up to the pic ed up number. 8ctually, we donEt have to try all smaller numbers, we can divide by numbers up to the s;uare root of the chosen number. The formula will wor . 8t the core, of the algorithm we use the remainder division operator, called also a modulo operator.

#G

nums ! (J..90).t-_a

.e will calculate primes from these numbers.


print (6 8 (

.e s ip the calculations for the 7, : numbers. They are primes.


n-t_prim1 ! 'a"s1

The not0prime is a flag to indicate that the chosen number is not a prime. .e assume that the chosen number is a prime, untill it is proven otherwise later.
(6..\at*.sBrt(i).,1i").1a,* .- LDL n-t_prim1 ! tru1 i' i R D !! 0 1n.

.e are 2M if we only modulo divide by numbers smaller than the s;uare root of a number in ;uestion. If the remainder division operator returns - for any of the i values, then the number in ;uestion is not a prime.
print i< ( ( un"1ss n-t_prim1

.e print the number if the not0prime flag is not set.

The above e%ample was meant to demonstrate several operators. There is in fact an easier way to calculate prime numbers. Ruby has a module for calculating primes.
#$%usr%bin%rub& r1Buir1 Cprim1C Nrim1.1a,*(90) .- LiL print i< ( ( 1n. puts

8n e%ample calculating prime numbers up to $- using the Ruby prime module.


r1Buir1 Cprim1C

.e include the prime module.


Nrim1.1a,*(90) .- LiL print i< ( ( 1n.

.e calculate primes up to the upper bound Y $-.


$ .%prim1s.rb 6 8 9 11 18 1 1@ 68 6@ 81 8 J1 J8 J

#H

<rom this ouput we see primes between numbers 7 and $-. In this part of the Ruby tutorial, we covered the e%pressions.

)lo* control in Ruby


In this part of the Ruby tutorial, we will tal about the flow control. .e will define several eywords that enable us to control the flow of a Ruby program. +onditionals and loops alter the flow of a Ruby program. +onditionals are eywords that e%ecute a certain statement under a specific condition. 'oops are bloc s of program that are e%ecuted multiple times. .hen the program is run, the statements are e%ecuted from the top of the source file to the bottom. 2ne by one.

-he i* statement
The i' eyword is used to chec if an e%pression is true. If it is true, a statement is then e%ecuted. The statement can be a single statement or a compound statement. 8 compound statement consists of multiple statements enclosed by the bloc . 8 bloc is code enclosed by the 1n. eyword. The t*1n eyword is optional.
#$%usr%bin%rub& num ! 21ts.t-_i i' num > 0 t*1n puts (num :ariab"1 is p-siti:1( puts (num :ariab"1 1Bua"s t- #FnumG( 1n.

.e read a number from a user. If the number is greater than Iero, then we print two messages to the console. If not, nothing is done.
$ .%simp"1i'.rb J num :ariab"1 is p-siti:1 num :ariab"1 1Bua"s t- J

The condition is met and the message is written to the console.

.e can use the 1"s1 eyword to create a simple branch. If the e%pression inside the s;uare brac ets following the i' eyword evaluates to false, the statement following the 1"s1 eyword is automatically e%ecuted. The bloc of code is enclosed by the 1n. eyword.
#$%usr%bin%rub& a21 ! 1 i' a21 > 18

#>

1"s1 1n.

puts (Eri:in2 "i,1n,1 issu1.( puts (Eri:in2 "i,1n,1 n-t p1rmitt1.(

.e have an age variable. The boolean e%pression evaluates to false and we get FLriving licence not permittedF in the console.
$ .%"i,1n,1.rb Eri:in2 "i,1n,1 n-t p1rmitt1.

.e can create multiple branches using the 1"si' eyword. The 1"si' eyword tests for another condition, if and only if the previous condition was not met. 3ote that we can use multiple 1"si' eywords in our tests.
#$%usr%bin%rub& print (Ent1r a numb1r: ( num ! 21ts.t-_i i' num M 0 puts (#FnumG is n12ati:1( 1"si' num !! 0 puts (#FnumG is ?1r-( 1"si' num > 0 puts (#FnumG is p-siti:1( 1n.

.e have a numerical variable and we test it, if it is a negative number or positive or if it e;uals to Iero. Lepending on the value read from the user, we print one of the messages to the console.

-he case statement


The ,as1 statement is a selection control flow statement. It allows the value of a variable or e%pression to control the flow of program e%ecution via a multi way branch. It creates multiple branches in a simpler way than using the combination of i', 1"si' statements. .e have a variable or an e%pression. The ,as1 eyword is used to test a value from the variable or the e%pression against a list of values. The list of values is presented with the +*1n eyword. If the values match, the statement following the +*1n is e%ecuted. There is an optional 1"s1 statement. It is e%ecuted if no other match is found.
#$%usr%bin%rub& print (Ent1r t-p "1:1" .-main: ( .-main ! 21ts.,*-mp ,as1 .-main

##

+*1n (us( puts (Unit1. Stat1s( +*1n (.1( puts (=1rman&( +*1n (sH( puts (S"-:aHia( +*1n (*u( puts (Aun2ar&( 1"s1 puts (UnHn-+n( 1n.

In our program, we have a domain variable. .e read a value for the variable from the command line. .e use the +*1n statement to test for the value of the variable. There are several options. If the value e;uals for e%ample to FusF, the F&nited )tatesF string is printed to the console.
.-main ! 21ts.,*-mp

.e get an input from the user with the 21ts method. The input also includes the newline character. The newline is e%cluded with the ,*-mp method.
$ .%.-mains.rb Ent1r t-p "1:1" .-main: *u Aun2ar&

.e have entered FhuF string to the console and the program responded with F=ungaryF.

-he "hile& until statements


The +*i"1 statement is a control flow statement that allows code to be e%ecuted repeatedly based on a given boolean condition. It e%ecutes the code while the condition is true. The +*i"1 eyword e%ecutes the statements inside the bloc enclosed by the 1n. eyword. The statements are e%ecuted each time the e%pression is evaluated to true.
#$%usr%bin%rub& i ! 0 sum ! 0 +*i"1 i M 10 .i ! i / 1 sum ! sum / i 1n. puts ()*1 sum -' 0..@ :a"u1s is #FsumG(

In the code e%ample, we calculate the sum of values from a range of numbers. The +*i"1 loop has three parts5 initialiIation, testing and updating. *ach e%ecution of the statement is called a cycle.
i ! 0 sum ! 0

"--

.e initiate the i and the sum variables. The i is used as a counter.


+*i"1 i M 10 ... 1n. .-

The e%pression between the +*i"1 and .- eywords is the second phase, the testing. 3ote that the .- eyword is optional. The statements in the body are e%ecuted until the e%pression is evaluated to false.
i ! i / 1

This is the last, third phase of the +*i"1 loop Y the updating. .e increment the counter. 3ote that improper handling of the +*i"1 loops may lead to endless cycles.
$ .%+*i"1.rb )*1 sum -' 0..@ :a"u1s is 99

This is the output of the e%ample.

The unti" is a control flow statement which e%ecutes code while the condition is false. The loop stops when the condition is true.
#$%usr%bin%rub& *-urs_"1't ! 16 unti" *-urs_"1't !! 0 i' *-urs_"1't !! 1 puts ()*1r1 is #F*-urs_"1'tG *-ur "1't( 1"s1 puts ()*1r1 ar1 #F*-urs_"1'tG *-urs "1't( 1n. *-urs_"1't ;! 1 1n.

In our e%ample, we have a variable hours0left. .e begin a count down. In each loop cycle, we print how many hours are left there. .hen the variable e;uals Iero, the loop is stopped.
$ .%unti".rb )*1r1 ar1 16 *-urs "1't )*1r1 ar1 11 *-urs "1't )*1r1 ar1 10 *-urs "1't )*1r1 ar1 @ *-urs "1't )*1r1 ar1 8 *-urs "1't )*1r1 ar1 *-urs "1't )*1r1 ar1 > *-urs "1't )*1r1 ar1 9 *-urs "1't )*1r1 ar1 J *-urs "1't )*1r1 ar1 8 *-urs "1't )*1r1 ar1 6 *-urs "1't )*1r1 is 1 *-ur "1't

"-"

Running the e%ample we get this outcome.

-he *or statement


.hen the number of cycles is now before the loop is initiated, we can use the '-r statement. The for loop is used in conjuction with ranges. <or each element of a range a bloc of statements is e%ecuted. The statements are enclosed with the 1n. eyword. The .- eyword is optional.
#$%usr%bin%rub& '-r i in 0..@ .1n. puts (#FiG(

In this e%ample, we print numbers -..# to the console. In each of the loops the i variable holds a value from a range of numbers. The value is printed to the console. The .. range operator creates a list of numbers, including the last number.
$ .%'-r"--p.rb 0 1 6 8 J 9 > 8 @

This is the output of the e%ample.

To go through an array of elements using the for loop, we can use the "1n2t* method of the array.
#$%usr%bin%rub& p"an1ts ! I(\1r,ur&(< (V1nus(< (Eart*(< (\ars(< (3upit1r(< (Saturn(< (Uranus(< (N1ptun1(K '-r i in 0...p"an1ts."1n2t* puts p"an1tsIiK 1n.

In this e%ample, we have an array of planets. .e traverse the array and print each element of the array.
p"an1ts ! I(\1r,ur&(< (V1nus(< (Eart*(< (\ars(< (3upit1r(< (Saturn(< (Uranus(< (N1ptun1(K

This is an array of planets. "-7

'-r i in 0...p"an1ts."1n2t*

The "1n2t* method returns the length of the array. )ince arrays begin with -, the last inde% is n-". The ... range operator creates a range of numbers, e%cluding the last high value.
puts p"an1tsIiK

.e print the element having a specific inde% in the array.


$ .%p"an1ts6.rb \1r,ur& V1nus Eart* \ars 3upit1r Saturn Uranus N1ptun1

Running the above Ruby program gives this output.

-he each metho#


In Ruby, we can use the 1a,* method to iterate through items of an array. It ta es two parameters. 8n element and a bloc . The element is put between pipes. It is a placeholder for the item of the current iteration. The bloc is the code which is e%ecuted on each iteration.
#$%usr%bin%rub& p"an1ts ! I(\1r,ur&(< (V1nus(< (Eart*(< (\ars(< (3upit1r(< (Saturn(< (Uranus(< (N1ptun1(K p"an1ts.1a,* .- Lp"an1tL 1n. puts p"an1t

In this e%ample, we go through an array of planets using the 1a,* iterator.


p"an1ts.1a,* .- Lp"an1tL 1n. puts p"an1t

The 1a,* iterator is a method which wor s on the planets array. The planet is a placeholder for a current item of the iteration. .e could put there any character we wanted. .e could use JK characters instead of do, end eywords.

-he break& ne.t statements


The br1aH statement can be used to terminate a bloc defined by +*i"1, '-r or ,as1 statements.
#$%usr%bin%rub&

"-:

+*i"1 tru1 r ! 1 / ran.(80) print (#FrG ( i' r !! 66 br1aH 1n.

1n. puts

.e define an endless +*i"1 loop. .e use the br1aH statement to get out of this loop. .e choose a random value from " to :-. .e print the value. If the value e;uals to 77, we finish the endless while loop.
+*i"1 tru1 ... 1n.

This is an endless cycle. The condition for the while loop is always true. The only way to get out of this endless loop is to brea out.
r ! 1 / ran.(80) print (#FrG (

.e compute a random number from " to :- and print it to the console.


i' r !! 66 br1aH 1n.

If the number e;uals to 77, we brea the loop. The while cycle terminates.
$ .%br1aH.rb 60 1J > 6> 80 16 6 10 18 6@ 68 11 80 6> 60 66

.e might get something li e this.

The n10t statement is used to s ip a part of the loop and continue with the ne%t iteration of the loop. It can be used in combination with '-r and +*i"1 statements. In the following e%ample, we will print a list of numbers that cannot be divided by 7 without a remainder.
#$%usr%bin%rub& num ! 0 +*i"1 num M 100 num /! 1

"-@

i' (num R 6 !! 0) n10t 1n. 1n. puts print (#FnumG (

.e iterate through numbers "..## with the +*i"1 loop.


i' (num R 6 !! 0) n10t 1n.

If the e%pression num R 7 returns -, the number in ;uestion can be divided by 7. The n10t statement is e%ecuted and the rest of the cycle is s ipped. In our case, the last statement of the loop is s ipped and the number is not printed to the console. The ne%t iteration is started.
$ .%n10t.rb 1 8 9 @ 11 18 19 1 1@ 61 68 69 6 6@ 81 88 89 8 J1 J8 J9 J J@ 91 98 99 9 9@ >1 >8 >9 > >@ 1 8 @ 81 88 89 8 8@ @1 @8 @9 @ @@ 8@ 9

This is a sample output of the program.

-he re#o statement


The r1.- statement restarts an iteration of a loop, without chec ing the loop condition. The last e%ample will be a more comple% one. It will demonstrate the r1.- statement and other features as well.
#$%usr%bin%rub& -pti-ns ! I(r-,H(< (s,iss-rs(< (pap1r(K +*i"1 tru1 print MM)E^) 1 ; r-,H 6 ; s,iss-rs 8 ; pap1r @ ; 1n. 2am1 )E^) :a" ! 21ts.t-_i r ! ran.(8) / 1 i' :a" !! @ puts (En.( 10it 1n. i' $I1< 6< 8< @K.in,"u.1U(:a") puts (In:a"i. -pti-n( r1.-

"-$

1n. ,-mput1r ! -pti-nsIr;1K *uman ! -pti-nsI:a";1K puts (I *a:1 #F,-mput1rG< &-u *a:1 #F*umanG( i' :a" !! r puts ()i1< n10t t*r-+( r1.1n. i' :a" !! 1 an. r !! 6 puts (R-,H b"unts s,iss-rs< &-u +in( 1"si' :a" !! 6 an. r !! 1 puts (R-,H b"unts s,iss-rs< &-u "--s1( 1"si' :a" !! 6 an. r !! 8 puts (S,iss-rs ,ut pap1r< &-u +in( 1"si' :a" !! 8 an. r !! 6 puts (S,iss-rs ,ut pap1r< &-u "--s1( 1"si' :a" !! 8 an. r !! 1 puts (Nap1r ,-:1rs r-,H< &-u +in( 1"si' :a" !! 1 an. r !! 8 puts (Nap1r ,-:1rs r-,H< &-u "--s1( 1n. 1n.

.e have a simple Roc -paper-scissors game. In this code e%ample, we will utiliIe the r1.statement, conditionals, random numbers, arrays and user input.
-pti-ns ! I(r-,H(< (s,iss-rs(< (pap1r(K

.e have all possibilities of the game in the options array. These three words will be used when printing messages to the console.
print MM)E^) 1 ; r-,H 6 ; s,iss-rs 8 ; pap1r @ ; 1n. 2am1 )E^)

.e print the menu to the console using the heredoc synta%. The heredoc starts with [[ followed by a string. The same string closes the constructN it must be left aligned. This allows us to print multiple lines in one step. This menu is printed each game cycle.
:a" ! 21ts.t-_i r ! ran.(8) / 1

"-G

In these code lines, we read a value from the terminal. Then we select randomly a number among ", 7, :. 3ote that randA:B returns a number from -, ", 7. This is why we add ".
i' :a" !! @ puts (En.( 10it 1n.

If the input from the user e;uals #, we print E*ndE to the terminal and end the game. The 10it method terminates the program.
i' $I1< 6< 8< @K.in,"u.1U(:a") puts (In:a"i. -pti-n( r1.1n.

In case the user selects a different value than offered in the menu, we inform about the invalid option and redo the cycle.
,-mput1r ! -pti-nsIr;1K *uman ! -pti-nsI:a";1K puts (I *a:1 #F,-mput1rG< &-u *a:1 #F*umanG(

The numbers are transformed into strings. .e print both the userEs and the computerEs selection.
i' :a" !! r puts ()i1< n10t t*r-+( r1.1n.

If both parties have the same option, there is a tie. .e start a new game cycle. .e utiliIe the r1.- eyword.
i' :a" !! 1 an. r !! 6 puts (R-,H b"unts s,iss-rs< &-u +in( 1"si' :a" !! 6 an. r !! 1 puts (R-,H b"unts s,iss-rs< &-u "--s1( ...

&sing multiple i', 1"si' branches, we compare the selections of the user and the computer. .e decide, who is the winner.
$ .%r1.-.rb 1 ; r-,H 6 ; s,iss-rs 8 ; pap1r @ ; 1n. 2am1 8 I *a:1 pap1r< &-u *a:1 pap1r )i1< n10t t*r-+ 1 ; r-,H 6 ; s,iss-rs 8 ; pap1r

"-H

@ ; 1n. 2am1 6 I *a:1 r-,H< &-u *a:1 s,iss-rs R-,H b"unts s,iss-rs< &-u "--s1 1 ; r-,H 6 ; s,iss-rs 8 ; pap1r @ ; 1n. 2am1 1 I *a:1 s,iss-rs< &-u *a:1 r-,H R-,H b"unts s,iss-rs< &-u +in 1 ; r-,H 6 ; s,iss-rs 8 ; pap1r @ ; 1n. 2am1 @ En.

This is a sample output. In this part of the Ruby tutorial, we were tal ing about control flow structures.

+rrays in Ruby
In this part of the Ruby tutorial, we will cover arrays. 8rrays are ordered collections of objects. 8 variable can hold only one item at a time. 8rrays can hold multiple items. These items are called elements of the array. 8rrays can hold objects of any data type. *ach element can be referred to by an inde%. 8rrays are Iero based. The inde% of the first element is Iero. 3ote that Ruby arrays are very different from arrays in languages li e +, +?? or Java.
#$%usr%bin%rub& nums ! I1< 6< 8< J< 9K nums.1a,* .- LnumL puts num 1n.

2ur first e%ample will create an array of five integers. The elements of the array are printed to the console.
nums ! I1< 6< 8< J< 9K

This line creates an array of five integers. The elements are separated by commas and placed between s;uare brac ets.
nums.1a,* .- LnumL puts num 1n.

.e go through the array with the 1a,* method and print each element to the console. "->

$ .%arra&.rb 1 6 8 J 9

This is the output of the program.

Array creation
8n array in Ruby is an object. 8rrays can be instantiated with the n1+ method.
#$%usr%bin%rub& nums ! 7rra&.n1+ nums.pus* nums.pus* nums.pus* nums.pus* nums.pus* puts nums 1 6 8 J 9

In the script we first create a nums array. Then we add five integers to it.
nums ! 7rra&.n1+

8n array object is created.


nums.pus* 1

The pus* method appends an item to the end of the array.

.e will continue with the array object creation using the n1+ method.
#$%usr%bin%rub& a1 a6 a8 aJ a9 ! ! ! ! ! 7rra&.n1+ 7rra&.n1+ 7rra&.n1+ 7rra&.n1+ 7rra&.n1+ 8 >< (,-in( I11K (19) FL1L 1Q1G

puts Ia1< a6< a8< aJ< a9K.insp1,t

The n1+ method of the 8rray class may ta e some options.


a1 ! 7rra&.n1+

8n empty array is created. .e are supposed to fill it with data later on.
a6 ! 7rra&.n1+ 8

"-#

=ere we create an array of three nil objects.


a8 ! 7rra&.n1+ >< (,-in(

8n array containing si% FcoinF strings is created. The first option is the siIe of the array. The second option is the object to fill the array.
aJ ! 7rra&.n1+ I11K

The fourth array will have one item.


a9 ! 7rra&.n1+ (19) FL1L 1Q1G

.e create an array with "$ elements. *ach element is created in the bloc . There we compute a se;uence of s;uared integers.
puts Ia1< a6< a8< aJ< a9K.insp1,t

.e put all our arrays into one array. 8rrays may be put into other arrays. Then we call the insp1,t method on the array. This will call the method on all its elements. The insp1,t method returns the string representation of the array. This is useful when we need to ;uic ly chec the contents of an array.
$ .%arra&n1+.rb IIK< Ini"< ni"< ni"K< I(,-in(< (,-in(< (,-in(< (,-in(< (,-in(< (,-in(K< I11K< I0< 1< J< @< 1>< 69< 8>< J@< >J< 81< 100< 161< 1JJ< 1>@< 1@>KK

.e can see the contents of all the arrays created.

The following script shows various ways to create arrays in Ruby.


#$%usr%bin%rub& int121rs ! I1< 6< 8< J< 9K anima"s ! R+( .-nH1& .-2 ,at .-"p*in 1a2"1 ) +1i2*ts ! 7rra&.n1+ +1i2*ts MM J.99 MM 8.66 MM 8.99 MM 8.99 MM 8.68 puts int121rs.insp1,t puts anima"s.insp1,t puts +1i2*ts.insp1,t

.e create three arrays of integers, strings and decimals.


int121rs ! I1< 6< 8< J< 9K

This line creates an array having $ integers. This is the classic array creation. The elements of the array are put between s;uare brac ets and separated by commas.
anima"s ! R+( .-nH1& .-2 ,at .-"p*in 1a2"1 )

""-

The code line creates a string array with five elements. In this mode, we save some typing. .e do not use the commas and double ;uotes.
+1i2*ts ! 7rra&.n1+ +1i2*ts MM J.99 MM 8.66 MM 8.99 MM 8.99 MM 8.68

In the third way, there are two steps. <irst we creaet an 8rray object, then we initialiIe it with data. This is a formal array creation. The above ways were in fact shorthands for this notation.
puts int121rs.insp1,t

The insp1,t method prints the string representation of the array to the terminal.
$ .%,r1ati-n.rb I1< 6< 8< J< 9K I(.-nH1&(< (.-2(< (,at(< (.-"p*in(< (1a2"1(K IJ.99< 8.66< 8.99< 8.99< 8.68K

This is the output of the code e%ample.

8rray items are not limited to numbers and strings. 8rrays can contain all Ruby data types.
#$%usr%bin%rub& ,"ass Empt& 1n. nums ! I1< 6< 8< J< 9K :ari-us ! I1< ;1< (bi2(< 8.J< Empt&.n1+< nums< :t+-K puts :ari-us.insp1,t

.e put various Ruby objects inside the various array.


:ari-us ! I1< ;1< (bi2(< 8.J< Empt&.n1+< nums< :t+-K

The array contains numbers, a string, a custom object, another array and a symbol.
$ .%arra&-bD1,ts.rb I1< ;1< (bi2(< 8.J< #MEmpt&:00@8 ' 0J>< I1< 6< 8< J< 9K< :t+-K

Running the arrayobjects.rb e%ample, we receive this output.

The last e%ample showed a nested arrayN an array within another array. In Ruby, it is possible to nest arrays into arrays.
#$%usr%bin%rub& numb1rs ! I1< 6< 8< I6< J< >< I11< 16KKK

"""

puts numb1rs."1n2t* puts numb1rsI0K< numb1rsI1K puts numb1rsI8KI0K puts numb1rsI8KI1K puts numb1rsI8KI8KI0K puts numb1rsI8KI8KI1K puts numb1rs.'"att1n$.insp1,t

The array S"", "7T is nested within the S7, @, G, ...T array, which is also nested in the S", 7, :, ...T array.
puts numb1rs."1n2t*

The "1n2t* method returns @. The inner array is counted as one element.
puts numb1rsI0K< numb1rsI1K

The ST characters serve in this conte%t the purpose of accessing array elements. The above line returns the first and the second element Anumbers " and 7B of the numbers array. The numbers within the s;uare brac ets are inde%es to the array. The first inde% is -, which returns the first element.
puts numb1rsI8KI0K puts numb1rsI8KI1K

=ere we access elements from the nested array. The S:T grabs the fourth element, which is an array, S7, @, G, S"", "7TT. The S:TS-T returns the first element of the inner array, which is number 7 in our case. In a similar fashion, the S:TS"T returns the second element of the inner array, the number @.
puts numb1rsI8KI8KI0K puts numb1rsI8KI8KI1K

3ow we go even deeper. .e access the elements of the innermost array. The S:TS:T return the S"", "7T array. 8nd from this array we get the first A""B and the second A"7B element.
puts numb1rs.'"att1n$.insp1,t

The '"att1n$ method flattens the array. It ta es all elements from the inner arrays and creates a new one, without any inner arrays.
$ .%arra&-'arra&s.rb J 1 6 6 J 11 16 I1< 6< 8< 6< J< >< 11< 16K

""7

This is the output of the code e%ample.

Printing array contents


8 common job is to print array elements to to console. .e have several ways to accomplish this tas .
#$%usr%bin%rub& int121rs ! I1< 6< 8< J< 9K puts int121rs puts int121rs.insp1,t int121rs.1a,* .- L1L puts 1 1n.

In this script, we print all the elements of an array three times.


puts int121rs

The array as a parameter to the puts6print method is the simplest way to print the contents of the array. *ach element is printed on a separate line.
puts int121rs.insp1,t

&sing the insp1,t method, the output is more readable. The line prints the string representation of the array to the terminal.
int121rs.1a,* .- L1L puts 1 1n.

The 1a,* method calls a bloc once for each element in array, passing that element as a parameter. .e simply use the puts method on each element.
$ .%printarra&1.rb 1 6 8 J 9 I1< 6< 8< J< 9K 1 6 8 J 9

The array is printed three times to the console.

In the second e%ample, we provide additional two ways to print array elements.

"":

#$%usr%bin%rub& int121rs ! I1< 6< 8< J< 9K int121rs."1n2t*.tim1s .- Li.0L puts int121rsIi.0K 1n. int121rs.1a,*_+it*_in.10 .- Lnum< i.0L puts (:a"u1 #FnumG *as in.10 #Fi.0G( 1n.

In the first case, we use the combination of the "1n2t* and tim1s methods. In the second case, we use the 1a,*_+it*_in.10 method.
int121rs."1n2t*.tim1s .- Li.0L puts int121rsIi.0K 1n.

The "1n2t* method returns the siIe of the array. The tim1s method iterates the following bloc length times, passing in values from - to length-". These numbers serve as inde%es to the array in ;uestion.
int121rs.1a,*_+it*_in.10 .- Lnum< i.0L puts (:a"u1 #FnumG *as in.10 #Fi.0G( 1n.

The 1a,*_+it*_in.10 iterates the array and passes the element and its inde% to the given bloc . This way we can easily print the element and its inde% in one shot.
$ .%printarra&6.rb 1 6 8 J 9 :a"u1 1 *as in.10 0 :a"u1 6 *as in.10 1 :a"u1 8 *as in.10 6 :a"u1 J *as in.10 8 :a"u1 9 *as in.10 J

This is the output of the e%ample.

Rea#ing array elements


In this section, we will read data from the arrays.
#$%usr%bin%rub& "ts ! R+F a b , . 1 ' 2 *G puts "ts.'irst puts "ts."ast puts "ts.at(8)

""@

In the first e%ample, we show three simple methods for data retrieval.
puts "ts.'irst puts "ts."ast

The 'irst method reads the first element of the array. The "ast method reads the last element of the array.
puts "ts.at(8)

The at method returns the array element having a specific inde%. This line reads the fourth element of the array.
$ .%r1tri1:a".rb a * .

This is the output of the retrieval.rb program.

The ST characters can be used to access data. This is the traditional way of accessing data in arrays, used by many other programming languages. It saves some typing.
#$%usr%bin%rub& "ts ! R+F a b , . 1 ' 2 * G puts puts puts puts puts "tsI0K "tsI;1K "tsI0< 8K.insp1,t "tsI6..>K.insp1,t "tsI6...>K.insp1,t

.e show five e%amples of reading data using the ST characters.


puts "tsI0K puts "tsI;1K

.e get the first and the last item of the array. .e put the inde% number of an item between the ST characters. The first item has inde% -, the last item has inde% -".
puts "tsI0< 8K.insp1,t

.hen we have two numbers between the s;uare brac ets, the first is the start inde% and the second is the length. In this code line, we return : elements starting from inde% -. 3ote that the insp1,t method is optional and it is only used to produce more readable output.
puts "tsI6..>K.insp1,t puts "tsI6...>K.insp1,t

.e can use range operator inside the s;uare brac ets. In the first line we read elements from inde% 7 to G, in the second line elements from 7 to $.

""$

3e%t we will demonstrate the :a"u1s_at method. The advantage of this method is that we can place multiple inde%es between the ST characters to get various elements.
#$%usr%bin%rub& "ts ! R+F a b , . 1 ' 2 *G puts puts puts puts "ts.:a"u1s_at(1..9).insp1,t "ts.:a"u1s_at(1< 8< 9).insp1,t "ts.:a"u1s_at(1< 8< 9< >< 8).insp1,t "ts.:a"u1s_at(;1< ;8).insp1,t

The :a"u1s_at method returns an array containing the elements which corresponding to the given selectorAsB. The insp1,t method is optional. It is used to get a more readable output.
puts "ts.:a"u1s_at(1..9).insp1,t

This code line returns elements which have inde%es " to $.


puts "ts.:a"u1s_at(1< 8< 9).insp1,t

=ere we read elements with inde%es ", : and $.


puts "ts.:a"u1s_at(1< 8< 9< >< 8).insp1,t

.e put as many inde%es as we want. If there is no element with the specific inde%, we get nil.
puts "ts.:a"u1s_at(;1< ;8).insp1,t

3egative inde%es return elements from the end of the array.


$ .%r1tri1:a"8.rb I(b(< (,(< (.(< (1(< ('(K I(b(< (.(< ('(K I(b(< (.(< ('(< (2(< ni"K I(*(< ('(K

This is the output of the script.

.e will use the '1t,* method to read data from an array.


#$%usr%bin%rub& "ts ! I0< 1< 6< 8< J< 9< >K puts puts puts puts "ts.'1t,*(0) "ts.'1t,*(;6) "ts.'1t,*(8< Cun.1'in1.C) "ts.'1t,*(8) F L1L ;6Q1 G

.e show several forms of using the '1t,* method.

""G

puts "ts.'1t,*(0) puts "ts.'1t,*(;6)

The first line prints the first element from the array. The second line prints the second element from the end of the array.
puts "ts.'1t,*(8< Cun.1'in1.C)

The third form of the '1t,* method returns the element with the given inde%. If the inde% lies outside the array elements, the method returns the default value, EundefinedE in our case. .ithout the second parameter, the '1t,* method throws an In.10Err-r.
puts "ts.'1t,*(8) F L1L ;6Q1 G

In the last form of the '1t,* method, we have a bloc . In case a value with a given inde% is not found, the method returns a value of invo ing the bloc , passing in the inde%.
$ .%r1tri1:a"J.rb 0 9 un.1'in1. ;1>

This is the output of the script.

.e will show the usage of the taH1 and taH1_+*i"1 methods.


#$%usr%bin%rub& "ts ! R+F a b , . 1 ' 2 *G puts "ts.taH1(J).insp1,t "ts6 ! "ts.taH1_+*i"1 F L1L 1 M C'C G puts "ts6.insp1,t

The taH1 n method returns the first n elements of the array. The taH1_+*i"1 method passes elements to the bloc until the bloc returns nil or false, then stops iterating and returns an array of all prior elements.
puts "ts.taH1(J).insp1,t

=ere we return the first four elements of the array.


"ts6 ! "ts.taH1_+*i"1 F L1L 1 M C'C G puts "ts6.insp1,t

=ere we create a new array from the original array. In the new array we have all characters that come before the EfE character.
$ .%r1tri1:a"9.rb I(a(< (b(< (,(< (.(K

""H

I(a(< (b(< (,(< (.(< (1(K

=ere we see the output of the retrieval$.rb program.

The s"i,1 method is identical to the ST characters. The method returns one or more elements from the array.
#$%usr%bin%rub& "ts ! R+F a b , . 1 ' 2 *G puts puts puts puts puts "ts.s"i,1(0) "ts.s"i,1(;1) "ts.s"i,1(0< 8).insp1,t "ts.s"i,1(6..>).insp1,t "ts.s"i,1(6...>).insp1,t

.e present five e%amples of the s"i,1 method.


puts "ts.s"i,1(0) puts "ts.s"i,1(;1)

These forms of the s"i,1 method return one array element. The first code line returns the first element, the second line returns the last element of the lts array.
puts "ts.s"i,1(0< 8).insp1,t

The first parameter is the start inde% and the second parameter is the length. In this code line, we return : elements starting from inde% -.
puts "ts.s"i,1(6..>).insp1,t puts "ts.s"i,1(6...>).insp1,t

.e can use range operator with the s"i,1 method. In the first line we read elements from inde% 7 to G, in the second line elements from 7 to $.
$ .%r1tri1:a">.rb a * I(a(< (b(< (,(K I(,(< (.(< (1(< ('(< (2(K I(,(< (.(< (1(< ('(K

The s"i,1 method returns portions of the array, one or more elements of the array.

It is possible to select a random number from an array. Ruby has a samp"1 method for this.
#$%usr%bin%rub& "ts ! R+F a b , . 1 ' 2 *G puts "ts.samp"1

"">

puts "ts.samp"1(8).insp1,t

The samp"1 method comes in two forms. In the first form, we select a random element. In the second form, we select n random elements from the array.
$ .%ran.-m.rb b I(,(< ('(< (.(K $ .%ran.-m.rb . I(,(< (.(< (1(K

Running the e%ample twice gives different results.

Working "ith arrays


In the following e%amples, we will introduce several Ruby array methods.
#$%usr%bin%rub& num1 ! I1< 6< 8< J< 9K num6 ! I>< < 8< @< 10K puts num1 / num6 puts num1.,-n,at num6

.e have two arrays. .e add these two arrays.


puts num1 / num6 puts num1.,-n,at num6

There are two ways to add arrays. .e can use the ? operator or the ,-n,at method. The result is the same.

Ruby has plenty of methods for wor ing with arrays. <or e%ample, the "1n2t* method returns the number of elements in the array.
#$%usr%bin%rub& "ts ! R+F a b , . 1 'G puts puts puts puts "ts.insp1,t (7rra& *as #F"ts."1n2t*G 1"1m1nts( ()*1 'irst 1"1m1nt is #F"ts.'irstG( ()*1 "ast 1"1m1nt is #F"ts."astG(

puts "ts.1B"U "ts..up puts "ts.1B"U "ts..up..1"1t1_at(0) "ts.,"1ar puts "ts.insp1,t puts "ts.1mpt&U

In the above script, we introduce seven new methods.

""#

puts (7rra& *as #F"ts."1n2t*G 1"1m1nts(

The "1n2t* method determines the siIe of the array.


puts ()*1 'irst 1"1m1nt is #F"ts.'irstG( puts ()*1 "ast 1"1m1nt is #F"ts."astG(

=ere we get the first and the last element of the array.
puts "ts.1B"U "ts..up

The 1B"U method figures out if two arrays are e;ual. In our case the line returns true. The .up method creates a shallow copy of an object. It is inherited from the ObD1,t parent.
puts "ts.1B"U "ts..up..1"1t1_at(0)

The .1"1t1_at method deletes the first element of the array. This time the two arrays do not e;ual.
"ts.,"1ar

The ,"1ar method deletes all elements from the array.


puts "ts.1mpt&U

The 1mpt&U method chec s, whether the array is empty. In our case the code line returns true, because we have just deleted all its elements.
$ .%basi,s.rb I(a(< (b(< (,(< (.(< (1(< ('(K 7rra& *as > 1"1m1nts )*1 'irst 1"1m1nt is a )*1 "ast 1"1m1nt is ' tru1 'a"s1 IK tru1

This is the output of the e%ample.

)ome Ruby array methods end with an e%clamation mar . This is a Ruby idiom. The e%clamation mar tells the programmer that the method will modify data. The e%clamation mar itself does not have any effect. It is merely a naming convention.
#$%usr%bin%rub& ,*ars ! R+Fa b , . 1G r1:1rs1._,*ars ! ,*ars.r1:1rs1 puts r1:1rs1._,*ars.insp1,t puts ,*ars.insp1,t r1:1rs1._,*ars ! ,*ars.r1:1rs1$

"7-

puts r1:1rs1._,*ars.insp1,t puts ,*ars.insp1,t

Ruby has, among others, two similar methods, the r1:1rs1 method and r1:1rs1$ method. These two methods change the order of the elements, they reverse it. The difference is, that the r1:1rs1 method returns a reversed array and leaves the original array intact, while the r1:1rs1$ method both modifies the contents of the original array.
$ .%t+-t&p1s.rb I(1(< (.(< (,(< I(a(< (b(< (,(< I(1(< (.(< (,(< I(1(< (.(< (,(< (b(< (.(< (b(< (b(< (a(K (1(K (a(K (a(K

.e can clearly see that the first two arrays are different. The third and fourth arrays are same.

8 few other methods will be presented in the coming code e%ample.


#$%usr%bin%rub& numb1rs ! I1< 6< 6< 6< 8< J< 9< 8< 11K puts numb1rs.in.10 6 puts numb1rs.in.10 11 puts numb1rs.rin.10 6 puts numb1rs.in,"u.1U 8 puts numb1rs.in,"u.1U 10 puts numb1rs.D-in C;C puts numb1rs.uniB$.insp1,t

.e introduce additional five methods.


puts numb1rs.in.10 6 puts numb1rs.in.10 11

The in.10 method returns the inde% of the array element. It returns the inde% of the first element from the left. The first line returns ", which is the inde% of the first 7 in the array. There is only one "" in the array and its inde% is >.
puts numb1rs.rin.10 6

The rin.10 returns the inde% of the first element from the right. In our case, the rightmost 7 has inde% :.
puts numb1rs.in,"u.1U 8 puts numb1rs.in,"u.1U 10

The in,"u.1U method chec s if an element is present in the array. The first line returns trueN : is present. The second line returns falseN there is no "- in our array. /y convention, Ruby methods ending with ;uestion mar return a boolean value. 8gain, the ;uestion mar has no effect on the array. It is merely a hint for the programmer.

"7"

puts numb1rs.D-in C;C

The D-in method returns a string created from the array elements, separated by a provided separator.
puts numb1rs.uniB$.insp1,t

The uniB$ method removes duplicate elements from the array. .e have three times number 7 in the array. 8fter the method call, there will be only one 7 left.
$ .%m1t*-.s6.rb 1 8 8 tru1 'a"s1 1;6;6;6;8;J;9;8;11 I1< 6< 8< J< 9< 8< 11K

3otice the product of the D-in method. It is a string in which the numbers of the array are joined by the - character.

1o#i*ying arrays
In this section, we will loo closer at the methods that modify an array. /asically, we will do various insertion and deletion operations on the arrays.
#$%usr%bin%rub& "ts ! IK "ts.ins1rt 0< CEC< C]C< C=C "ts.pus* CAC "ts.pus* CIC< C3C< CZC "ts MM CYC MM C\C "ts.uns*i't C7C< CBC< C5C "ts.ins1rt(8< CEC) puts "ts.insp1,t

.e start with an empty array. .e build the array using different insertion methods.
"ts.ins1rt 0< CEC< C]C< C=C

The ins1rt method inserts three elements into the lts array. The first letter has inde% -, the second " and the third :.
"ts.pus* CAC "ts.pus* CIC< C3C< CZC

The pus* method appends the elements to the array. .e can append one or more elements.
"ts MM CYC MM C\C

"77

The [[ is a synonym for the pus* method. It appends an element to the array. This operator6method can be called in a chain.
"ts.uns*i't C7C< CBC< C5C

The uns*i't method prepends elements to the front of the array.


"ts.ins1rt(8< CEC)

In this case, the ins1rt method inserts the ELE character at a specific inde%.
$ .%ins1rti-n.rb I(7(< (B(< (5(< (E(< (E(< (](< (=(< (A(< (I(< (3(< (Z(< (Y(< (\(K

&sing the above mentioned array insertion methods, we have built this array of uppercase letters.

There are several methods for deleting array elements.


#$%usr%bin%rub& "ts ! R+F a b , . 1 ' 2 *G "ts.p-p "ts.p-p puts "ts.insp1,t "ts.s*i't "ts.s*i't puts "ts.insp1,t "ts..1"1t1_at(0) "ts..1"1t1(C.C) puts "ts.insp1,t puts "ts.,"1ar puts "ts.insp1,t

In this script we demonstrate five methods that delete elements from an array.
"ts ! R+F a b , . 1 ' 2 *G

.e have an array of > elements.


"ts.p-p

The p-p method removes the last element from the array.
"ts.s*i't

The s*i't method removes the first element from the array. "7:

"ts..1"1t1_at(0)

The .1"1t1_at deletes an element at a specific position. .e delete the first element of the remaining elements.
puts "ts.,"1ar

The ,"1ar method clears all the elements from the array.
"ts..1"1t1(C.C)

The .1"1t1 method deletes a specific item from the array.


$ .%.1"1ti-n.rb I(a(< (b(< (,(< (.(< (1(< ('(K I(,(< (.(< (1(< ('(K I(1(< ('(K IK

=ere we see the output of the e%ample.

)o far we have wor ed with methods Awith an e%ception of the ,"1ar methodB that modified an array by adding or deleting an item a time. Ruby has methods that affect multiple array items at once.
#$%usr%bin%rub& nms ! I6< ;1< ;J< 0< J< 8< ;6< 8< 9K nms..1"1t1_i' F L0L 0 M 0 G puts nms.insp1,t

The e%ample introduces a .1"1t1_i' method that deletes all items that meet a condition presented in the bloc .
nms..1"1t1_i' F L0L 0 M 0 G

This line deletes all negative numbers from the array.


$ .%.1"1t1_i'.rb I6< 0< J< 8< 8< 9K

.e have dropped all negative numbers from the nms array.

.e present another two methods that process multiple array items.


#$%usr%bin%rub& "ts ! R+F a b , . 1 ' 2G puts "ts.insp1,t

"7@

"ts.r1D1,t$ .- L1L 1 !P %I,;&K% 1n. puts "ts.insp1,t "ts.r1p"a,1(I(0(< (&(< (?(K) puts "ts.insp1,t

.e use two methods, the r1D1,t$ method and the r1p"a,1 method.
"ts.r1D1,t$ .- L1L 1 !P %I,;&K% 1n.

The r1D1,t$ method removes all array items that meet a specific condition inside the bloc . In our case, we delete all letters that comply with the regular e%pressionN any letter from c to y. The 9U operator matches strings against regular e%pressions.
"ts.r1p"a,1(I(0(< (&(< (?(K)

The r1p"a,1 method will replace items with other given items. It truncates or e%pands the array if necessary.
$ .%m-.i'&.rb I(a(< (b(< (,(< (.(< (1(< ('(< (2(K I(a(< (b(K I(0(< (&(< (?(K

This is the output of the m-.i'&.rb e%ample.

Set operations
In this section, we present set operations applicable on Ruby arrays. In mathematics a set is a is a collection of distinct objects.
#$%usr%bin%rub& 7 ! I1< 6< 8< J< 9K B ! IJ< 9< >< < 8K uni-n ! 7 L B is1,t ! 7 S B .i''1 ! 7 ; B .i''6 ! B ; 7 s.i'' ! (7 ; B) L (B ; 7) puts puts puts puts puts (Uni-n -' arra&s: #Funi-nG( (Int1rs1,ti-n -' arra&s: #Fis1,tG( (Ei''1r1n,1 -' arra&s 7 ; B: #F.i''1G( (Ei''1r1n,1 -' arra&s B ; 7: #F.i''6G( (S&mm1tri, .i''1r1n,1 -' arra&s: #Fs.i''G(

"7$

In the above script, we demonstrate several set operations, union, intersection, difference and symmetric difference.
nums1 ! I1< 6< 8< J< 9K nums6 ! IJ< 9< >< < 8K

.e define two arrays of integers. /oth are sets, because each element in the array is presented only once. The two arrays have two numbers in common, the @ and $.
uni-n ! nums1 L nums6

This operation is a union of two arrays. The two arrays are added. *ach element in the final array is presented only once.
is1,t ! 7 S B

The above operations is intersection of two sets. The outcome is an array having elements which are present in both arrays. In our case, @ and $.
.i''1 .i''6 ! 7 ; B ! B ; 7

=ere we have two difference operations, also called complements. In the first line, we get all elements that are present in 8 and not present in /. In the second line, we get all elements which are members of / and not 8.
s.i'' ! (7 ; B) L (B ; 7)

=ere we have a symmetric difference. 8 symmetric difference gives elements that are either in 8 or in /, but not in both sets.
$ .%s1t-p1rati-ns.rb Uni-n -' arra&s: I1< 6< 8< J< 9< >< < 8K Int1rs1,ti-n -' arra&s: IJ< 9K Ei''1r1n,1 -' arra&s 7 ; B: I1< 6< 8K Ei''1r1n,1 -' arra&s B ; 7: I>< < 8K S&mm1tri, .i''1r1n,1 -' arra&s: I1< 6< 8< ><

< 8K

This is the output of the e%ample.

-he select& collect& map metho#s


In the ne%t e%ample, we will present three methods5 the s1"1,t, ,-""1,t and map method.
#$%usr%bin%rub& nums ! I1< 8< 6< >< < 16< 8< 19K

s1"1,t1. ! nums.s1"1,t .- L1L 1 > 10 1n. puts s1"1,t1..insp1,t

"7G

,-""1,t1. ! nums.,-""1,t .- L1L 1 M 10 1n. puts ,-""1,t1..insp1,t mapp1. ! nums.map .- L1L 1Q6 1n. puts mapp1..insp1,t

8ll these methods e%ecute mass operations on the elements of an array.


s1"1,t1. ! nums.s1"1,t .- L1L 1 > 10 1n.

In the above code, we create a new array using the s1"1,t method. <or the newly created array, we choose elements that comply with the condition inside the bloc . In our case, we select all elements that are greater than "-.
,-""1,t1. ! nums.,-""1,t .- L1L 1 M 10 1n.

The ,-""1,t method wor s a bit differently. It invo es the appended bloc for each element and returns the value from the bloc . The new array contains true, false values.
mapp1. ! nums.map .- L1L 1Q6 1n.

The map method wor s the same as the ,-""1,t method. In the above lines we create a new array from the e%isting array. *ach element is multiplied by 7.
$ .%mass.rb I16< 19K Itru1< tru1< tru1< tru1< tru1< 'a"s1< tru1< 'a"s1K I6< >< J< 16< 1J< 6J< 1>< 80K

These are the newly created arrays.

Or#ering elements
<inally, we will be ordering elements in our array.
#$%usr%bin%rub& p"an1ts ! R+F \1r,ur& V1nus Eart* \ars 3upit1r Saturn Uranus N1ptun1 N"ut- G puts (#Fp"an1ts.s-rtG( puts (#Fp"an1ts.r1:1rs1G( puts (#Fp"an1ts.s*u''"1G(

"7H

The e%ample uses three Ruby array methods to reorganiIe elements in the array.
puts (#Fp"an1ts.s-rtG(

The s-rt method alphabetically sorts the array elements.


puts (#Fp"an1ts.r1:1rs1G(

The r1:1rs1 method returns a new array with all elements in a reverse order.
puts (#Fp"an1ts.s*u''"1G(

The s*u''"1 method randomly reorganiIes the array elements.


$ .%-r.1rin2.rb I(Eart*(< (3upit1r(< (\ars(< (\1r,ur&(< (N1ptun1(< (N"ut-(< (Saturn(< ...K I(N"ut-(< (N1ptun1(< (Uranus(< (Saturn(< (3upit1r(< (\ars(< (Eart*(< ...K I(Eart*(< (3upit1r(< (\1r,ur&(< (Saturn(< (\ars(< (V1nus(< (Uranus(< ...K

This is a sample output of the code e%ample. In this chapter, we wor ed with Ruby arrays.

,ashes in Ruby
This part of the Ruby tutorial will mention Ruby hashes. 8 hash is a collection of ey-value pairs. It is similar to an array. &nli e arrays, hashes can have arbitrary objects as inde%es. 8rrays have can only have integers. =ashes are sometimes called associated arrays. =ashes are powerful collections. They have many methods that programmers can use to do their wor .

3ash creation
8 hash can be created in two basic ways5 with the n1+ eyword or with the hash literal.
#$%usr%bin%rub& nam1s ! Aas*.n1+ nam1sI1K ! (3an1( nam1sI6K ! ()*-mas( puts nam1s

The first script creates a hash and adds two ey-value pairs into the hash object.
nam1s ! Aas*.n1+

8 hash object is created.


nam1sI1K ! (3an1( nam1sI6K ! ()*-mas(

"7>

.e add two pairs of values to the hash. The numbers ", 7 are the eys to the hash. The eys are placed inside the s;uare brac ets. The names are the values that belong to the eys.
puts nam1s

The puts method prints the string representation of the hash to the console. It is also the string literal of the hash.
$ .%,r1at1.rb F1!>(3an1(< 6!>()*-mas(G

<rom the output we can see the literal representation of the names hash. 8 hash is bounded by curly brac ets. The eys and the values are paired with the 9^ characters.

8 st-r1 method can be used to initialiIe the hash with some values. It can be use instead of the s;uare brac ets.
#$%usr%bin%rub& nam1s ! Aas*.n1+ nam1s.st-r1(1< (3an1() nam1s.st-r1(6< ()*-mas() nam1s.st-r1(8< (R1b1,,a() puts nam1s

.e have a similar script. This time we use the st-r1 method. The method associates the given ey with the given value and stores the pair in the hash.
nam1s.st-r1(1< (3an1()

The first parameter of the st-r1 method is the ey and the second parameter is the value.

In the third script, we create a hash with the hash literal notation. The values are bound by the curly brac ets. 8nd the ey-value pairs are associated with the 9^ characters.
#$%usr%bin%rub& .-mains ! F (.1( (sH( (*u( (us( (n-( G !> !> !> !> !> (=1rman&(< (S"-:aHia(< (Aun2ar&(< (Unit1. Stat1s(< (N-r+a&(

puts .-mainsI(.1(K puts .-mainsI(sH(K

.e create a domains hash with $ pairs. This time both eys and values are string types.
.-mains ! F (.1( !> (=1rman&(< (sH( !> (S"-:aHia(<

"7#

(*u( !> (Aun2ar&(< (us( !> (Unit1. Stat1s(< (n-( !> (N-r+a&(

This is a hash literal notation. The ey-value pairs are put between the curly brac ets. The items are separated by the comma character. 8nd the eys are associated with values using the 9^ characters combination.
puts .-mainsI(.1(K

=ere we print the domain value name associated with the FdeF ey.
$ .%,r1at18.rb =1rman& S"-:aHia

This is the output of the code e%ample.

Basic "ork
In this section, we present some methods for the very basic wor with Ruby hashes.
#$%usr%bin%rub& nam1s ! Aas*.n1+ nam1sI1K nam1sI6K nam1sI8K nam1sIJK nam1sI9K ! ! ! ! ! (3an1( ()*-mas( (R-b1rt( (3u"ia( (R1b1,,a(

puts ()*1 si?1 -' t*1 *as* is #Fnam1s.si?1G( puts nam1s.H1&s.insp1,t puts nam1s.:a"u1s.insp1,t

In the above Ruby script, we create a hash with five values. .e introduce three hash methods.
puts ()*1 si?1 -' t*1 *as* is #Fnam1s.si?1G(

The si?1 method returns the siIe of the hash. It is a synonym for the "1n2t* method.
puts nam1s.H1&s.insp1,t puts nam1s.:a"u1s.insp1,t

The H1&s method returns all eys of the hash. In a similar fashion, the :a"u1s method returns all the values of the hash. The returned data is in the form of an array. To have a more readable output, we also call the insp1,t method on the returned arrays.
$ .%basi,.rb )*1 si?1 -' t*1 *as* is 9 I1< 6< 8< J< 9K

":-

I(3an1(< ()*-mas(< (R-b1rt(< (3u"ia(< (R1b1,,a(K

.e see the ouput of the e%ample. 3ote that the output of the last two methods are two arrays.

The second e%ample of the section presents three distinct hash methods.
#$%usr%bin%rub& nam1s1 ! Aas*.n1+ nam1s1I1K nam1s1I6K nam1s1I8K nam1s1IJK nam1s1I9K ! ! ! ! ! (3an1( ()*-mas( (R-b1rt( (3u"ia( (R1b1,,a(

nam1s6 ! nam1s1..up puts nam1s1.1B"U nam1s6 puts nam1s1.1mpt&U nam1s1.,"1ar puts nam1s1.1mpt&U

The Ruby script creates a names hash. It calls three hash methods on the object.
nam1s6 ! nam1s1..up

.e create a duplicate of the hash by calling the .up method. The method is inherited by the hash from the parent object.
puts nam1s1.1B"U nam1s6

The 1B"U method compares two hash objects. In our case the hashes are e;ual and the line prints true.
puts nam1s1.1mpt&U

The 1mpt&U method chec s whether the hash is empty or not. The line print false because the names" hash has five items.
nam1s1.,"1ar puts nam1s1.1mpt&U

The ,"1ar method deletes all items from the hash. The successive call of the 1mpt&U method returns true.
$ .%basi,6.rb tru1 'a"s1 tru1

This is the e%ample output.

":"

.e have methods that can determine whether a ey or a value is present in the hash.
#$%usr%bin%rub& .-mains ! F :.1 !> (=1rman&(< :sH !> (S"-:aHia(< :n- !> (N-r+a&(< :us !> (Unit1. Stat1s( G puts puts puts puts .-mains.*as_H1&U :.1 .-mains.in,"u.1U :n.-mains.H1&U :m1 .-mains.m1mb1rU :sH

puts .-mains.*as_:a"u1U (S"-:aHia( puts .-mains.:a"u1U (=1rman&(

.e create a domains hash with four pairs. The eys are symbols. )ymbols are often used as eys, because they are more efficient.
puts puts puts puts .-mains.*as_H1&U :.1 .-mains.in,"u.1U :n.-mains.H1&U :m1 .-mains.m1mb1rU :sH

=ere we have four methods that determine whether a ey is in the hash. They all do the sameN they are synonyms.
puts .-mains.*as_:a"u1U (S"-:aHia( puts .-mains.:a"u1U (=1rman&(

These two methods chec if the two strings are inside the hash.
$ .%*as.rb tru1 tru1 'a"s1 tru1 tru1 tru1

This is the output of the e%ample.

In the final e%ample of the section, we will read values from the hash.
#$%usr%bin%rub& st-n1s ! F 1 !> (2arn1t(< 6 !> (t-pa?(< 8 !> (-pa"(< J !> (am1t*&st( G puts st-n1s.'1t,* 1 puts st-n1sI6K puts st-n1s.:a"u1s_at 1< 6< 8

":7

The Ruby script presents three hash methods for reading values of a hash.
puts st-n1s.'1t,* 1

The '1t,* method reads a value for a given ey.


puts st-n1sI6K

);uare brac ets can be used to get a value. In our case, the line prints FtopaIF to the console.
puts st-n1s.:a"u1s_at 1< 6< 8

The :a"u1s_at method can be used to get multiple values at one step. The method returns an array of the values for the given eys.
$ .%r1a..rb 2arn1t t-pa? 2arn1t t-pa? -pa"

This is the output of the e%ample.

%ooping through a hash


There are several methods that can be used to loop through a Ruby hash.
#$%usr%bin%rub& st-n1s ! F 1 !> (2arn1t(< 6 !> (t-pa?(< 8 !> (-pa"(< J !> (am1t*&st( G st-n1s.1a,* F LH< :L puts (Z1&: #FHG< Va"u1: #F:G( G st-n1s.1a,*_H1& F LH1&L puts (#FH1&G( G st-n1s.1a,*_:a"u1 F L:a"L puts (#F:a"G( G st-n1s.1a,*_pair F LH< :L puts (Z1&: #FHG< Va"u1: #F:G( G

In the above e%ample, we present four methods. .e use them to display all eys, values and both eys and values of a hash.
st-n1s.1a,* F LH< :L puts (Z1&: #FHG< Va"u1: #F:G( G

The 1a,* method calls the given bloc for each ey in the hash, passing ey-value pair as parameter.
st-n1s.1a,*_H1& F LH1&L puts (#FH1&G( G

.e use the 1a,*_H1& method to loop throug all eys of a hash. They are printed to the console.
st-n1s.1a,*_:a"u1 F L:a"L puts (#F:a"G( G

"::

The 1a,*_:a"u1 can be used to loop throug the values of a hash.


st-n1s.1a,*_pair F LH< :L puts (Z1&: #FHG< Va"u1: #F:G( G

The 1a,*_pair method is a synonym for the 1a,* method. .e loop through the eys and values of the stones hash.
$ .%"--p.rb Z1&: 1< Va"u1: Z1&: 6< Va"u1: Z1&: 8< Va"u1: Z1&: J< Va"u1: 1 6 8 J 2arn1t t-pa? -pa" am1t*&st Z1&: 1< Va"u1: Z1&: 6< Va"u1: Z1&: 8< Va"u1: Z1&: J< Va"u1: 2arn1t t-pa? -pa" am1t*&st

2arn1t t-pa? -pa" am1t*&st

The output shows the eys and values, eys, values of the stones hash.

eleting pairs
In the following e%amples, we will concern ourselves with methods that delete pairs from the hashes. This includes methods that delete individual pairs as well as methods that can delete multiple ey-values at one step.
#$%usr%bin%rub& nam1s ! Aas*.n1+ nam1sI1K nam1sI6K nam1sI8K nam1sIJK nam1sI9K ! ! ! ! ! (3an1( ()*-mas( (R-b1rt( (3u"ia( (R1b1,,a(

nam1s..1"1t1 J nam1s.s*i't puts nam1s

In the script we have two methods5 .1"1t1 and s*i't. The .1"1t1 method removes and returns a value for a specified ey. The s*i't method deletes the first pair from the hash. It also returns the removed pair as an array.
nam1s..1"1t1 J

=ere we delete a pair @ 9^ FJuliaF.

":@

nam1s.s*i't

This code line removes the first pair, namely " 9^ FJaneF.
$ .%.1"1t1it1m.rb F6!>()*-mas(< 8!>(R-b1rt(< 9!>(R1b1,,a(G

In the output we can see the pairs of the hash that are left.

The r1D1,t and the .1"1t1_i' methods can remove multiple pairs from a hash. The methods delete pairs that return true for the given condition in the bloc . There is an important distinction between the two methods. The r1D1,t method wor s on a copy of a hash while the .1"1t1_i' wor s on the original hash.
#$%usr%"-,a"%bin%rub& nam1s1 ! Aas*.n1+ nam1s1I1K nam1s1I6K nam1s1I8K nam1s1IJK nam1s1I9K puts puts puts puts ! ! ! ! ! (3an1( ()*-mas( (R-b1rt( (3u"ia( (R1b1,,a(

nam1s1.r1D1,t F LH< :L : !P %R.Q% G nam1s1 nam1s1..1"1t1_i' F LH< :L HM!8 G nam1s1

The e%ample deletes multiple pairs using the previously mentioned methods.
puts nam1s1.r1D1,t F LH< :L : !P %R.Q% G

The r1D1,t method removes all values that fit the regular e%pression in the bloc . The modified hash is returned and the original hash is not changed.
puts nam1s1

The output of this line confirms that the original hash was intact.
puts nam1s1..1"1t1_i' F LH< :L HM!8 G

In this case, we delete all pairs, for which the ey is lower or e;ual to :. The method modifies the original hash.
$ .%mass.1"1t1.rb F1!>(3an1(< 6!>()*-mas(< J!>(3u"ia(G F1!>(3an1(< 6!>()*-mas(< 8!>(R-b1rt(< J!>(3u"ia(< 9!>(R1b1,,a(G FJ!>(3u"ia(< 9!>(R1b1,,a(G FJ!>(3u"ia(< 9!>(R1b1,,a(G

2utput of the e%ample.

":$

A##ing hashes
RubyEs merge and update methods add A ey, valueB pairs to hashes. Ruby has methods for hash addition.
#$%usr%bin%rub& nam1s1 ! Aas*.n1+ nam1s1I1K ! (3an1( nam1s1I6K ! ()*-mas( nam1s6 ! Aas*.n1+ nam1s6I8K ! (R-b1rt( nam1s6IJK ! (3u"ia( nam1s ! nam1s1.m1r21 nam1s6 puts nam1s nam1s ! nam1s1.up.at1 nam1s6 puts nam1s

In the Ruby script, we create two hashes. Then we apply m1r21 and up.at1 methods on them.
nam1s ! nam1s1.m1r21 nam1s6 puts nam1s

The names" and names7 hashes are combined. The result is assigned to the names hash. .e print the newly created hash.
$ .%m1r21.rb F1!>(3an1(< 6!>()*-mas(< 8!>(R-b1rt(< J!>(3u"ia(G F1!>(3an1(< 6!>()*-mas(< 8!>(R-b1rt(< J!>(3u"ia(G

8s we can see, the final hashes contain pairs from the names" and names7 hashes.

-he merge vs merge4


In the final section, we recap a common Ruby idiom. )everal Ruby methods have counterparts that end with an e%clamation point. This mar , which has no syntactic significance, indicates that a method modifies the object on which that method is called.
#$%usr%bin%rub& nam1s1 ! Aas*.n1+ nam1s1I1K ! (3an1( nam1s1I6K ! ()*-mas( nam1s6 ! Aas*.n1+ nam1s6I8K ! (R-b1rt( nam1s6IJK ! (3u"ia(

":G

nam1s ! nam1s1.m1r21 nam1s6 puts nam1s puts nam1s1 nam1s ! nam1s1.m1r21$ nam1s6 puts nam1s puts nam1s1

.e will demonstrate the difference on the m1r21 and m1r21$ methods.


nam1s ! nam1s1.m1r21 nam1s6

The m1r21 does not modify the names" hash. It wor s on its copy.
nam1s ! nam1s1.m1r21$ nam1s6

The m1r21$ method wor s on the original hash. The names" hash is changed.
$ .%m1r216.rb F1!>(3an1(< 6!>()*-mas(< 8!>(R-b1rt(< J!>(3u"ia(G F1!>(3an1(< 6!>()*-mas(G F1!>(3an1(< 6!>()*-mas(< 8!>(R-b1rt(< J!>(3u"ia(G F1!>(3an1(< 6!>()*-mas(< 8!>(R-b1rt(< J!>(3u"ia(G

This is the output of the merge7.rb program. In this chapter, we wor ed with Ruby hashes.

"b#ect-oriented programming in Ruby


In this part of the Ruby tutorial, we will tal about object-oriented programming in Ruby. (rogramming languages have procedural programming, functional programming and objectoriented programming paradigms. Ruby is an object-oriented language with some functional and procedural features. Object-oriented programming (OOP) is a programming paradigm that uses objects and their interactions to design applications and computer programs. The basic programming concepts in 22( are5

8bstraction (olymorphism *ncapsulation Inheritance

The abstraction is simplifying comple% reality by modeling classes appropriate to the problem. The polymorphism is the process of using an operator or function in different ways for different data input. The encapsulation hides the implementation details of a class from other objects. The inheritance is a way to form new classes using classes that have already been defined.

":H

Ob+ects
2bjects are basic building bloc s of a Ruby 22( program. 8n object is a combination of data and methods. In a 22( program, we create objects. These objects communicate together through methods. *ach object can receive messages, send messages and process data. There are two steps in creating an object. <irst, we define a class. 8 class is a template for an object. It is a blueprint that describes the state and behavior that the objects of the class all share. 8 class can be used to create many objects. 2bjects created at runtime from a class are called instances of that particular class.
#$%usr%bin%rub& ,"ass B1in2 1n. b ! B1in2.n1+ puts b

In our first e%ample, we create a simple object.


,"ass B1in2 1n.

This is a simple class definition. The body of the template is empty. It does not have any data or methods.
b ! B1in2.n1+

.e create a new instance of the /eing class. <or this we have the n1+ method. The b variable stores the newly created object.
puts b

.e print the object to the console to get some basic description of the object. .hen we print an object, we in fact call its t-_s method. /ut we have not defined any method yet. It is because every object created inherits from the base ObD1,t. It has some elementary functionality, which is shared among all objects created. 2ne of this is the t-_s method.
$ .%simp"1.rb #MB1in2:00@'8,6@0>

.e get the object class name.

-he constructor
8 constructor is a special ind of a method. It is automatically called when an object is created. +onstructors do not return values. The purpose of the constructor is to initiate the state of an object. The constructor in Ruby is called initia"i?1. +onstructors do not return any values.

":>

+onstructors cannot be inherited. The constructor of a parent object is called with a sup1r method. They are called in the order of inheritance.
#$%usr%bin%rub& ,"ass B1in2 .1' initia"i?1 puts (B1in2 is ,r1at1.( 1n. 1n. B1in2.n1+

.e have a /eing class.


,"ass B1in2 .1' initia"i?1 puts (B1in2 is ,r1at1.( 1n. 1n.

The /eing class has a constructor method called initia"i?1. It prints a message to the console. The definition of a Ruby method is placed between the .1' and 1n. eywords.
B1in2.n1+

8n instance of the /eing class is created. 8t the moment of the object creation, the constructor method is called.
$ .%,-nstru,t-r.rb B1in2 is ,r1at1.

This is the output of the program.

8n objectEs attributes are the data items that are bundled inside that object. These items are also called instance variables or member fields. 8n instance variable is a variable defined in a class, for which each object in the class has a separate copy. In the ne%t e%ample, we initiate data members of the class. Initiation of variables is a typical job for constructors.
#$%usr%bin%rub& ,"ass N1rs-n .1' initia"i?1 nam1 Onam1 ! nam1 1n. .1' 21t_nam1

":#

1n. 1n.

Onam1

p1 ! N1rs-n.n1+ (3an1( p6 ! N1rs-n.n1+ (B1H&( puts p1.21t_nam1 puts p6.21t_nam1

In the above Ruby code, we have a (erson class with one member field.
,"ass N1rs-n .1' initia"i?1 nam1 Onam1 ! nam1 1n.

In the constructor of the (erson class, we set a member field to a value name. The name parameter is passed to the constructor at creation. 8 constructor is a method called initia"i?1 that is being called at the creation of an instance object. The Onam1 is an instance variable. Instance variables start with D character in Ruby.
.1' 21t_nam1 Onam1 1n.

The get0name method returns the member field. In Ruby member fields are accessible only via methods.
p1 ! N1rs-n.n1+ (3an1( p6 ! N1rs-n.n1+ (B1H&(

.e create two objects of a (erson class. 8 string parameter is passed to each object constructor. The names are stored inside instance variables that are uni;ue to each object.
puts p1.21t_nam1 puts p6.21t_nam1

.e print the member fields by calling the get0name on each of the objects.
$ .%p1rs-n.rb 3an1 B1H&

.e see the output of the program. *ach instance of the (erson class has its own name member field.

.e can create an object without calling the constructor. Ruby has a special a""-,at1 method for this. The a""-,at1 method allocates space for a new object of a class and does not call initialiIe on the new instance.

"@-

#$%usr%bin%rub& ,"ass B1in2 .1' initia"i?1 puts (B1in2 ,r1at1.( 1n.

1n.

b1 ! B1in2.n1+ b6 ! B1in2.a""-,at1 puts b6

In the e%ample, we create two objects. The first object using the n1+ method, the second object using the a""-,at1 method.
b1 ! B1in2.n1+

=ere we create an instance of the object with the n1+ eyword. The constructor method initia"i?1 is called and the message is printed to the console.
b6 ! B1in2.a""-,at1 puts b6

In case of the a""-,at1 method, the constructor is not called. .e call the t-_s method with the puts eyword to show, that the object was created.
$ .%a""-,at1.rb B1in2 ,r1at1. #MB1in2:0081a00JJ>

=ere we see the output of the program.

Constructor overloa#ing
+onstructor overloading is the ability to have multiple types of constructors in a class. This way we can create an object with different number or different types of parameters. Ruby has no constructor overloading that we now from some programming languages. This behaviour can be simulated to some e%tent with default parameter values in Ruby.
#$%usr%bin%rub& ,"ass N1rs-n .1' initia"i?1 nam1!(unHn-+n(< a21!0 Onam1 ! nam1 Oa21 ! a21 1n. .1' t-_s (Nam1: #FOnam1G< 721: #FOa21G( 1n.

"@"

1n. p1 p6 p8 pJ ! ! ! ! N1rs-n.n1+ N1rs-n.n1+ (unHn-+n(< 1 N1rs-n.n1+ (B1,H&(< 1@ N1rs-n.n1+ (R-b1rt(

p p1< p6< p8< pJ

This e%ample shows how we could simulate constructor overloading on a (erson class that has two member fields. .hen the name parameter is not specified, the string Fun nownF is used instead. <or unspecified age we have -.
.1' initia"i?1 nam1!(unHn-+n(< a21!0 Onam1 ! nam1 Oa21 ! a21 1n.

The constructor ta es two parameters. They have a default value. The default value is used, if we do not specify our own values at the object creation. 3ote that the order of parameters must be ept. <irst comes the name, then the age.
p1 p6 p8 pJ ! ! ! ! N1rs-n.n1+ N1rs-n.n1+ (unHn-+n(< 1 N1rs-n.n1+ (B1,H&(< 1@ N1rs-n.n1+ (R-b1rt(

p p1< p6< p8< pJ

.e create four objects. The constructors ta e different number of parameters.


$ .%,-ns-:1r.rb Nam1: unHn-+n< 721: 0 Nam1: unHn-+n< 721: 1 Nam1: B1,H&< 721: 1@ Nam1: R-b1rt< 721: 0

This is the output of the e%ample.

1etho#s
!ethods are functions defined inside the body of a class. They are used to perform operations with the attributes of our objects. !ethods are essential in the encapsulation concept of the 22( paradigm. <or e%ample, we might have a connect method in our 8ccessLatabase class. .e need not to be informed how e%actly the method connects to the database. .e only have to now that it is used to connect to a database. This is essential in dividing responsibilities in programming, especially in large applications. In Ruby, data is accessible only via methods.
#$%usr%bin%rub& ,"ass N1rs-n

"@7

.1' initia"i?1 nam1 Onam1 ! nam1 1n. .1' 21t_nam1 Onam1 1n. 1n. p1r ! N1rs-n.n1+ (3an1( puts p1r.21t_nam1 puts p1r.s1n. :21t_nam1

The e%ample shows two basic ways to call a method.


puts p1r.21t_nam1

The common way is to use a dot operator on an object followed by a method name.
puts p1r.s1n. :21t_nam1

The alternative is to use a built-in s1n. method. It ta es a symbol of the method to be called as a parameter.

!ethods typically perform some action on an objectEs data.


#$%usr%bin%rub& ,"ass 5ir,"1 OONI ! 8.1J19@6 .1' initia"i?1 Ora.ius ! 0 1n. .1' s1t_ra.ius ra.ius Ora.ius ! ra.ius 1n. .1' ar1a Ora.ius Q Ora.ius Q OONI 1n. 1n. , ! 5ir,"1.n1+ ,.s1t_ra.ius 9 puts ,.ar1a

In the code e%ample, we have a +ircle class. .e define two methods.


OONI ! 8.1J19@6

"@:

.e have defined a DD(I variable in our +ircle class. It is a class variable. +lass variables start with DD sigils in Ruby. +lass variables belong to a class, not to an object. *ach object has access to its class variables. .e use the DD(I to compute the area of the circle.
.1' initia"i?1 Ora.ius ! 0 1n.

.e have one member field. It is the radius of the circle. If we want to modify this variable from the outside, we must use the publicly available s1t_ra.ius method. The data is protected.
.1' s1t_ra.ius ra.ius Ora.ius ! ra.ius 1n.

This is the s1t_ra.ius method. It gives the Dradius instance variable a new value.
.1' ar1a Ora.ius Q Ora.ius Q OONI 1n.

The area method returns the area of a circle. This is a typical tas for a method. It wor s with data and produces some value for us.
, ! 5ir,"1.n1+ ,.s1t_ra.ius 9 puts ,.ar1a

.e create an instance of the +ircle class, and set its radius by calling the s1t_ra.ius method on the object of the circle. .e use the dot operator to call the method.
$ .%,ir,"1.rb 8.98@8

Running the e%ample we get this output.

Access mo#i*iers
8ccess modifiers set the visibility of methods and member fields. Ruby has three access modifiers5 pub"i,, pr-t1,t1. and pri:at1. In Ruby, all data members are private. 8ccess modifiers can be used only on methods. Ruby methods are public, unless we say otherwise. The pub"i, methods can be accessed from inside the definition of the class as well as from the outside of the class. The difference between the pr-t1,t1. and the pri:at1 methods is subtle. 3either can be accessed outside the definition of the class. They can be accessed only within the class itself and by inherited or parent classes. 3ote that unli e in other object-oriented programming languages, inheritance does not play role in Ruby access modifiers. 2nly two things are important. <irst, if we call the method inside or outside the class definition. )econd, if we use or do not use the s1"' eyword which points to the current receiver. "@@

8ccess modifiers protect data against accidental modifications. They ma e the programs more robust. The implementation of some methods is subject to change. These methods are good candidates for being private. The interface that is made public to the users should only change when really necessary. 2ver the years users are accustomed to using specific methods and brea ing bac ward compatibility is generally frowned upon.
#$%usr%bin%rub& ,"ass S-m1 .1' m1t*-.1 puts (pub"i, m1t*-.1 ,a""1.( 1n. pub"i, .1' m1t*-.6 puts (pub"i, m1t*-.6 ,a""1.( 1n. .1' m1t*-.8 puts (pub"i, m1t*-.8 ,a""1.( m1t*-.1 s1"'.m1t*-.1 1n.

1n.

s ! S-m1.n1+ s.m1t*-.1 s.m1t*-.6 s.m1t*-.8

The e%ample e%plains the usage of public Ruby methods.


.1' m1t*-.1 puts (pub"i, m1t*-.1 ,a""1.( 1n.

The method" is public, even if we did not specify the pub"i, access modifier. It is because methods are public by default, if not specified otherwise.
pub"i, .1' m1t*-.6 puts (pub"i, m1t*-.6 ,a""1.( 1n. ...

!ethods following the pub"i, eyword are public.


.1' m1t*-.8 puts (pub"i, m1t*-.8 ,a""1.( m1t*-.1 s1"'.m1t*-.1 1n.

"@$

<rom inside the public method:, we call other public method, with and without the s1"' eyword.
s ! S-m1.n1+ s.m1t*-.1 s.m1t*-.6 s.m1t*-.8

(ublic methods are the only methods that can be called outside the definition of a class as shown here.
$ .%pub"i,_m1t*-.s.rb pub"i, m1t*-.1 ,a""1. pub"i, m1t*-.6 ,a""1. pub"i, m1t*-.8 ,a""1. pub"i, m1t*-.1 ,a""1. pub"i, m1t*-.1 ,a""1.

Running the e%ample we have this output.

The ne%t e%ample loo s at private methods.


#$%usr%bin%rub& ,"ass S-m1 .1' initia"i?1 m1t*-.1 # s1"'.m1t*-.1 1n. pri:at1 .1' m1t*-.1 puts (pri:at1 m1t*-.1 ,a""1.( 1n. 1n. s ! S-m1.n1+ # s.m1t*-.1

(rivate methods are tightest methods in Ruby. They can be called only inside a class definition and without the s1"' eyword.
.1' initia"i?1 m1t*-.1 # s1"'.m1t*-.1 1n.

In the constructor of the method, we call the private method". +alling the method with the self is commented. (rivate methods cannot be specified with a receiver.

"@G

pri:at1 .1' m1t*-.1 puts (pri:at1 m1t*-.1 ,a""1.( 1n.

!ethods following the pri:at1 eyword are private in Ruby.


s ! S-m1.n1+ # s.m1t*-.1

.e create an instance of the )ome class. +alling the method outside the class definition is prohibited. If we uncomment the line, the Ruby interpreter gives an error.
$ .%pri:at1_m1t*-.s.rb pri:at1 m1t*-. ,a""1.

2utput of the e%ample code.

<inally, we will wor with protected methods. The distinction between protected and private methods in Ruby is subtle. (rotected methods are li e private. There is only one small difference. They can be called with the s1"' eyword specified.
#$%usr%bin%rub& ,"ass S-m1 .1' initia"i?1 m1t*-.1 s1"'.m1t*-.1 1n. pr-t1,t1. .1' m1t*-.1 puts (pr-t1,t1. m1t*-.1 ,a""1.( 1n. 1n. s ! S-m1.n1+ # s.m1t*-.1

The above e%ample shows protected method in usage.


.1' initia"i?1 m1t*-.1 s1"'.m1t*-.1 1n.

(rotected methods can be called with and without the self eyword.
pr-t1,t1.

"@H

.1' m1t*-.1 puts (pr-t1,t1. m1t*-.1 ,a""1.( 1n.

(rotected methods are preceded by the pr-t1,t1. eyword.


s ! S-m1.n1+ # s.m1t*-.1

(rotected methods cannot be called outside the class definition. &ncommenting the line would lead to an error.

Inheritance
Inheritance is a way to form new classes using classes that have already been defined. The newly formed classes are called derived classes, the classes that we derive from are called base classes. Important benefits of inheritance are code reuse and reduction of comple%ity of a program. The derived classes AdescendantsB override or e%tend the functionality of base classes AancestorsB.
#$%usr%bin%rub& ,"ass B1in2 .1' initia"i?1 puts (B1in2 ,"ass ,r1at1.( 1n. 1n. ,"ass Auman M B1in2 .1' initia"i?1 sup1r puts (Auman ,"ass ,r1at1.( 1n. 1n. B1in2.n1+ Auman.n1+

In this program, we have two classes5 a base /eing class and a derived =uman class. The derived class inherits from the base class.
,"ass Auman M B1in2

In Ruby, we use the [ operator to create inheritance relations. The =uman class inherits from the /eing class.
.1' initia"i?1 sup1r puts (Auman ,"ass ,r1at1.( 1n.

The sup1r method calls the constructor of the parent class.

"@>

B1in2.n1+ Auman.n1+

.e instantiate the /eing and the =uman class.


$ .%in*1ritan,1.rb B1in2 ,"ass ,r1at1. B1in2 ,"ass ,r1at1. Auman ,"ass ,r1at1.

<irst the /eing class is created. The derived =uman class also calls the costructor of its parent.

8n 2bject may be involved in comlicated relationships. 8 single object can have multiple ancestors. Ruby has a method an,1st-rs which gives a list of ancestors for a specific class. *ach Ruby object is automatically a descendant of 2bject, /asic2bject classes and Mernel !odule. They are built-in the core of the Ruby language.
#$%usr%bin%rub& ,"ass B1in2 1n. ,"ass Yi:in2 M B1in2 1n. ,"ass \amma" M Yi:in2 1n. ,"ass Auman M \amma" 1n. p Auman.an,1st-rs

.e have four classes in this e%ample. 8 =uman is a !ammal a 'iving and a /eing.
p Auman.an,1st-rs

.e print the ancestors of a =uman class.


$ .%an,1st-rs.rb IAuman< \amma"< Yi:in2< B1in2< ObD1,t< Z1rn1"< Basi,ObD1,tK

8 =uman class has three custom and three built-in ancestors.

8 more comple% e%ample follows.


#$%usr%bin%rub& ,"ass B1in2

"@#

OO,-unt ! 0 .1' initia"i?1 OO,-unt /! 1 puts (B1in2 ,"ass ,r1at1.( 1n. .1' s*-+_,-unt ()*1r1 ar1 #FOO,-untG b1in2s( 1n. 1n. ,"ass Auman M B1in2 .1' initia"i?1 sup1r puts (Auman is ,r1at1.( 1n. 1n. ,"ass 7nima" M B1in2 .1' initia"i?1 sup1r puts (7nima" is ,r1at1.( 1n. 1n. ,"ass E-2 M 7nima" .1' initia"i?1 sup1r puts (E-2 is ,r1at1.( 1n. 1n. Auman.n1+ . ! E-2.n1+ puts ..s*-+_,-unt

.e have four classes. The inheritance hierarchy is more complicated. The =uman and the 8nimal classes inherit from the /eing class. 8nd the Log class inherits directly from the 8nimal class and further from the /eing class. .e also use a class variable to count the number of beings created.
OO,-unt ! 0

.e define a class variable. 8 class variable begins with DD sigils and it belongs to the class, not to the instance of the class. .e use it to count the number of beins created.
.1' initia"i?1 OO,-unt /! 1 puts (B1in2 ,"ass ,r1at1.( 1n.

"$-

*ach time the /eing class is instantiated, we increase the DDcount variable by one. This way we eep trac of the number of instances created.
,"ass 7nima" M B1in2 ... ,"ass E-2 M 7nima" ...

The 8nimal inherits from the /eing and the Log inherits from the 8nimal. <urther, the Log inherits from the /eing as well.
Auman.n1+ . ! E-2.n1+ puts ..s*-+_,-unt

.e create instances from the =uman and from the Log classes. .e call the show0count method on the Log object. The Log class has no such methodN the grandparentEs A/eingB method is called then.
$ .%in*1ritan,16.rb B1in2 ,"ass ,r1at1. Auman is ,r1at1. B1in2 ,"ass ,r1at1. 7nima" is ,r1at1. E-2 is ,r1at1. )*1r1 ar1 6 b1in2s

The =uman object calls two constructors. The Log object calls three constructors. There are two /eings instantiated.

Inheritance does not play role in the visibility of methods and data members. This is a notable difference from many common object-oriented programming languages. In +, or Java, public and protected data members and methods are inheritedN private data members and methods are not. In contrast to this, private data members and methods are inherited in Ruby as well. The visibility of data members and methods is not affected by inheritance in Ruby.
#$%usr%bin%rub& ,"ass Bas1 .1' initia"i?1 Onam1 ! (Bas1( 1n. pri:at1 .1' pri:at1_m1t*-. puts (pri:at1 m1t*-. ,a""1.( 1n. pr-t1,t1.

"$"

.1' pr-t1,t1._m1t*-. puts (pr-t1,t1._m1t*-. ,a""1.( 1n. pub"i, .1' 21t_nam1 r1turn Onam1 1n. 1n. ,"ass E1ri:1. M Bas1 .1' pub"i,_m1t*-. pri:at1_m1t*-. pr-t1,t1._m1t*-. 1n.

1n.

. ! E1ri:1..n1+ ..pub"i,_m1t*-. puts ..21t_nam1

In the e%ample we have two classes. The Lerived class inherits from the /ase class. It inherits all three methods and one data field.
.1' pub"i,_m1t*-. pri:at1_m1t*-. pr-t1,t1._m1t*-. 1n.

In the public0method of the Lerived class we call one private and one protected method. They were defined in the parent class.
. ! E1ri:1..n1+ ..pub"i,_m1t*-. puts ..21t_nam1

.e create an instance of the Lerived class. .e call public0method, as well as also get0name, which returns the private Dname variable. Remember that all instance variables are private in Ruby. The get0name method returns the variable, regardless of DnameEs being private and defined in the parent class.
$ .%in*1ritan,18.rb pri:at1 m1t*-. ,a""1. pr-t1,t1._m1t*-. ,a""1. Bas1

The output of the e%ample confirms that in Ruby language, public, protected, private methods and private member fields are inherited by child objects from their parents.

"$7

-he super metho#


The sup1r method calls a method of the same name in the parentEs class. If the method has no arguments it automatically passes all its arguments. If we write sup1r() no arguments are passed to parentEs method.
#$%usr%bin%rub& ,"ass Bas1 .1' s*-+ 0!0< &!0 p (Bas1 ,"ass< 0: #F0G< &: #F&G( 1n.

1n.

,"ass E1ri:1. M Bas1 .1' s*-+ 0< & sup1r sup1r 0 sup1r 0< & sup1r() 1n.

1n.

. ! E1ri:1..n1+ ..s*-+ 8< 8

In the e%ample, we have two classes in a hierarchy. They both have a show method. The show method in the Lerived class calls the show method in the /ase class using the sup1r method.
.1' s*-+ 0< & sup1r sup1r 0 sup1r 0< & sup1r() 1n.

The sup1r method without any arguments calls the parentEs show method with the arguments that were passed to the show method of the Lerived class5 here, %9: and y9:. The sup1r() method passes no arguments to the parentEs show method.
$ .%sup1r.rb (Bas1 ,"ass< (Bas1 ,"ass< (Bas1 ,"ass< (Bas1 ,"ass< 0: 0: 0: 0: 8< 8< 8< 0< &: &: &: &: 8( 0( 8( 0(

This is the output of the e%ample. This was the first part of the description of 22( in Ruby.

"$:

"b#ect-oriented programming !! in Ruby


In this part of the Ruby tutorial, we will continue tal ing about object-oriented programming in Ruby. .e start with attribute accessors. .e will cover class constants, class methods and operator overloading. .e will define polymorphism and will show how it is used in Ruby. .e will also mention modules and e%ceptions.

Attribute accessors
8ll Ruby variables are private. It is possible to access them only via methods. These methods are often called setters and getters. +reating a setter and a getter method is a very common tas . Therefore Ruby has convenient methods to create both types of methods. They are attr_r1a.1r, attr_+rit1r and attr_a,,1ss-r. The attr_r1a.1r creates getter methods. The attr_+rit1r method creates setter methods and instance variables for this setters. The attr_a,,1ss-r method creates both getter, setter methods and their instance variables.
#$%usr%bin%rub& ,"ass 5ar attr_r1a.1r :nam1< :pri,1 attr_+rit1r :nam1< :pri,1 .1' t-_s (#FOnam1G: #FOpri,1G( 1n. 1n. ,1 ! 5ar.n1+ ,6 ! 5ar.n1+ ,1.nam1 ! (N-rs,*1( ,1.pri,1 ! 68900 ,6.nam1 ! (V-"Hs+a21n( ,6.pri,1 ! @900 puts ()*1 #F,1.nam1G ,-sts #F,1.pri,1G( p ,1 p ,6

.e have a +ar class. In the definition of the class, we use the attr_r1a.1r and attr_+rit1r to create two getter and setter methods for the +ar class.
attr_r1a.1r :nam1< :pri,1

"$@

=ere we create two instance methods named name and price. 3ote that the attr_r1a.1r ta es symbols of methods as parameters.
attr_+rit1r :nam1< :pri,1

The attr_+rit1r creates two setter methods named name and price and two instance variables, Dname and Dprice.
,1.nam1 ! (N-rs,*1( ,1.pri,1 ! 68900

In this conte%t, two setter methods are called to fill instance variables with some data.
puts ()*1 #F,1.nam1G ,-sts #F,1.pri,1G(

=ere two getter methods are called to get data from the instance variables of the c" object.
$ .%ar+.rb )*1 N-rs,*1 ,-sts 68900 N-rs,*1: 68900 V-"Hs+a21n: @900

This is the output of the e%ample.

8s we already stated above, the attr_a,,1ss-r method creates getter, setter methods and their instance variables.
#$%usr%bin%rub& ,"ass B--H attr_a,,1ss-r :tit"1< :pa21s 1n. b1 ! B--H.n1+ b1.tit"1 ! (Ai..1n m-ti:1s( b1.pa21s ! 699 p ()*1 b--H #Fb1.tit"1G *as #Fb1.pa21sG pa21s(

.e have a /oo class in which the attr_a,,1ss-r creates two pairs of methods and two instance variables.
,"ass B--H attr_a,,1ss-r :tit"1< :pa21s 1n.

The attr_a,,1ss-r method that sets up title and pages methods and Dtitle and Dpages instance variables.
b1 ! B--H.n1+ b1.tit"1 ! (Ai..1n m-ti:1s( b1.pa21s ! 699

"$$

8n object of a /oo class is created. Two setter methods fill the instance variables of the object.
p ()*1 b--H #Fb1.tit"1G *as #Fb1.pa21sG pa21s(

In this code line we use two getter methods to read the values of the instance variables.
$ .%a,,1ss-r.rb ()*1 b--H Ai..1n m-ti:1s *as 699 pa21s(

This is e%ample output.

Class constants
Ruby enables you to create class constants. These constants do not belong to a concrete object. They belong to the class. /y convention, constants are written in uppercase letters.
#$%usr%bin%rub& ,"ass \\at* NI ! 8.1J19@6 1n. puts \\at*::NI

.e have a !!ath class with a (I constant.


NI ! 8.1J19@6

.e create a (I constant. Remember that constants in Ruby are not enforced.


puts \\at*::NI

.e access the (I constant using the 55 operator.


$ .%,"ass,-nstant.rb 8.1J19@6

Running the e%ample we see this output.

-he to5s metho#


*ach object has a t-_s method. It returns a string representation of the object. 3ote that when the puts method ta es an object as a parameter, the t-_s of the object is being called.
#$%usr%bin%rub& ,"ass B1in2 .1' t-_s ()*is is B1in2 ,"ass( 1n.

"$G

1n. b ! B1in2.n1+ puts b.t-_s puts b

.e have a /eing class in which we override the default implementation of the t-_s method.
.1' t-_s ()*is is B1in2 ,"ass( 1n.

*ach class created inherits from the base ObD1,t. The t-_s method belongs to this class. .e overwrite the to0s method and create a new implementation. .e provide a human-readable description of our object.
b ! B1in2.n1+ puts b.t-_s puts b

.e create a /eing class and call the t-_s method twice. The first time e%plicitly, the second time implicitly.
$ .%t-strin2.rb )*is is B1in2 ,"ass )*is is B1in2 ,"ass

This is what we get when we run the e%ample.

Operator overloa#ing
2perator overloading is a situation where different operators have different implementations depending on their arguments. In Ruby there is only a slight distinction between an operator and a method.
#$%usr%bin%rub& ,"ass 5ir,"1 attr_a,,1ss-r :ra.ius .1' initia"i?1 r Ora.ius ! r 1n. .1' /(-t*1r) 5ir,"1.n1+ Ora.ius / -t*1r.ra.ius 1n. .1' t-_s (5ir,"1 +it* ra.ius: #FOra.iusG( 1n.

1n.

"$H

,1 ! 5ir,"1.n1+ 9 ,6 ! 5ir,"1.n1+ > ,8 ! ,1 / ,6 p ,8

In the e%ample, we have a +ircle class. .e overload the ? operator in the class. .e use it to add two circle objects.
.1' /(-t*1r) 5ir,"1.n1+ Ora.ius / -t*1r.ra.ius 1n.

.e define a method with a ? name. The method adds the radiuses of two circle objects.
,1 ! 5ir,"1.n1+ 9 ,6 ! 5ir,"1.n1+ > ,8 ! ,1 / ,6

.e create two circle objects. In the third line, we add these two objects to create a new one.
$ .%-p1rat-r-:1r"-a.in2.rb 5ir,"1 +it* ra.ius: 11

8dding these two circle objects creates a third with a radius of "".

Class metho#s
Ruby methods can be divided into class methods and instance methods. lass methods are called on a class. They cannot be called on an instance of a class. +lass methods cannot access instance variables.
#$%usr%bin%rub& ,"ass 5ir,"1 .1' initia"i?1 0 Or ! 0 1n. .1' s1"'.in'()*is is a 5ir,"1 ,"ass( 1n. .1' ar1a Or Q Or Q 8.1J19@6 1n. 1n. p 5ir,"1.in', ! 5ir,"1.n1+ 8 p ,.ar1a

"$>

The above code e%ample presents a +ircle class. 8part from a constructor method, it has one class and one instance method.
.1' s1"'.in'()*is is a 5ir,"1 ,"ass( 1n.

!ethods that start with a s1"' eyword are class methods.


.1' ar1a (5ir,"1< ra.ius: #FOrG( 1n.

Instance methods do not start with the self eyword.


p 5ir,"1.in'-

.e call a class method. 3ote that we call the method on a class name.
, ! 5ir,"1.n1+ 8 p ,.ar1a

To call an instance method, we must first create an object. Instance methods are always called on an object. In our case, the c variable holds the object and we call the area method on the circle object. .e utiliIe a dot operator.
$ .%,"assm1t*-.s.rb ()*is is a 5ir,"1 ,"ass( 68.6 J868

2utput of the code e%ample describing class methods in Ruby.

There are three ways to create a class method in Ruby.


#$%usr%bin%rub& ,"ass W--. .1' s1"'.in'()*is is a W--. ,"ass( 1n. 1n. ,"ass Bri,H ,"ass MM s1"' .1' in'()*is is a Bri,H ,"ass( 1n. 1n.

1n.

,"ass R-,H 1n.

"$#

.1' R-,H.in'()*is is a R-,H ,"ass( 1n. p W--..in'p Bri,H.in'p R-,H.in'-

The e%ample has three classes. *ach of them has one class method.
.1' s1"'.in'()*is is a W--. ,"ass( 1n.

+lass methods may start with a s1"' eyword.


,"ass MM s1"' .1' in'()*is is a Bri,H ,"ass( 1n. 1n.

8nother way is to put a method definition after the class [[ self construct.
.1' R-,H.in'()*is is a R-,H ,"ass( 1n.

This is the third way to define a class method in Ruby.


$ .%,"assm1t*-.s6.rb ()*is is a W--. ,"ass( ()*is is a Bri,H ,"ass( ()*is is a R-,H ,"ass(

.e see the output of calling all three class methods on a .ood, /ric and Roc classes.

-hree "ays to create an instance metho#


Ruby has three basic ways to create instance methods. Instance methods belong to an instance of an object. They are called on an object using a dot operator.
#$%usr%bin%rub& ,"ass W--. .1' in'()*is is a +--. -bD1,t( 1n.

1n.

+--. ! W--..n1+ p +--..in'-

"G-

,"ass Bri,H 1n. attr_a,,1ss-r :in'-

bri,H ! Bri,H.n1+ bri,H.in'- ! ()*is is a bri,H -bD1,t( p bri,H.in',"ass R-,H 1n. r-,H ! R-,H.n1+ .1' r-,H.in'()*is is a r-,H -bD1,t( 1n. p r-,H.in'-

In the e%ample we create three instance objects from a .ood, a /ric and a Roc class. *ach object has one instance method defined.
,"ass W--. .1' in'()*is is a +--. -bD1,t( 1n.

1n.

+--. ! W--..n1+ p +--..in'-

This is probably the most common way to define and call an instance method. The info method is defined inside the .ood class. 'ater, the object is created and we call the info method on the object instance.
,"ass Bri,H attr_a,,1ss-r :in'1n. bri,H ! Bri,H.n1+ bri,H.in'- ! ()*is is a bri,H -bD1,t( p bri,H.in'-

8nother way is to create a method using the attribute accessors. This is a convenient way which saves some typing for the programmer. The attr_a,,1ss-r creates two methods, the getter and the setter method It also creates an instance variable which stores the data. The bric object is created and the data is stored in the Dinfo variable using the info setter method. <inally, the message is read by the info getter method.
,"ass R-,H 1n.

"G"

r-,H ! R-,H.n1+ .1' r-,H.in'()*is is a r-,H -bD1,t( 1n. p r-,H.in'-

In the third way we create an empty Roc class. The object is instantiated. 'ater, a method is dynamically created and placed into the object.
$ .%t*r11+a&s.rb ()*is is a +--. -bD1,t( ()*is is a bri,H -bD1,t( ()*is is a r-,H -bD1,t(

*%ample output.

Polymorphism
Polymorphism is the process of using an operator or function in different ways for different data input. In practical terms, polymorphism means that if class / inherits from class 8, it doesnEt have to inherit everything about class 8N it can do some of the things that class 8 does differently. A.i ipediaB In general, polymorphism is the ability to appear in different forms. Technically, it is the ability to redefine methods for derived classes. (olymorphism is concerned with the application of specific implementations to an interface or a more generic base class. 3ote that there is some difference in the definition of the polymorphism in statically typed languages li e +??, Java or +, and dynamically typed languages li e (ython or Ruby. In statically typed languages it is important when the compilers determine the method definition, at compile time or at run time. In dynamically typed languages we concentrate on the fact that methods with the same name do different things.
#$%usr%bin%rub& ,"ass 7nima" .1' maH1_n-is1 (S-m1 n-is1( 1n. .1' s"11p puts (#Fs1"'.,"ass.nam1G is s"11pin2.( 1n. 1n. ,"ass E-2 M 7nima" .1' maH1_n-is1 CW--'$C 1n.

"G7

1n. ,"ass 5at M 7nima" .1' maH1_n-is1 C\1-+$C 1n.

1n.

I7nima".n1+< E-2.n1+< 5at.n1+K.1a,* .- Lanima"L puts anima".maH1_n-is1 anima".s"11p 1n.

.e have a simple inheritance hierarchy. There is an 8nimal base class and two descendants, a +at and a Log. *ach of these three classes has its own implementation of the ma e0noise method. The implementation of the method of the descendants replaces the definition of a method in the 8nimal class.
,"ass E-2 M 7nima" .1' maH1_n-is1 CW--'$C 1n. 1n.

The implementation of the ma e0noise method in the Log class replaces the implementation of the ma e0noise of the 8nimal class.
I7nima".n1+< E-2.n1+< 5at.n1+K.1a,* .- Lanima"L puts anima".maH1_n-is1 anima".s"11p 1n.

.e create an instance of each class. .e call ma e0noise and sleep methods on the objects.
$ .%p-"&m-r*ism.rb S-m1 n-is1 7nima" is s"11pin2. W--'$ E-2 is s"11pin2. \1-+$ 5at is s"11pin2.

This is the output of the polymorhism.rb script.

1o#ules
8 Ruby \-.u"1 is a collection of methods, classes and constants. !odules are similar to classes with a few differences. !odules cannot have instances and cannot subclasses. !odules are used to group related classes, methods and constants can be put into separate modules. This also prevents name clashes, because modules encapsulate the objects they contain. In this regard, Ruby modules are similar to +, namespaces and Java pac ages.

"G:

!odules also support the use of mi%ins in Ruby. 8 mixin is a Ruby facility to create multiple inheritance. If a class inherits functionality from more than one class, we spea of multiple inheritance.
#$%usr%bin%rub& puts \at*::NI puts \at*.sin 6

Ruby has a built-in \at* module. It has multiple methods and a constant. .e access the (I constant by using the 55 operator. !ethods are accessed by a dot operator as in classes.
#$%usr%bin%rub& in,"u.1 \at* puts NI puts sin 6

If we include a module in our script, we can refer to the !ath objects directly, omitting the !ath name. !odules are added to a script using the in,"u.1 eyword.
$ .%m-.u"1s.rb 8.1J19@6>9898@ @8 0.@0@6@ J6>869>81

2utput of the program.

In the following e%ample, we show how modules can be used to organiIe code.
#$%usr%bin%rub& m-.u"1 ]-r1st ,"ass R-,H V 1n. ,"ass )r11 V 1n. ,"ass 7nima" V 1n. 1n. m-.u"1 )-+n ,"ass ,"ass ,"ass ,"ass 1n. p ]-r1st::)r11.n1+ p ]-r1st::R-,H.n1+ p )-+n::5in1ma.n1+ p ]-r1st::7nima".n1+ p )-+n::7nima".n1+ N--" V 5in1ma SBuar1 7nima" 1n. V 1n. V 1n. V 1n.

"G@

Ruby code can be grouped semantically. Roc s and trees belong to a forest. (ools, cinemas, s;uares belong to a town. /y using modules our code has some order. 8nimals can be in a forest and in a town too. In a single script, we cannot define two animal classes. They would clash. (utting them in different modules we solve the issue.
p ]-r1st::)r11.n1+ p ]-r1st::R-,H.n1+ p )-+n::5in1ma.n1+

.e are creating objects that belong to a forest and to a town. To access an object in a module, we use the 55 operator.
p ]-r1st::7nima".n1+ p )-+n::7nima".n1+

Two different animal objects are created. The Ruby interpreter can tell between them. It identifies them by their module name.
$ .%m-.u"1s8.rb #M]-r1st::)r11:00@ '891,> #M]-r1st::R-,H:00@ '89b0> #M)-+n::5in1ma:00@ '8988> #M]-r1st::7nima":00@ '89>0> #M)-+n::7nima":00@ '8988>

This is the output of the modules:.rb program.

The final code e%ample of this section will demonstrate multiple inheritance using Ruby modules. In this conte%t the modules are called mi%ins.
#$%usr%bin%rub& m-.u"1 E1:i,1 .1' s+it,*_-n V puts (-n( 1n. .1' s+it,*_-'' V puts (-''( 1n. 1n. m-.u"1 V-"um1 .1' :-"um1_up V puts (:-"um1 up( 1n. .1' :-.u"1_.-+n V puts (:-"um1 .-+n( 1n. 1n. m-.u"1 N"u22ab"1 .1' p"u2_in V puts (p"u2 in( 1n. .1' p"u2_-ut V puts (p"u2 -ut( 1n. 1n. ,"ass 51""N*-n1 in,"u.1 E1:i,1< V-"um1< N"u22ab"1 .1' rin2 puts (rin2in2( 1n.

1n.

"G$

,p* ! 51""N*-n1.n1+ ,p*.s+it,*_-n ,p*.:-"um1_up ,p*.rin2

.e have three modules and one class. The modules represent some functionality. 8 device can be swiched on and off. !any objects can share this functionality, including televisions, mobile phones, computers or refrigerators. Rather than creating this ability to be swiched on6off for each object class, we separate it in one module, which can be included in each object if necessary. This way the code is better organiIed and more compact.
m-.u"1 V-"um1 .1' :-"um1_up V puts (:-"um1 up( 1n. .1' :-.u"1_.-+n V puts (:-"um1 .-+n( 1n. 1n.

8 1olume module organiIes methods that are responsible for controlling the volume level. If a device needs these methods, it simply includes the module to its class.
,"ass 51""N*-n1 in,"u.1 E1:i,1< V-"um1< N"u22ab"1 .1' rin2 puts (rin2in2( 1n. 1n.

8 cell phone adds all three modules with the in,"u.1 method. The methods of the modules are mi%ed in the +ell(hone class. 8nd are available for the instances of the class. The +ell(hone class has also its own ring method that is specific to it.
,p* ! 51""N*-n1.n1+ ,p*.s+it,*_-n ,p*.:-"um1_up ,p*.rin2

8 +ell(hone object is created and we call three methods upon the object.
$ .%mi0ins.rb -n :-"um1 up rin2in2

Running the e%ample gives this output.

'.ceptions
*%ceptions are objects that signal deviations from the normal flow of program e%ecution. *%ceptions are raised, thrown or initiated. Luring the e%ecution of our application, many things might go wrong. 8 dis might get full and we cannot save our file. 8n Internet connection might go down and our application tries to connect to a site. 8ll these might result in a crash of our application. To prevent this from

"GG

happening, we should anticipate and respond to errors in e%pected program operation. <or this, we can use the e%ception handling. *%ceptions are objects. They are descendants of a built-in E0,1pti-n class. *%ception objects carry information about the e%ception. Its type Athe e%ceptionXs class nameB, an optional descriptive string, and optional tracebac information. (rograms may subclass E0,1pti-n, or more often Stan.ar.Err-r, to obtain custom *%ception objects that provide additional information about operational anomalies.
#$%usr%bin%rub& 0 ! 89 & ! 0 b12in ? ! 0 % & puts ? r1s,u1 !> 1 puts 1 p 1 1n.

In the above program, we intentionally divide a number by Iero. This leads to an error.
b12in ? ! 0 % & puts ?

)tatements that can fail are placed after the b12in eyword.
r1s,u1 !> 1 puts 1 p 1 1n.

In the code following the r1s,u1 eyword, we deal with an e%ception. In this case, we print the error message to the console. The e is an e%ception object that is created when the error occurs.
$ .%?1r-.i:isi-n.rb .i:i.1. b& 0 #M41r-Ei:isi-nErr-r: .i:i.1. b& 0>

In the output of the e%ample, we see the message of the e%ception. The last line shows the e%ception object called ZeroLivision*rror.

8 programmer may raise e%ceptions himself using the rais1 eyword.


#$%usr%bin%rub& a21 ! 1 b12in i' a21 M 18

"GH

1n.

rais1 (N1rs-n is a min-r(

puts (Entr& a""-+1.( r1s,u1 !> 1 puts 1 p 1 10it 1 1n.

The entrance to a club is not allowed for people younger than "> years. .e simulate this situation in our Ruby script.
b12in i' a21 M 18 rais1 (N1rs-n is a min-r( 1n. puts (Entr& a""-+1.(

If the person is a minor, an e%ception is raised. If the rais1 eyword does not have a specific e%ception as a parameter, a Runtime*rror e%ception is raised setting its message to the given string. The code does not reach the puts (Entr& a""-+1.( line. The e%ecution of the code is interrupted and it continues at the rescue bloc .
r1s,u1 !> 1 puts 1 p 1 10it 1 1n.

In the rescue bloc , we print the error message and the string representation of the Runtim1Err-r object. .e also call the 10it method to inform the environment that the e%ecution of the script ended in error.
$ .%rais1_10,1pti-n.rb N1rs-n is a min-r #MRuntim1Err-r: N1rs-n is a min-r> $ 1,*- $U 1

The person, a minor, was not allowed to enter the club. The bash CQ variable is set to the e%it error of the script.

RubyEs 1nsur1 clause creates a bloc of code that always e%ecutes, whether there is an e%ception or not.
#$%usr%bin%rub& b12in ' ! ]i"1.-p1n((st-n1s(< (r() +*i"1 "in1 ! '.21ts .puts "in1 1n.

"G>

r1s,u1 !> 1 puts 1 p 1 1nsur1 '.,"-s1 i' ' 1n.

In the code e%ample, we try to open and read the stones file. I62 operations are error prone. .e could easily have an e%ception.
1nsur1 '.,"-s1 i' ' 1n.

In the ensure bloc we close the file handler. .e chec if the handler e%ists because it might not have been created. 8llocated resources are often placed in the ensure bloc .

.e can create our own custom e%ceptions if we want. +ustom e%ceptions in Ruby should inherit from the Stan.ar.Err-r class.
#$%usr%bin%rub& ,"ass Bi2Va"u1Err-r M Stan.ar.Err-r V 1n. YI\I) ! 888 0 ! 8_J86_J98 b12in i' 0 > YI\I) rais1 Bi2Va"u1Err-r< (E0,11.1. t*1 ma0imum :a"u1( 1n. puts (S,ript ,-ntinu1s( r1s,u1 !> 1 puts 1 p 1 10it 1 1n.

'etEs say we have a situation in which we cannot deal with big numbers.
,"ass Bi2Va"u1Err-r M Stan.ar.Err-r V 1n.

.e have a /ig1alue*rror class. This class derives from the built-in Stan.ar.Err-r class.
YI\I) ! 888

3umbers which e%ceed this constant are considered to be FbigF by our program.
i' 0 > YI\I) rais1 Bi2Va"u1Err-r< (E0,11.1. t*1 ma0imum :a"u1( 1n.

"G#

If the value is bigger than the limit, we throw our custom e%ception. .e give the e%ception a message F*%ceeded the ma%imum valueF.
$ .%,ust-m_10,1pti-n.rb E0,11.1. t*1 ma0imum :a"u1 #MBi2Va"u1Err-r: E0,11.1. t*1 ma0imum :a"u1>

Running the program. In this chapter we finished tal ing about object-oriented programming in Ruby language.

Regular expressions in Ruby


In this part of the Ruby tutorial, we will tal about Regular e%pressions in Ruby. Regular e%pressions are used for te%t searching and more advanced te%t manipulation. Regular e%pressions are built into tools li e grep, sedN te%t editors li e vi, emacsN programming languages li e Tcl, (erl, (ython. Ruby has a built-in support for regular e%pressions too. <rom another point of view, regular e%pression synta% constitutes a domain specific language for matching te%t. 8 pattern is a regular e%pression that defines the te%t we are searching for or manipulating. It consists of te%t literals and metacharacters. The pattern is placed inside two delimiters. In Ruby these are 66 characters. They inform the rege% function where the pattern starts and ends. =ere is a partial list of metacharacters5 . P ST Sa T a C ` !atches any single character. !atches the preceding element Iero or more times. /rac et e%pression. !atches a character within the brac ets. !atches a single character, that is not contained within the brac ets. !atches the starting position within the string. !atches the ending position within the string. 8lternation operator.

The 9U operator matches the regular e%pression against a string, and it returns either the offset of the match from the string if it is found, otherwise nil. The R1210p class is used to develop regular e%pressions. There are also two shorthand ways to create regular e%pressions. The following e%ample will show them.
#$%usr%bin%rub& r1 ! R1210p.n1+ C3an1C p (3an1 is *-t(.mat,* r1 p (3an1 is *-t( !P %3an1% p (3an1 is *-t(.mat,* RrF3an1G

"H-

In the first e%ample, we show three ways of applying regular e%pressions on a string.
r1 ! R1210p.n1+ C3an1C p (3an1 is *-t(.mat,* r1

In the above two lines, we create a R1210p object cointaining a simple regular e%pression te%t. &sing the mat,* method, we apply this regular e%pression object on the FJane is hotF sentence. .e chec , if the word EJaneE is inside the sentence.
p (3an1 is *-t( !P %3an1% p (3an1 is *-t(.mat,* RrF3an1G

These two lines do the same. Two forward slashes 66 and the RrJK characters are shorthands for the more verbose first way. In this tutorial, we will use the forward slashes. This is a de facto standard in many languages.
$ .%r1210.rb #M\at,*Eata (3an1(> 0 #M\at,*Eata (3an1(>

In all three cases there is a match. The mat,* method returns a matched data, or ni" if there is no match. The 9U operator returns the first character of the matched te%t, or ni" otherwise.

-he #ot character


The dot character is a regular e%pression character, which matches any single character. 3ote that there must be some characterN it may not be omitted.
#$%usr%bin%rub& p p p p (S1:1n(.mat,* %.1:1n% (1:1n(.mat,* %.1:1n% (1"1:1n(.mat,* %.1:1n% (pr-:1n(.mat,* %.1:1n%

In the first e%ample, we will use the mat,* method to apply regular e%pression on strings. The mat,* method returns the matched data on success or ni" otherwise.
p (S1:1n(.mat,* %.1:1n%

The F)evenF is the string on which we call the mat,* method. The parameter of the method is the pattern. The 6.even6 regular pattern loo s for a te%t that starts with an arbitrary character followed by the EevenE characters.
$ .%.-t.rb #M\at,*Eata (S1:1n(> ni" #M\at,*Eata ("1:1n(> ni"

<rom the output we can see which strings did match and which did not.

"H"

8s we have said above, if there is a dot character, there must be an arbitrary character. It may not be omitted. .hat if we wanted to search for a te%t, in which the character might be omittedQ In other words, we want a pattern for both EsevenE and EevenE. <or this, we can use a Q repetition character. The Q repetition character tells that the previous character may be present - or " time.
#$%usr%bin%rub& p (s1:1n(.mat,* %.1:1n% p (1:1n(.mat,* %.1:1n% p (1:1n(.mat,* %.U1:1n%

The script uses the Q repetition character.


p (1:1n(.mat,* %.1:1n%

This line prints ni" since the regular e%pression e%pects one character before the EevenE string.
p (1:1n(.mat,* %.U1:1n%

=ere we have slightly modified the regular e%pression. The E.QE stands for no character or one arbitrary character. This time there is a match.
$ .%.-t6.rb #M\at,*Eata (s1:1n(> ni" #M\at,*Eata (1:1n(>

This is the e%ample output.

Regular e.pression metho#s


In the previous two e%amples, we have used the mat,* method to wor with regular e%pressions. 2ther methods besides match accept regular e%pressions as parameters.
#$%usr%bin%rub& puts (m-t*1rb-ar.( !P %b-ar.% puts (16< @11< 16< 111(I%X.F8G%K puts (m-t*1rb-ar.(.2sub %b-ar.%< ("an.( p (m11t bi2 .11p ni" n11.(.s,an %.I1KI1K.% p ()*is is Sparta$(.sp"it(%Xs%)

The e%ample shows some methods that can wor with regular e%pressions.
puts (m-t*1rb-ar.( !P %b-ar.%

The 9U is an operator that applies the regular e%pression on the right to the string on the left.
puts (16< @11< 16< 111(I%X.F8G%K

"H7

Regular e%pressions can be placed between the s;uare brac ets following the string. This line prints the first string which has three digits.
puts (m-t*1rb-ar.(.2sub %b-ar.%< ("an.(

.ith the 2sub method we replace a EboardE string with a ElandE string.
p (m11t bi2 .11p ni" n11.(.s,an %.I1KI1K.%

The s,an method loo s for matches in the string. It loo s for all occurences, not just the first one. The line prints all strings that match the pattern.
p ()*is is Sparta$(.sp"it(%Xs%)

The sp"it method splits a string using a given regular e%pression as a separator. The ]s character type stands for any whitespace character.
$ .%app"&.rb > @11 m-t*1r"an. I(m11t(< (.11p(< (n11.(K I()*is(< (is(< (Sparta$(K

.e see the output of the apply.rb script.

Special variables
)ome of the methods that wor with regular e%pressions activate a few special variables. They contain the last matched string, the string before the last match and string after the last match. These variables ma e the job easier for a programmer.
#$%usr%bin%rub& puts (A1r nam1 is 3an1( !P %nam1% p $[ p $S p $C

The e%ample shows three special variables.


puts (A1r nam1 is 3an1( !P %nam1%

In this line we have a simple regular e%pression matching. .e loo for a EnameE string inside the E=er name is JaneE sentence. .e use the 9U operator. This operator also sets three special variables. The line returns number @, which is the position on which the match starts.
p $[

The CW special variable contains the te%t before the last match.
p $S

"H:

The CV has the matched te%t.


p $C

8nd the CE variable contains the te%t after the last match.
$ .%s:ars.rb J (A1r ( (nam1( ( is 3an1(

This is the output of the e%ample.

Anchors
8nchors match positions of characters inside a given te%t. .e present three anchoring characters. The a character matches the beginning of the line. The C character matches the end of the line. The ]b character matches word boundaries.
#$%usr%bin%rub& s1n1 ! (E:1r&+*1r1 I "--H I s11 3an1( s1n6 ! (3an1 is t*1 b1st t*in2 t*at *app1n1. t- m1( p s1n1.mat,* %T3an1% p s1n6.mat,* %T3an1% p s1n1.mat,* %3an1$% p s1n6.mat,* %3an1$%

In the first e%ample, we wor with the a and the C anchoring characters.
s1n1 ! (E:1r&+*1r1 I "--H I s11 3an1( s1n6 ! (3an1 is t*1 b1st t*in2 t*at *app1n1. t- m1(

.e have two sentences. The word EJaneE is located at the beginning of the first one and at the end of the second one.
p s1n1.mat,* %T3an1% p s1n6.mat,* %T3an1%

=ere we loo if the word EJaneE is at the beginning of the two sentences.
p s1n1.mat,* %3an1$% p s1n6.mat,* %3an1$%

=ere we loo for a match of a te%t at the end of the sentences.


$ .%an,*-rs.rb ni" #M\at,*Eata (3an1(> #M\at,*Eata (3an1(> ni"

"H@

These are the results.

8 common re;uest is to include only a match of a whole word. /y default we count any match, including a match in larger or compound words. 'et us loo at an e%ample to clarify things.
#$%usr%bin%rub& t10t ! ()*1 ,at a"s- Hn-+n as t*1 .-m1sti, ,at is a sma""< usua""& 'urr&< .-m1sti,at1.< ,arni:-r-us mamma".( p t10t.s,an %,at% p $[ p $S p $C

.e have a sentence. 8nd within this sentence, we loo for a string cat. &sing s,an, we loo for all EcatE strings in the sentenceYnot just the first occurence.
t10t ! ()*1 ,at a"s- Hn-+n as t*1 .-m1sti, ,at is a sma""< usua""& 'urr&< .-m1sti,at1.< ,arni:-r-us mamma".(

The problem is that inside the te%t there are three EcatE strings. In addition to matching the EcatE that refers to the mammal, 6cat6 matches letters >-"- inside the word EdomesticatedE. .hich is not what we are loo ing for in this case.
$ .%b-u.ari1s.rb I(,at(< (,at(< (,at(K ()*1 ,at a"s- Hn-+n as t*1 .-m1sti, ,at is a sma""< Xnusua""& 'urr&< .-m1sti( (,at( (1.< ,arni:-r-us mamma".(

This last match on EdomesticatedE will be eliminated in the ne%t e%ample, using the ]b anchor.

The Xb character is used to set boundaries to the words we are loo ing for.
#$%usr%bin%rub& t10t ! ()*1 ,at a"s- Hn-+n as t*1 .-m1sti, ,at is a sma""< usua""& 'urr&< .-m1sti,at1.< ,arni:-r-us mamma".( p t10t.s,an %Xb,atXb% p $[ p $S p $C

The e%ample is improved by including the ]b metacharacter.


p t10t.s,an %Xb,atXb%

"H$

.ith the above regular e%pression, we loo for EcatE strings as whole words. .e do not count subwords.
$ .%b-u.ari1s6.rb I(,at(< (,at(K ()*1 ,at a"s- Hn-+n as t*1 .-m1sti, ( (,at( ( is a sma""< Xnusua""& 'urr&< .-m1sti,at1.< ,arni:-r-us mamma".(

This time there are two matches. 8nd the special variables show correctly the te%t before and after the last match.

Character classes
.e can combine characters into character classes with the s;uare brac ets. 8 character class matches any character that is specified in the brac ets. The 6SabT6 pattern means a or b, as opposed to 6ab6 which means a followed by b.
#$%usr%bin%rub& +-r.s ! R+% sit \I) 'it 'at "-t pa. % patt1rn ! %I'sKit% +-r.s.1a,* .- L+-r.L i' +-r..mat,* patt1rn puts (#F+-r.G mat,*1s t*1 patt1rn( 1"s1 puts (#F+-r.G .-1s n-t mat,* t*1 patt1rn( 1n. 1n.

.e have an array of si% three letter words. .e apply a regular e%pression on the strings of the array with a specific character set.
patt1rn ! %I'sKit%

This is the pattern. The pattern loo s for EfitE and EsitE strings in the array. .e use either EfE or EsE from the character set.
$ .%,"ass1s.rb sit mat,*1s t*1 patt1rn \I) .-1s n-t mat,* t*1 patt1rn 'it mat,*1s t*1 patt1rn 'at .-1s n-t mat,* t*1 patt1rn "-t .-1s n-t mat,* t*1 patt1rn pa. .-1s n-t mat,* t*1 patt1rn

There are two matches.

In the ne%t e%ample we will further e%plore the character classes.


#$%usr%bin%rub&

"HG

p (,ar(.mat,* RrFIab,KIaKIrsKG p (,ar(.mat,* %Ia;rK/% p (68a' J88a J2a(.s,an %XbIa;'0;@K/Xb%

The e%ample has three regular e%pressions with character classes.


p (,ar(.mat,* RrFIab,KIaKIrsKG

The regular e%pression in this line consists of three character classes. *ach is for one character. The SabcT is either a, b or c. The SaT is only a. The third one, SrsT, is either r or s. There is a match with the EcarE string.
p (,ar(.mat,* %Ia;rK/%

.e can use a hyphen Y character inside the character class. The hyphen is a metacharacter denoting an inclusive range of characters5 here, a, b, c, d, e, f, g, h, i, j, , l, m, n, o, p, ;, or r. )ince the character class applies only for one character, we also use the ? repetition character. This says that the previous character from the character set may be repeated one or more times. The EcarE strings meets these conditions.
p (68a' J88a J2a(.s,an %XbIa;'0;@K/Xb%

In this line, we have a string consisting of three substrings. .ith the s,an method we chec for he%adicimal numbers. .e have two ranges. The first, Sa-fT stands for characters from a to f. The second one, S--#T stands for numbers - to #. The ? specifies that these characters can be repeated multiple times. <inally, the ]b metacharacters create boundaries, which accept only strings that consists of only these characters.
$ .%,"ass1s6.rb #M\at,*Eata (,ar(> #M\at,*Eata (,ar(> I(68a'(< (J88a(K

This is the e%ample output.

If the first character of a character class is a caret AaB the class is inverted. It matches any character e%cept those which are specified.
#$%usr%bin%rub& p (7B5(.mat,* %ITa;?KF8G% p (ab,(.mat,* %ITa;?KF8G%

In the e%ample, we use a caret character inside a character class.


p (7B5(.mat,* %ITa;?KF8G%

.e loo for a string having : letters. These letters may not be letters from a to I. The F8/+F string matches the regular e%pression because all three characters are uppercase characters.
p (ab,(.mat,* %ITa;?KF8G%

"HH

This FabcF string does not match. 8ll three characters are in the range, that is e%cluded from the search.
$ .%,ar1t.rb #M\at,*Eata (7B5(> ni"

=ere we have the e%ample output.

6uanti*iers
8 ;uantifier after a to en or group specifies how often that preceding element is allowed to occur.
U Q / FnG Fn<G F<nG Fn<mG ; ; ; ; ; ; ; 0 -r 1 mat,* 0 -r m-r1 1 -r m-r1 10a,t"& n n -r m-r1 n -r "1ss (UU) ran21 n t- m

The above is a list of common ;uantifiers.


#$%usr%bin%rub& p (s1:1n .i2 m--n ,ar "-t 'ir1(.s,an %X+F8G% p (s1:1n .i2 m--n ,ar "-t 'ir1(.s,an %XbX+F8GXb%

In the e%ample, we want to select those words that have e%actly three characters. The ]w character is a word character, and ]wJ:K means three times the prevoius word character.
p (s1:1n .i2 m--n ,ar "-t 'ir1(.s,an %X+F8G%

The first line simply cuts first three characters from each string. This is not e%actly what we want.
p (s1:1n .i2 m--n ,ar "-t 'ir1(.s,an %XbX+F8GXb%

This is an improved search. .e put the previous pattern between the ]b boundary metacharacter. 3ow the search will find only those words that have e%actly three characters.
$ .%n,*ars.rb I(s1:(< (.i2(< (m--(< (,ar(< ("-t(< ('ir(K I(.i2(< (,ar(< ("-t(K

2utput of the e%ample.

The Jn,mK is a repetition structure for strings having from n to m characters.


#$%usr%bin%rub&

"H>

p (I .i2 m--n "-tt1r& it 'ir1(.s,an %XbX+F6<JGXb%

In the above e%ample we choose words that have two, three of four characters. .e again use the boundary ]b metacharacter to choose whole words.
$ .%r,*ars.rb I(.i2(< (m--n(< (it(< ('ir1(K

The e%ample prints an array of words having 7-@ characters.

In the ne%t e%ample, we will present the Q metacharacter. 8 character followed by a Q is optional. <ormally, the character preceding the Q may be present once or - times.
#$%usr%bin%rub& p (,-"-r ,-"-ur ,-"-rs ,-"-urs(.s,an %,-"-uUrs% p (,-"-r ,-"-ur ,-"-rs ,-"-urs(.s,an %,-"-uUrsU% p (,-"-r ,-"-ur ,-"-rs ,-"-urs(.s,an %Xb,-"-rXbLXb,-"-rsXbLXb,-"-urXbLXb,-"-ursXb%

)ay we have a te%t in which we want to loo for the colour word. The word has two distinct spellings, english EcolourE and american EcolorE. .e want to find both occurences, plus we want to find their plurals too.
p (,-"-r ,-"-ur ,-"-rs ,-"-urs(.s,an %,-"-uUrs%

The colouQrs pattern finds both EcoloursE and EcolorsE. The u character, which precedes the Q metacharacter is optional.
p (,-"-r ,-"-ur ,-"-rs ,-"-urs(.s,an %,-"-uUrsU%

The colouQrsQ pattern ma es the u and s characters optional. 8nd so we find all four colour combinations.
p (,-"-r ,-"-ur ,-"-rs ,-"-urs(.s,an %Xb,-"-rXbLXb,-"-rsXbLXb,-"-urXbLXb,-"-ursXb%

The same re;uest could be written using alternations.


$ .%BmarH.rb I(,-"-rs(< (,-"-urs(K I(,-"-r(< (,-"-ur(< (,-"-rs(< (,-"-urs(K I(,-"-r(< (,-"-ur(< (,-"-rs(< (,-"-urs(K

This is the e%ample output.

In the last e%ample of this section, we will show the ? metacharacter. It allows the preceding character to be repeated " or more times.
#$%usr%bin%rub&

"H#

nums ! R+% 68J 1 68 98J8J 68J986J98J>J 68J99>8> 86J' 8J986J968J8J96 8J8 686J 6J661 8J$8J686% nums.1a,* .- LnumL m ! num.mat,* %I0;@K/% i' m.t-_s.1B"U num puts num 1n. 1n.

In the e%ample, we have an array of numbers. 3umbers can have one or more number characters.
nums ! R+% 68J 1 68 98J8J 68J986J98J>J 68J99>8> 86J' 8J986J968J8J96 8J8 686J 6J661 8J$8J686%

This is an array of strings. Two of them are not numbers, because they contain non-numerical characters. They must be e%cluded.
nums.1a,* .- LnumL m ! num.mat,* %I0;@K/% i' m.t-_s.1B"U num puts num 1n.

1n.

.e go through the array and apply the regular e%pression on each string. The e%pression is S--#T?, which stands for any character from -..#, repeated - or multiple times. /y default, the regular e%pression loo s for substrings as well. In the :@C:@7:7 the engine considers :@ to be a number. The ]b boundaries do not wor here because we do not have concrete characters and the engine does not now, where to stop loo ing. This is why we have included an if condition in the bloc . The string is considered a number only if the match is e;ual to the original string.
$ .%numb1rs.rb 68J 1 68 98J8J 68J986J98J>J 68J99>8> 8J986J968J8J96 8J8 686J 6J661

These values are numbers.

">-

Case insensitive search


.e can perform a case insensitive search. 8 regular e%pression can be followed by an option. It is a single character that modifies the pattern in some way. In case of a case insensitive search, we apply the i option.
#$%usr%bin%rub& p (3an1(.mat,* %3an1% p (3an1(.mat,* %Dan1% p (3an1(.mat,* %37NE% p (3an1(.mat,* %Dan1%i p (3an1(.mat,* %3an1%i p (3an1(.mat,* %37NE%i

The e%ample show both case sensitive and case insensitive search.
p (3an1(.mat,* %3an1% p (3an1(.mat,* %Dan1% p (3an1(.mat,* %37NE%

In these three lines the characters must e%actly match the pattern. 2nly the first line gives a match.
p (3an1(.mat,* %Dan1%i p (3an1(.mat,* %3an1%i p (3an1(.mat,* %37NE%i

=ere we use the i option, which followes the second 6 character. .e do case insensitive search. 8ll three lines do match.
$ .%i,as1.rb #M\at,*Eata (3an1(> ni" ni" #M\at,*Eata (3an1(> #M\at,*Eata (3an1(> #M\at,*Eata (3an1(>

This is the output of the e%ample.

Alternation
The ne%t e%ample e%plains the alternation operator A`B. This operator enables to create a regular e%pression with several choices.
#$%usr%bin%rub& nam1s ! R+%3an1 )*-mas R-b1rt Yu,& B1H& 3-*n N1t1r 7n.&% patt1rn ! %3an1LB1H&LR-b1rt% nam1s.1a,* .- Lnam1L

">"

i' nam1 !P patt1rn puts (#Fnam1G is m& 'ri1n.( 1"s1 puts (#Fnam1G is n-t m& 'ri1n.( 1n. 1n.

.e have > names in the names array. .e will loo for a multiple combination of strings in that array.
patt1rn ! %3an1LB1H&LR-b1rt%

This is the search pattern. It says, Jane, /e y and Robert are my friends. If you find either of them, you have found my friend.
$ .%a"t1rnati-n.rb 3an1 is m& 'ri1n. )*-mas is n-t m& 'ri1n. R-b1rt is m& 'ri1n. Yu,& is n-t m& 'ri1n. B1H& is m& 'ri1n. 3-*n is n-t m& 'ri1n. N1t1r is n-t m& 'ri1n. 7n.& is n-t m& 'ri1n.

=ere we see the output of the script.

Subpatterns
.e can use parentheses AB to create subpatterns inside patterns.
#$%usr%bin%rub& p p p p (b--H+-rm( !P %b--H(+-rm)U$% (b--H( !P %b--H(+-rm)U$% (+-rm( !P %b--H(+-rm)U$% (b--Hst-r1( !P %b--H(+-rm)U$%

.e have the following rege% pattern5 boo AwormBQC. The AwormB is a subpattern. 2nly two strings can match5 either Eboo E or Eboo wormE. The Q character follows the subpattern, which means, that the subpattern might appear -, " time in the final pattern. The C character is here for the e%act end match of the string. .ithout it, words li e boo store and boo mania would match too.
#$%usr%bin%rub& p p p p (b--H( !P %b--H(s*1"'L+-rm)U$% (b--Hs*1"'( !P %b--H(s*1"'L+-rm)U$% (b--H+-rm( !P %b--H(s*1"'L+-rm)U$% (b--Hst-r1( !P %b--H(s*1"'L+-rm)U$%

)ubpatterns are often combined with alternation to create multiple word combinations. <or e%ample, boo Ashelf`wormB matches Eboo shelfE and Eboo wormE, and boo Ashelf`wormBQ matches Eboo shelfE, Eboo wormE, and Eboo E. ">7

$ .%subpatt1rns6.rb 0 0 0 ni"

The last subpattern does not match. Remember that the -s do not mean that there was no match. <or the 9U operator, it is the inde% of the first character of the matched string.

'mail e.ample
In the final e%ample, we create a rege% pattern for chec ing email addresses.
#$%usr%bin%rub& 1mai"s ! R+% "uH1O2mai".,-m an.&O&a*--.,-m 6861Js.DTas '8JJJO2mai".,-m % patt1rn ! %TIa;?7;40;@._;K/OIa;?7;40;@;K/X.Ia;?7;4.KF6<9G$% 1mai"s.1a,* .- L1mai"L i' 1mai".mat,* patt1rn puts (#F1mai"G mat,*1s( 1"s1 puts (#F1mai"G .-1s n-t mat,*( 1n. 1n.

3ote that this e%ample provides only one solution. It does not have to be the best one.
1mai"s ! R+% "uH1O2mai".,-m an.&O&a*--,-m 6861Js.DTas '8JJJO2mai".,-m %

This is an array of emails. 2nly two of them are valid.


patt1rn ! %TIa;?7;40;@._;K/OIa;?7;40;@;K/X.Ia;?7;4.KF6<9G$%

This is the pattern. The first a and the last C characters are here to get an e%act pattern match. 3o characters before and after the pattern are allowed. The email is divided into five parts. The first part is the local part. This is usually a name of a company, individual or a nic name. The Sa-I8-Z--#.0-T? lists all possible characters we can use in the local part. They can be used one or more times. The second part is the literal D character. The third part is the domain part. It is usually the domain name of the email provider5 e.g., yahoo or gmail. The character set Sa-I8-Z--#-T? specifies all characters that can be used in the domain name. The ? ;uantifier ma es use of one or more of these characters. The fourth part is the dot character. It is preceded by the escape character. A].B This is because the dot character is a metacharacter and has a special meaning. /y escaping it, we get a literal dot. The final part is the top level domain. The pattern is as follows5 Sa-I8-Z.TJ7,$K Top level domains can have from 7 to $ characters, li e s , net, info, travel. There is also a dot character. This is because some top level domains li e co.u have two parts.
$ .%1mai".rb

">:

"uH1O2mai".,-m mat,*1s an.&O&a*--,-m .-1s n-t mat,* 6861Js.DTas .-1s n-t mat,* '8JJJO2mai".,-m mat,*1s

The regular e%pression mar ed two strings as valid email adresses. In this chapter, we have covered regular e%pressions in Ruby.

!nput . output in Ruby


In this part of the Ruby tutorial, we will tal about input V output operations in Ruby. Input is any data that is read by the program, either from a eyboard, file or other programs. 2utput is data that is produced by the program. The output may go to the screen, to a file or to another program. Input V output is a large topic. .e bring forward some e%amples to give you a general idea of the subject. )everal classes in Ruby have methods for doing input V output operations. <or e%ample Z1rn1", IO, Eir or ]i"1.

Writing to console
Ruby has several methods for printing output on the console. These methods are part of the Z1rn1" module. !ethods of the Z1rn1" are available to all objects in Ruby.
#$%usr%bin%rub& print (7pp"1 ( print (7pp"1Xn( puts (Oran21( puts (Oran21(

The print and puts methods produce te%tual output on the console. The difference between the two is that the latter adds a new line character.
print (7pp"1 ( print (7pp"1Xn(

The print method prints two consecutive F8ppleF strings to the terminal. If we want to create a new line, we must e%plicitly include a newline character. The newline character is E]nE. /ehind the scenes, the print method actually calls the t-_s method of the object being printed.
puts (Oran21( puts (Oran21(

The puts method prints two strings to the console. *ach is on its own line. The method includes automatically the newline character.
$ .%printin2.rb 7pp"1 7pp"1

">@

Oran21 Oran21

This the output of the printing.rb script file. 8ccording to the Ruby documentation, the print method is an e;uivalent to the $st.-ut.print. The $st.-ut is a global variable which holds the standard output stream.
#$%usr%bin%rub& $st.-ut.print (Rub& "an2ua21Xn( $st.-ut.puts (N&t*-n "an2ua21(

.e print two lines using the $st.-ut variable. Ruby has another three methods for printing output.
#$%usr%bin%rub& p (Y1m-n( p (Y1m-n( print' ()*1r1 ar1 R. app"1sXn(< 8 put, CZC put, 007

In the e%ample, we present the p, print' and put, methods.


p (Y1m-n(

The p calls the insp1,t method upon the object being printed. The method is useful for debugging.
print' ()*1r1 ar1 R. app"1sXn(< 8

The print' method is well nown from the + programming language. It enables string formatting.
put, CZC put, 007

The put, method prints one character to the console. The second line prints a newline. The -%8 is a he%adecimal code for the newline character.
$ .%printin28.rb (Y1m-n( (Y1m-n( )*1r1 ar1 8 app"1s Z

This is the output of the printing:.rb program.

">$

(rinting data to the console using the ernel methods is a shortcut5 a convenient way to print data. The following e%ample shows a more formal way to print data to the terminal.
i-s ! IO.n1+ S)EOU).'i"1ni-s.+rit1 (41t5-.1Xn( i-s.,"-s1

In the e%ample, we open a standard output stream and write a string into it.
i-s ! IO.n1+ S)EOU).'i"1n-

The n1+ method returns a stream to which we can write data. The method ta es a numeric file descriptor. The S)EOU).'i"1n- gives us the file descriptor for the standard output stream. .e could also simply write 7.
i-s.+rit1 (41t5-.1Xn(

.e write a string to the opened stream.


i-s.,"-s1

The input stream is closed. 2n &ni% systems the standard terminal output is connected to a special file called 6dev6tty. /y opening it and writing to it, we write to a console.
#$%usr%bin%rub& '. ! IO.s&s-p1n (%.1:%tt&(< (+( i-s ! IO.n1+('.< (+() i-s.puts (41t5-.1( i-s.,"-s1

8 small e%ample in which we write to a 6dev6tty file. This only wor s on &ni%.
'. ! IO.s&s-p1n (%.1:%tt&(< (+(

The s&s-p1n method opens the given path, returning the underlying file descriptor number.
i-s ! IO.n1+('.< (+()

The file descriptor number is used to open a stream.


i-s.puts (41t5-.1( i-s.,"-s1

.e write a string to the stream and close it.

Rea#ing input *rom console


In this section, we will create some code e%amples that will deal with reading from the console.

">G

The $st.in is a global variable that holds a stream for the standard input. It can be used to read input from the console.
#$%usr%bin%rub& inp ! $st.in.r1a. puts inp

In the above code, we use the r1a. method to read input from the console.
inp ! $st.in.r1a.

The r1a. method reads data from the standard input until it reaches the end of the file. *2< is produced by pressing +trl ? L on &ni% or +trl ? Z on .indows.
$ .%r1a.in2.rb Rub& "an2ua21 Rub& "an2ua21

.hen we launch a program without a parameter, the script reads data from the user. It reads until we press +trl ? L or +trl ? Z.
$ 1,*- (41t5-.1( L .%r1a.in2.rb 41t5-.1 $ .%input.rb M st-n1s =arn1t )-pa? Opa" 7m1t*&st Rub& 3asp1r N&rit1 \a"a,*it1 _uart?

The script can read data from another program or a file, if we do some redirections. The common way to read data from the console is to use the 21ts method.
#$%usr%bin%rub& print (Ent1r &-ur nam1: ( nam1 ! 21ts puts (A1""- #Fnam1G(

.e use the 21ts method to read a line from the user.


nam1 ! 21ts

The 21ts method reads a line from the standard input. The data is assigned to the name variable.
puts (A1""- #Fnam1G(

">H

The data that we have read is printed to the console. .e use interpolation to include the variable in the string.
$ .%r1a."in1.rb Ent1r &-ur nam1: 3an A1""- 3an

)ample output. In the following two scripts, we will discuss the ,*-mp method. It is a string method which removes white spaces from the end of the string. It is useful when doing input operations. The method name and usage comes from the (erl language.
#$%usr%bin%rub& print (Ent1r a strin2: ( inp ! 21ts puts ()*1 strin2 *as #Finp.si?1G ,*ara,t1rs(

.e read a string from a user and calculate the length of the input string.
$ .%n-,*-mp.rb Ent1r a strin2: Rub& )*1 strin2 *as 9 ,*ara,t1rs

The message says that the string has $ characters. It is because it counts the newline as well. To get the correct answer, we need to remove the newline character. This is a job for the ,*-mp method.
#$%usr%bin%rub& print (Ent1r a strin2: ( inp ! 21ts.,*-mp puts ()*1 strin2 *as #Finp.si?1G ,*ara,t1rs(

This time we use we cut the newline character with the ,*-mp method.
$ .%,*-mp.rb Ent1r a strin2: Rub& )*1 strin2 *as J ,*ara,t1rs

The Ruby string has indeed @ characters.

,iles
<rom the official Ruby documentation we learn that the IO class is the basis for all input and output in Ruby. The ]i"1 class is the only subclass of the IO class. The two classes are closely related.
#$%usr%bin%rub&

">>

' ! ]i"1.-p1n(C-utput.t0tC< C+C) '.puts ()*1 Rub& tut-ria"( '.,"-s1

In the first e%ample, we open a file and write some data to it.
' ! ]i"1.-p1n(C-utput.t0tC< C+C)

.e open a file Eoutput.t%tE in write mode. The -p1n method returns an io stream.
'.puts ()*1 Rub& tut-ria"(

.e used the above opened stream to write some data. The puts method can be used to write data to a file as well.
'.,"-s1

8t the end the stream is closed.


$ .%simp"1+rit1.rb $ ,at -utput.t0t )*1 Rub& tut-ria"

.e e%ecute the script and show the contents of the output.t%t file. .e will have a similar e%ample which will show additional methods in action.
#$%usr%bin%rub& ]i"1.-p1n(C"an2sC< C+C) .- L'L '.puts (Rub&( '.+rit1 (3a:aXn( ' MM (N&t*-nXn( 1n.

If there is a bloc after the -p1n method then Ruby passes the opened stream to this bloc . 8t the end of the bloc , the file is automatically closed.
'.puts (Rub&( '.+rit1 (3a:aXn( ' MM (N&t*-nXn(

.e use three different methods to write to a file.


$ .%simp"1+rit16.rb $ ,at "an2s Rub& 3a:a N&t*-n

.e e%ecute the script and chec the contents of the langs file.

">#

In the second e%ample, we show a few methods of the ]i"1 class.


#$%usr%bin%rub& puts ]i"1.10istsU Ct1mp'i"1C ' ! ]i"1.n1+ Ct1mp'i"1C< C+C puts ]i"1.mtim1 Ct1mp'i"1C puts '.si?1 ]i"1.r1nam1 Ct1mp'i"1C< Ct1mp'i"16C '.,"-s1

The e%ample creates a new file named EtempfileE and calls some methods.
puts ]i"1.10istsU Ct1mp'i"1C

The 10istsU method chec s if a file with a given name already e%ists. The line returns false, because we have not yet created the file.
' ! ]i"1.n1+ Ct1mp'i"1C< C+C

The file is created.


puts ]i"1.mtim1 Ct1mp'i"1C

The mtim1 method gives us the last modification time of the file.
puts '.si?1

.e determine the file siIe. The method returns -, since we have not written to the file.
]i"1.r1nam1 Ct1mp'i"1C< Ct1mp'i"16C

<inally, we rename the file using the r1nam1 method.


$ .%t1st'i"1.rb 'a"s1 6011;11;09 1>:1@:8> /0100 0

This is a sample output. 3e%t, we will be reading data from the files on the dis .
#$%usr%bin%rub& ' ! ]i"1.-p1n((st-n1s() +*i"1 "in1 ! '.21ts .puts "in1 1n. '.,"-s1

"#-

This is a simple script that will open a file called stones and print it contents line by line to the terminal.
' ! ]i"1.-p1n((st-n1s()

.e open a EstonesE file. The default mode is a read mode. The EstonesE file contains nine names of valued stones, each on a separate line.
+*i"1 "in1 ! '.21ts .puts "in1 1n.

The 21ts method reads a line from the I62 stream. The while bloc ends when we reach the end of file.
$ .%r1a."in1s6.rb =arn1t )-pa? Opa" 7m1t*&st Rub& 3asp1r N&rit1 \a"a,*it1 _uart?

This is the output of the e%ample. The ne%t e%ample will read data from a file.
#$%usr%bin%rub& 'nam1 ! Ca"""in1s.rbC ]i"1.r1a."in1s('nam1).1a,* .- L"in1L puts "in1 1n.

This script shows another way of reading a fileEs contents. The code e%ample will print its own code to the terminal.
]i"1.r1a."in1s('nam1).1a,* .- L"in1L puts "in1 1n.

The r1a."in1s reads all lines from the specified file and returns them in the form of an array. .e go through the array with the 1a,* method and print the lines to the terminal.
$ .%a"""in1s.rb #$%usr%bin%rub& 'nam1 ! Ca"""in1s.rbC ]i"1.r1a."in1s('nam1).1a,* .- L"in1L puts "in1

"#"

1n.

2utput of the e%ample.

irectories
In this section, we wor with directories. .e have a Eir class to wor with directories in Ruby.
#$%usr%bin%rub& Eir.mH.ir (tmp( puts Eir.10istsU (tmp( puts Eir.p+. Eir.,*.ir (tmp( puts Eir.p+. Eir.,*.ir C..C puts Eir.p+. Eir.rm.ir (tmp( puts Eir.10istsU (tmp(

In the script we use four methods of the Eir class.


Eir.mH.ir (tmp(

The mH.ir method ma es a new directory called EtmpE.


puts Eir.10istsU (tmp(

.ith the 10istsU method, we chec if a directory with a given name e%ists in the filesystem.
puts Eir.p+.

The p+. method prints a current wor ing directory. This is the directory from which we launched the script.
Eir.,*.ir C..C

The ,*.ir method changes to another directory. The E..E directory is the parent directory of the current wor ing directory.
Eir.rm.ir (tmp( puts Eir.10istsU (tmp(

<inally, we remove a directory with the rm.ir method. This time the 10istsU method returns false.
$ .%.irs.rb tru1 %*-m1%:r-nsHiD%pr-2rammin2%rub&%i%*-m1%:r-nsHiD%pr-2rammin2%rub&%i-%tmp %*-m1%:r-nsHiD%pr-2rammin2%rub&%i-

"#7

'a"s1

This is the output of the e%ample. In the second e%ample, we retrieve all of a directoryEs entries, including its files and subdirectories.
#$%usr%bin%rub& '"s ! Eir.1ntri1s C.C puts '"s.insp1,t

The 1ntri1s method returns all entries of a given diretory.


'"s ! Eir.1ntri1s C.C puts '"s.insp1,t

.e get the array of files and directories of a current directory. The E.E character stands for the current wor ing directory in this conte%t. The insp1,t method gives us a more readable representation of the array.
$ .%a""'i"1s.rb I(put,.rb(< (simp"1+rit1.rb(< (r1a."in1s6.rb(< ('i"110ists.rbP( ...

In the output we can see an array of files and directories. The third e%ample wor s with a home directory. *very user in a computer has a uni;ue directory assigned to him. It is called a home directory. It is a place where he can place his files and create his own hierarchy of directories.
#$%usr%bin%rub& puts Eir.*-m1 puts Eir.*-m1 Cr--tC

The script prints two home directories.


puts Eir.*-m1

If we do not specify the user name, then a home directory of a current user is returned. The current user is the owner of the script file. )omeone, who has launched the script.
puts Eir.*-m1 Cr--tC

=ere we print the home directory of a specific user5 in our case, the superuser.
$ .%*-m1.ir.rb %*-m1%:r-nsHiD %r--t

This is a sample output.

"#:

'.ecuting e.ternal programs


Ruby has several ways to e%ecute e%ternal programs. .e will deal with some of them. In our e%amples we will use well nown 'inu% commands. Readers with .indows or !ac can use commands specific for their systems.
#$%usr%bin%rub& .ata ! s&st1m C"sC puts .ata

.e call a "s command which lists directory contents.


.ata ! s&st1m C"sC

The s&st1m command e%ecutes an e%ternal program in a subshell. The method belongs to the Z1rn1" Ruby module.
$ .%s&st1m.rb a""'i"1s.rb ,*ara,t1rs.rb 'i"110ists.rb *-m1.ir.rbP ...

This is a sample output. .e show two other ways of running e%ternal programs in Ruby.
#$%usr%bin%rub& -ut ! [p+.[ puts -ut -ut ! R0Iuptim1K puts -ut -ut ! R0I"s L 2r1p Cr1a."in1CK puts -ut

To run e%ternal programs we can use bac tic s WW or R%ST characters.


-ut ! [p+.[

=ere we e%ecute the p+. command using bac tic s. The command returns the current wor ing directory.
-ut ! R0Iuptim1K

=ere we get the output of the uptim1 command, which tells how long a system is running.
-ut ! R0I"s L 2r1p Cr1a."in1CK

.e can use also a combination of commands.


$ .%s&st1m6.rb %*-m1%:r-nsHiD%pr-2rammin2%rub&%i66:90:90 up 9:86< 1 us1r< "-a. a:1ra21: 0.J>< 0.JJ< 0.J9

"#@

r1a."in1.rb r1a."in1.rbP r1a."in1s6.rb r1a."in1s6.rbP

This is a sample output. .e can e%ecute a command with the -p1n method. The method belongs to the Z1rn1" module. It creates an I2 object connected to the given stream, file, or subprocess. If we want to connect to a subprocess, we start the path of the -p1n with a pipe character A`B.
#$%usr%bin%rub& ' ! -p1n((L"s ;" L*1a. ;8() -ut ! '.r1a. puts -ut '.,"-s1 puts $U.su,,1ssU

In the e%ample, we print the outcome of the "s ;" L *1a. ;8 commands. The combination of these two commands returns the first three lines of the "s ;" command. .e also chec the status of the child subprocess.
' ! -p1n((L"s ;" L*1a. ;8()

.e connect to a subprocess, created by these two commands.


-ut ! '.r1a. puts -ut

.e read and print data from the subprocess.


'.,"-s1

.e close the file handler.


puts $U.su,,1ssU

The CQ is a special Ruby variable that is set to the status of the last e%ecuted child process. The su,,1ssU method returns true if the child process ended 2M.
$ .%s&st1m8.rb t-ta" 1J8 ;r+0r;0r;0 1 :r-nsHiD :r-nsHiD ;r+0r;0r;0 1 :r-nsHiD :r-nsHiD tru1

9 6011;10;80 68:88 a""'i"1s.rb 98 6011;10;80 68:88 a""'i"1s.rbP

This is a sample output.

"#$

Re#irecting stan#ar# output


Ruby has predefined global variables for standard input, standard output and standard error output. The $st.-ut is the name of the variable for the standard output.
#$%usr%bin%rub& $st.-ut ! ]i"1.-p1n (-utput."-2(< (a( puts (Rub&( puts (3a:a( $st.-ut.,"-s1 $st.-ut ! S)EOU) puts (N&t*-n(

In the above e%ample, we redirect a standard output to the output.log file.


$st.-ut ! ]i"1.-p1n (-utput."-2(< (a(

This line creates a new standard ouput. The standard output will now flow to the ouput.log file. The file is opened in the append mode. If the file does not e%ist yet, it is created. 2therwise it is opened and the data is written at the end of the file.
puts (Rub&( puts (3a:a(

.e print two strings. The strings will not be shown in the terminal as usual. Rather, they will be appended to the output.log file.
$st.-ut.,"-s1

The handler is closed.


$st.-ut ! S)EOU) puts (N&t*-n(

.e use a predefined standard constant S)EOU) to recreate the normal standard ouput. The F(ythonF string is printed to the console. In this part of the Ruby tutorial, we wor ed with input and output operations in Ruby.

"#G

%/0ite Ruby tutorial


This is a Ruby programming tutorial for the )b'ite database. It covers the basics of )b'ite programming with Ruby. It uses the s;lite: module. The e%amples were created and tested on 'inu%.

S6%ite ( Ruby
%/0ite is an embedded relational database engine. It is a self-contained, serverless, Ieroconfiguration and transactional )b' database engine. )b'ite implements most of the )b'#7 standard for )b'. The )b'ite engine is not a standalone process. Instead, it is statically or dynamically lin ed into the application. 8n )b'ite database is a single ordinary dis file that can be located anywhere in the directory hierarchy. Ruby is a dynamic, reflective, general-purpose object-oriented programming language. Recently it became very popular in web programming, mainly due to the successful Ruby on Rails framewor .

Connecting to the %/0ite database


This part of the )b'ite Ruby tutorial will show you how to connect to a database and do a few simple things with the database.

Be*ore "e start


The )b'ite comes with the s;lite: command line utility. It can be used to issue )b' commands against a database. 3ow we are going to use the s;lite: command line tool to create a new database.
$ sB"it18 t1st..b S_Yit1 :1rsi-n 8.>.66 Ent1r (.*1"p( '-r instru,ti-ns Ent1r S_Y stat1m1nts t1rminat1. +it* a (V(

.e provide a parameter to the s;lite: tool. The test.db is a database name. It is a single file on our dis . If it is present, it is opened. If not, it is created.
sB"it1> .tab"1s sB"it1> .10it $ "s t1st..b

The .tab"1s command gives a list of tables in the test.db database. There are currently no tables. The .10it command terminates the interactive session of the s;lite: command line tool. The ls &ni% command shows the contents of the current wor ing directory. .e can see the test.db file. 8ll data will be stored in this single file.

"#H

The s!lite-ruby interface is used to interact with )b'ite database with the Ruby language.
$ su.- apt;21t insta"" "ibsB"it18;rub&

The above command installs the module on Lebian based 'inu% systems. The first step is to create a Latabase object. The Latabase class encapsulates a single connection to an )b'ite database. The database object is closed with the ,"-s1 method.
S_Yit18::Eatabas1.n1+ .bnam1 S_Yit18::Eatabas1.-p1n .bnam1

The n1+ method creates a new Latabase object that opens the given dbname file. If the file does not e%ist, it will be created if possible. /y default, the new database will return result rows as arrays. The -p1n method opens the database contained in the given file.
S_Yit18::Eatabas1.n1+ (:m1m-r&:(

It is possible to create an in-memory database if we provide a special string F5memory5F for the file name.

Sources
The s;lite-ruby.rubyforge.org website was consulted when creating this tutorial.

Version
In the first code e%ample, we will get the version of the )b'ite database.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.n1+ (:m1m-r&:( puts .b.21t_'irst_:a"u1 CSEYE5) S_YI)E_VERSION()C r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

In the above Ruby script we create a new in-memory database. .e e%ecute an )b' statement which returns the version of the )b'ite database.
r1Buir1 CsB"it18C

.e use s;lite: Ruby module to connect to the )b'ite database.

"#>

.b ! S_Yit18::Eatabas1.n1+ (:m1m-r&:(

.e create a new database object. The Latabase class encapsulates a single connection to an )b'ite database. The database is created in memory. )o it is not permanent.
puts .b.21t_'irst_:a"u1 CSEYE5) S_YI)E_VERSION()C

.e call the 21t_'irst_:a"u1 method of the db object. It e%ecutes the )b' statement and obtains the first value of the first row of a result set.
r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1

.e chec for errors. This is important, since wor ing with databases is error prone.
1nsur1 .b.,"-s1 i' .b 1n.

In the end, we release the resources.


$ .%:1rsi-n.rb 8. .

The output might loo li e the above.

Inserting #ata
.e will create a +ars table and insert several rows to it.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( .b.101,ut1 (5RE7)E )7BYE I] NO) E^IS)S 5ars(I. IN)E=ER NRI\7RY ZEY< Nam1 )E^)< Nri,1 IN))( .b.101,ut1 (INSER) IN)O 5ars V7YUES(1<C7u.iC<96>J6)( .b.101,ut1 (INSER) IN)O 5ars V7YUES(6<C\1r,1.1sC<9 16 )( .b.101,ut1 (INSER) IN)O 5ars V7YUES(8<CSH-.aC<@000)( .b.101,ut1 (INSER) IN)O 5ars V7YUES(J<CV-":-C<6@000)( .b.101,ut1 (INSER) IN)O 5ars V7YUES(9<CB1nt"1&C<890000)( .b.101,ut1 (INSER) IN)O 5ars V7YUES(><C5itr-1nC<61000)( .b.101,ut1 (INSER) IN)O 5ars V7YUES( <CAumm1rC<J1J00)( .b.101,ut1 (INSER) IN)O 5ars V7YUES(8<CV-"Hs+a21nC<61>00)( r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1

"##

1n.

.b.,"-s1 i' .b

The above script creates a +ars table and inserts > rows into the table.
.b ! S_Yit18::Eatabas1.-p1n (t1st..b(

.e connect to the test.db database.


.b.101,ut1 (5RE7)E )7BYE I] NO) E^IS)S 5ars(I. IN)E=ER NRI\7RY ZEY< Nam1 )E^)< Nri,1 IN))(

The 101,ut1 method e%ecutes the given )b' statement. 8 new +ars table is created if it does not already e%ist.
.b.101,ut1 (INSER) IN)O 5ars V7YUES(1<C7u.iC<96>J6)( .b.101,ut1 (INSER) IN)O 5ars V7YUES(6<C\1r,1.1sC<9 16 )(

These two lines insert two cars into the table. 3ote that by default, we are in the autocommit mode, where all changes to the table are immediately effective.
sB"it1> .m-.1 ,-"umn sB"it1> .*1a.1rs -n

.e verify the written data with the s;lite: tool. <irst we modify the way the data is displayed in the console. .e use the column mode and turn on the headers.
sB"it1> SEYE5) Q ]RO\ 5arsV I. Nam1 Nri,1 ;;;;;;;;;; ;;;;;;;;;; ;;;;;;;;;; 1 7u.i 96>J6 6 \1r,1.1s 9 16 8 SH-.a @000 J V-":6@000 9 B1nt"1& 890000 > 5itr-1n 61000 Aumm1r J1J00 8 V-"Hs+a21n 61>00

This is the data that we have written to the +ars table.

-he last inserte# ro" i#


)ometimes we need to determine the id of the last inserted row. .e use the "ast_ins1rt_r-+_i. method to find it.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.n1+ (:m1m-r&:( .b.101,ut1 (5RE7)E )7BYE ]ri1n.s(I. IN)E=ER NRI\7RY ZEY< Nam1 )E^))(

7--

.b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1

(INSER) (INSER) (INSER) (INSER) (INSER)

IN)O IN)O IN)O IN)O IN)O

]ri1n.s(Nam1) ]ri1n.s(Nam1) ]ri1n.s(Nam1) ]ri1n.s(Nam1) ]ri1n.s(Nam1)

V7YUES V7YUES V7YUES V7YUES V7YUES

(C)-mC)( (CR1b1,,aC)( (C3imC)( (CR-b1rtC)( (C3u"ianC)(

i. ! .b."ast_ins1rt_r-+_i. puts ()*1 "ast i. -' t*1 ins1rt1. r-+ is #Fi.G( r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

.e create a <riends table in memory. The Id is automatically incremented.


.b.101,ut1 (5RE7)E )7BYE ]ri1n.s(I. IN)E=ER NRI\7RY ZEY< Nam1 )E^))(

In )b'ite, IN)E=ER NRI\7RY ZEY column is auto incremented. There is also an 7U)OIN5RE\EN) eyword. .hen used in IN)E=ER NRI\7RY ZEY 7U)OIN5RE\EN) a slightly different algorithm for Id creation is used.
.b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1 (INSER) (INSER) (INSER) (INSER) (INSER) IN)O IN)O IN)O IN)O IN)O ]ri1n.s(Nam1) ]ri1n.s(Nam1) ]ri1n.s(Nam1) ]ri1n.s(Nam1) ]ri1n.s(Nam1) V7YUES V7YUES V7YUES V7YUES V7YUES (C)-mC)( (CR1b1,,aC)( (C3imC)( (CR-b1rtC)( (C3u"ianC)(

These five )b' statements insert five rows into the <riends table.
i. ! .b."ast_ins1rt_r-+_i.

&sing the "ast_ins1rt_r-+_i. method, we get the last inserted row id.
$ .%"ast_r-+i..rb )*1 "ast i. -' t*1 ins1rt1. r-+ is 9

.e see the output of the script.

,etching #ata
In the last e%ample of this chapter we fetch some data. !ore about data fetching will be discussed in the bueries chapter.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b(

7-"

stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars YI\I) 9( rs ! stm.101,ut1 rs.1a,* .- Lr-+L puts r-+.D-in (Xs( 1n. r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 stm.,"-s1 i' stm .b.,"-s1 i' .b 1n.

In the e%ample we fetch $ rows from the +ars table.


stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars YI\I) 9( rs ! stm.101,ut1

.e prepare an )b' statement for e%ecution with the pr1par1 method. The method returns a statement object. Then the )b' statement is e%ecuted using the 101,ut1 method. It returns a result set. The Resutl)et object is a simple cursor over the data that the ;uery returns.
rs.1a,* .- Lr-+L puts r-+.D-in (Xs( 1n.

.ith the 1a,* method we traverse the data in the result set. In each cycle, it returns a row. The row is an array of fields. These fields are joined with a empty space to form a line.
$ 1 6 8 J 9 .%'1t,*.rb 7u.i 96>J6 \1r,1.1s 9 16 SH-.a @000 V-":- 6@000 B1nt"1& 890000

This is the output of the fetch.rb script. In this chapter of the )b'ite Ruby tutorial, we have shown how to establish a database connection to the )b'ite database. .e have e%plained scripts which do some basic wor with a database.

/ueries
.e have already established a connection to the database. 3ow we are going modify and fetch the data from the database. Lata is retrieved from the database with the )*'*+T statement. In )b'ite Ruby module, first we prepare the )b' statement with the pr1par1 method. The )b' string is sent to the database engine, which chec s the statement validity, synta% and in some databases also the 7-7

user permissions to perform certain ;ueries. If all is 2M, a statement object is returned to the Ruby script. The ne%t step is the call to the 101,ut1 method. The method e%ecutes the ;uery within the database. The data is retrieved. The Ruby )b'ite module has several methods to fetch data from database tables. 8fter the )b' statement was prepared and e%ecuted, we can go through the returned data.

,etching #ata
In the first e%ample we fetch one row from the +ars table.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.n1+ (t1st..b( i. ! 1 stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars WAERE I.!U( stm.bin._param 1< i. rs ! stm.101,ut1 r-+ ! rs.n10t puts r-+.D-in (Xs( r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 stm.,"-s1 i' stm .b.,"-s1 i' .b 1n.

In the e%ample we do all the steps to get the first row from the +ars table.
stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars WAERE I.!U(

The )*'*+T statement is prepared with the pr1par1 method. 8 statement object is returned.
stm.bin._param 1< i.

8 parameter is bound to the placeholder in the statement.


rs ! stm.101,ut1

The statement is e%ecuted. 8 Result)et object is returned.


r-+ ! rs.n10t

7-:

.e obtain the ne%t row from the result set. )ince we want to fetch only one row, we call the n10t method once.
puts r-+.D-in (Xs(

The row is a Ruby array. The three fields are joined with a space character to form a line using the D-in method.
$ .%'1t,*.rb 1 7u.i 96>J6

This is the output of the e%ample.

In the following e%ample, we will fetch five rows. .e put the n10t method in a while loop.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars YI\I) 9( rs ! stm.101,ut1 +*i"1 (r-+ ! rs.n10t) .puts r-+.D-in (Xs( 1n. r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 stm.,"-s1 i' stm .b.,"-s1 i' .b 1n.

In this script we connect to the database and fetch $ rows of the +ars table.
stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars YI\I) 9(

This is the )b' statement for fetching $ rows.


+*i"1 (r-+ ! rs.n10t) .puts r-+.D-in (Xs( 1n.

The n10t method is put inside the while loop. It returns the ne%t row from the result set. If no more rows are left, the method returns nil and the while loop is terminated.

7-@

.e can get data from the result set using the 1a,* method.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars YI\I) 9( rs ! stm.101,ut1 rs.1a,* .- Lr-+L puts r-+.D-in (Xs( 1n. r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 stm.,"-s1 i' stm .b.,"-s1 i' .b 1n.

8gain we select five rows from the +ars table.


rs.1a,* .- Lr-+L puts r-+.D-in (Xs( 1n.

.e use the 1a,* method to iterate over the result set.

The ne%t e%ample shows the database objectEs 101,ut1 method. It is a convenience method that saves a few eystro es.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( r-+s ! .b.101,ut1 (SEYE5) Q ]RO\ 5ars YI\I) 9( '-r r-+ in r-+s .puts r-+.D-in (Xs( 1n. r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1

7-$

1nsur1 .b.,"-s1 i' .b 1n.

The e%ample selects and prints five rows from the +ars table.
r-+s ! .b.101,ut1 (SEYE5) Q ]RO\ 5ars YI\I) 9(

=ere we do two jobs in one step. .e prepare the statement and e%ecute it. The method returns the data in a Ruby array.
'-r r-+ in r-+s .puts r-+.D-in (Xs( 1n.

.e print the data from the Ruby array.

)o far we have seen data returned in the form of a Result)et or an array. The ne%t e%ample will return the data in the form of an array of hashes. This way we can identify field values by their column names.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( .b.r1su"ts_as_*as* ! tru1 ar& ! .b.101,ut1 (SEYE5) Q ]RO\ 5ars YI\I) 9( ar&.1a,* .- Lr-+L print' (Rs Rs RsXn(< r-+ICI.CK< r-+ICNam1CK< r-+ICNri,1CK 1n. r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

In the e%ample we get fields by their column names.


.b.r1su"ts_as_*as* ! tru1

.e set the r1su"ts_as_*as* property to true. 8ll rows will be returned as =ash objects, with the column names as the eys.
ar&.1a,* .- Lr-+L print' (Rs Rs RsXn(< r-+ICI.CK< r-+ICNam1CK< r-+ICNri,1CK 1n.

7-G

.e get the fields by their column names.


$ 1 6 8 J 9 .%'1t,*_*as*.rb 7u.i 96>J6 \1r,1.1s 9 16 SH-.a @000 V-":- 6@000 B1nt"1& 890000

.e see the output of the e%ample.

,etching a ro" or a value


Ruby )b'ite module has two convenience methods for retrieving a row or a value. In the first e%ample, we will get a single row from a table.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( r-+ ! .b.21t_'irst_r-+ (SEYE5) Q ]RO\ 5ars WAERE I.!1( puts r-+.D-in (Xs( r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

.e get the data for the first row of the +ars table.
r-+ ! .b.21t_'irst_r-+ (SEYE5) Q ]RO\ 5ars WAERE I.!1(

The 21t_'irst_r-+ method gets the first row and discards all other rows.
puts r-+.D-in (Xs(

The row is printed to the console.


$ .%'1t,*r-+.rb 1 7u.i 96>J6

=ere we see the output of the fetchrow.rb e%ample.

In the last e%ample, we select a single value.


#$%usr%bin%rub&

7-H

r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( :a" ! .b.21t_'irst_:a"u1 (SEYE5) Nri,1 ]RO\ 5ars WAERE Nam1!CB1nt"1&C( puts :a" r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

.e select a price for a specific car.


:a" ! .b.21t_'irst_:a"u1 (SEYE5) Nri,1 ]RO\ 5ars WAERE Nam1!CB1nt"1&C(

.ith the 21t_'irst_:a"u1 method we select a specific field of a row. In our case it is the price of the /entley car.
$ .%'1t,*:a"u1.rb 890000

This is the output. In this part of the )b'ite Ruby tutorial, we have demonstrated how to fetch data from the database using various methods.

Binding parameters
)b' statements are often dynamically built. 8 user provides some input and this input is built into the statement. 8 programmer must be cautious every time he deals with an input from a user. It has some serious security implications. The recommended way to dynamically build )b' statements is to use parameter binding. .hen we bind parameters, we create placeholders in the statement. The placeholder is a special mar in the )b' statement. It is often a ;uestion mar AQB. 'ater a parameter is bound to the placeholder with a bind0param, e%ecute, ;uery etc. methods. /inding parameters guards the program against )b' injections. It automatically escapes some special characters and allows them to be handled correctly. Latabase performance is often improved when statements are prepared and their parameters bound prior to statement e%ecution. In s;lite: Ruby module the statements are always prepared. *ven if we do not call the pr1par1 method and call directly the 101,ut1 method of the database object, the statement is prepared behind the scenes by the s;lite: Ruby module.
#$%usr%bin%rub&

7->

r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.n1+ (t1st..b( nam1 ! (V-"Hs+a21n( stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars WAERE Nam1 ! U( stm.bin._param 1< nam1 rs ! stm.101,ut1 r-+ ! rs.n10t puts r-+.D-in (Xs( r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 stm.,"-s1 i' stm .b.,"-s1 i' .b 1n.

The e%ample selects a row from the +ars table for a specific car name.
nam1 ! (V-"Hs+a21n(

This is a value that could come from a user5 for e%ample, from a =T!' form.
stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars WAERE Nam1 ! U(

The ;uestion mar AQB is a placeholder for a value. It is added later in the script.
stm.bin._param 1< nam1 rs ! stm.101,ut1

.ith the bin._param method, the name variable is associated with the placeholder in the statement. The 101,ut1 method will return the result set.
$ .%bin.param1.rb 8 V-"Hs+a21n 61>00

This is the output of the e%ample.

3e%t we present another way of binding parameters.


#$%usr%bin%rub& r1Buir1 CsB"it18C b12in

7-#

.b ! S_Yit18::Eatabas1.n1+ (t1st..b( i. ! J stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars WAERE I. ! :i.( rs ! stm.101,ut1 i. r-+ ! rs.n10t puts r-+.D-in (Xs( r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 stm.,"-s1 i' stm .b.,"-s1 i' .b 1n.

.e select a row from the +ars table for a specific Id.


stm ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars WAERE I. ! :i.(

(reviously we have seen a ;uestion mar as a placeholder. )b'ite Ruby supports named placeholders too.
rs ! stm.101,ut1 i.

The parameter is bound in the 101,ut1 method.

.e provide yet another way for binding parameters.


#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.n1+ (t1st..b( i. ! 8 r-+ ! .b.21t_'irst_r-+ (SEYE5) Q ]RO\ 5ars WAERE I. ! U(< i. puts r-+.D-in (Xs( r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

This time, everythingYpreparing the statement, binding the parameter and e%ecuting the statementYis done using one method.

7"-

r-+ ! .b.21t_'irst_r-+ (SEYE5) Q ]RO\ 5ars WAERE I. ! U(< i.

The 21t_'irst_r-+ is a convenience method, where three things are done in one step.

In our final e%ample, we will bind several parameters in one statement.


#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.n1+ (:m1m-r&:( stm ! .b.pr1par1 (SEYE5) 6 / U / > / U / U( stm.bin._params 8< J< > rs ! stm.101,ut1 r-+ ! rs.n10t puts r-+ r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 stm.,"-s1 i' stm .b.,"-s1 i' .b 1n.

In the e%ample, we have more placeholders in the )b' statement.


stm ! .b.pr1par1 (SEYE5) 6 / U / > / U / U(

There are three placeholders in the )*'*+T statement.


stm.bin._params 8< J< >

.e bind three values with the bin._params method.


$ .%bin.params.rb 61

This is the output of the bindparams.rb program. In this part of the )b'ite Ruby tutorial we tal ed about binding parameters.

1orking *ith images


In this chapter of the )b'ite Ruby tutorial, we will wor with image files. 3ote that some people oppose putting images into databases. =ere we only show how to do it. .e do not dwell into technical issues of whether to save images in databases or not. 7""

sB"it1> 5RE7)E )7BYE Ima21s(I. IN)E=ER NRI\7RY ZEY< Eata BYOB)V

<or this e%ample, we create a new table called Images. <or the images, we use the BYOB data type, which stands for /inary 'arge 2bject.

Inserting images
In the first e%ample, we are going to insert an image to the )b'ite database.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in 'in ! ]i"1.-p1n (+-man.Dp2( < (rb( im2 ! 'in.r1a. r1s,u1 S&st1m5a""Err-r !> 1 puts 1 1nsur1 'in.,"-s1 i' 'in 1n. b12in .b ! S_Yit18::Eatabas1.-p1n Ct1st..bC b"-b ! S_Yit18::B"-b.n1+ im2 .b.101,ut1 (INSER) IN)O Ima21s V7YUES(1< U)(< b"-b r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

.e read an image from the current wor ing directory and write it into the Images table of the )b'ite test.db database.
'in ! ]i"1.-p1n (+-man.Dp2( < (rb( im2 ! 'in.r1a.

.e open and read a jpg image. The r1a. method returns the data as string.
b"-b ! S_Yit18::B"-b.n1+ im2

.e create an instance of the S_Yit18::B"-b class. It is intended for wor ing with binary data.
.b.101,ut1 (INSER) IN)O Ima21s V7YUES(1< U)(< b"-b

The image is written to the database.

7"7

Rea#ing images
In this section, we are going to perform the reverse operation. .e will read an image from the database table.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n Ct1st..bC .ata ! .b.21t_'irst_:a"u1 (SEYE5) Eata ]RO\ Ima21s YI\I) 1( ' ! ]i"1.n1+ (+-man6.Dp2(< (+b( '.+rit1 .ata r1s,u1 S_Yit18::E0,1pti-n< S&st1m5a""Err-r !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 '.,"-s1 i' ' .b.,"-s1 i' .b 1n.

.e read image data from the Images table and write it to another file, which we call woman7.jpg.
.ata ! .b.21t_'irst_:a"u1 (SEYE5) Eata ]RO\ Ima21s YI\I) 1(

This line selects the image data from the table.


' ! ]i"1.n1+ (+-man6.Dp2(< (+b( '.+rit1 .ata

.e open a new image file and write the retrieved data into that file. Then we close the file. This part of the )b'ite Ruby tutorial was dedicated to reading and writing images.

2etting database metadata


!etadata is information about the data in a database. !etadata in )b'ite contains information about the tables and columns in which we store data. The number of rows that an )b' statement affects is metadata. The number of rows and columns returned in a result set are metadata as well. !etadata in )b'ite can be obtained using the NR7=\7 command. )b'ite objects may have attributes, which are metadata. <inally, we can also obtain specific metatada from ;uerying the )b'ite system sB"it1_mast1r table.
#$%usr%bin%rub&

7":

r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( pst ! .b.pr1par1 (SEYE5) Q ]RO\ 5ars YI\I) >( puts pst.,-"umns puts pst.t&p1s puts pst.,-"umn_,-unt r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 pst.,"-s1 i' pst .b.,"-s1 i' .b 1n.

In the above e%ample, we get the column names, column types and the number of columns of a prepared statement.
puts pst.,-"umns puts pst.t&p1s puts pst.,-"umn_,-unt

These three methods return the column names, column types and the number of columns of a prepared statement.
$ .%,-"s_'i1".s.rb I. Nam1 Nri,1 IN)E=ER )E^) IN) 8

The output shows three column names5 Id, 3ame and (rice. The types are I3T*O*R, T*4T and I3T.

The following e%ample shows how to retrieve the number of changes produced by a particular )b' command.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.n1+ (:m1m-r&:(

7"@

.b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1

(5RE7)E (INSER) (INSER) (INSER) (INSER) (INSER) (EEYE)E

)7BYE ]ri1n.s(I. IN)E=ER NRI\7RY ZEY< Nam1 )E^))( IN)O ]ri1n.s(Nam1) V7YUES (C)-mC)( IN)O ]ri1n.s(Nam1) V7YUES (CR1b1,,aC)( IN)O ]ri1n.s(Nam1) V7YUES (C3imC)( IN)O ]ri1n.s(Nam1) V7YUES (CR-b1rtC)( IN)O ]ri1n.s(Nam1) V7YUES (C3u"ianC)( ]RO\ ]ri1n.s WAERE I. IN (8< J< 9)(

n ! .b.,*an21s puts ()*1r1 *as b11n #FnG ,*an21s( r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

.e create a <riends table in memory. In the last )b' command, we delete three rows. .e use the ,*an21s method to get the number of changes done by the last )b' operation.
.b.101,ut1 (EEYE)E ]RO\ ]ri1n.s WAERE I. IN (8< J< 9)(

In this )b' statement, we delete three rows.


n ! .b.,*an21s puts ()*1r1 *as b11n #FnG ,*an21s(

.e find out the number of changes done by the last )b' statement.
$ .%,*an21s.rb )*1r1 *as b11n 8 ,*an21s

*%ample output.

In the ne%t e%ample, we will find out some data about the +ars table.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( stm ! .b.pr1par1 (NR7=\7 tab"1_in'-(C5arsC)( rs ! stm.101,ut1 rs.1a,* .- Lr-+L puts r-+.D-in (Xs( 1n. r1s,u1 S_Yit18::E0,1pti-n !> 1

7"$

puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 stm.,"-s1 i' stm .b.,"-s1 i' .b 1n.

In this e%ample, we issue the NR7=\7 tab"1_in'-(tab"1Nam1) command to get some metadata info about our +ars table.
stm ! .b.pr1par1 (NR7=\7 tab"1_in'-(C5arsC)( rs ! stm.101,ut1

The NR7=\7 tab"1_in'-(5ars) command returns one row for each column in the +ars table. +olumns in the result set include the column order number, column name, data type, whether or not the column can be 3&'', and the default value for the column.
rs.1a,* .- Lr-+L puts r-+.D-in (Xs( 1n.

.e iterate over the result set and print the data.


$ 0 1 6 .%tab"1_in'-.rb I. IN)E=ER 0 1 Nam1 )E^) 0 0 Nri,1 IN) 0 0

2utput of the e%ample.

3e%t we will print $ rows from the +ars table with their column names.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( r-+s ! .b.101,ut16 (SEYE5) Q ]RO\ 5ars YI\I) 9( r-+s.1a,* .- Lr-+L puts (R8s R;8s Rs( R Ir-+I0K< r-+I1K< r-+I6KK 1n. r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

7"G

.e print five rows of the +ars table to the console. 3ow, we include the names of the columns too. The records are aligned with the column names.
r-+s ! .b.101,ut16 (SEYE5) Q ]RO\ 5ars YI\I) 9(

The 101,ut16 method e%ecutes the given )b' statement. The first row returned is the names of the columns.
r-+s.1a,* .- Lr-+L puts (R8s R;8s Rs( R Ir-+I0K< r-+I1K< r-+I6KK 1n.

The data is retrieved, formatted and printed to the terminal.


$ .%,-"umn_nam1s.rb I. Nam1 Nri,1 1 7u.i 96>J6 6 \1r,1.1s 9 16 8 SH-.a @000 J V-":6@000 9 B1nt"1& 890000

2utput.

In our last e%ample related to the metadata, we will list all tables in the test.db database.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( r-+s ! .b.101,ut1 MMS_Y SEYE5) nam1 ]RO\ sB"it1_mast1r WAERE t&p1!Ctab"1C OREER BY nam1V( r-+s.1a,* .- Lr-+L puts r-+ 1n. r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

S_Y

The code e%ample prints all available tables in the current database to the terminal.
r-+s ! .b.101,ut1 MMS_Y SEYE5) nam1 ]RO\ sB"it1_mast1r

7"H

WAERE t&p1!Ctab"1C OREER BY nam1V( S_Y

The table names are retrieved from the sB"it1_mast1r table.


$ .%"ist_tab"1s.rb 5ars ]ri1n.s Ima21s

These were the tables on our system. In this part of the )b'ite Ruby tutorial, we have wor ed with database metadata.

$ransactions
In this chapter, we will wor with transactions. <irst, we provide some basic definitions. Then we present Ruby scripts that show, how to wor with transactions in Ruby s;lite: module. .e will also tal about the autocommit mode, which is essential to understand when dealing with transactions.

e*initions
8 transaction is an atomic unit of database operations against the data in one or more databases. The effects of all the )b' statements in a transaction can be either all committed to the database or all rolled bac . In the autocommit mode the changes are immediately effective. To wor with transactions we start a transaction with the transa,ti-n method. The transaction is ended with either the ,-mmit or r-""ba,H methods. The database connection is in the autocommit mode by default. 3ote that the default mode depends on the driver. In the )b'ite (ython driver, the autocommit is turned off by default. In )b'ite, any command other than the )*'*+T will start an implicit transaction. 8lso, within a transaction a command li e +R*8T* T8/'* ..., 18+&&!, (R8O!8 will commit previous changes before e%ecuting. !anual transactions are started with the /*OI3 TR83)8+TI23 statement and finished with the +2!!IT 2R R2''/8+M statements. )b'ite supports three non-standard transaction levels5 L*<*RR*L, I!!*LI8T* and *4+'&)I1*.

'.amples
3ow we will have some scripts that wor with transactions and the autocommit mode.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in

7">

.b ! S_Yit18::Eatabas1.-p1n (t1st..b( .b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1 .b.101,ut1 (ERON )7BYE I] E^IS)S ]ri1n.s( (5RE7)E )7BYE ]ri1n.s(I. IN)E=ER NRI\7RY ZEY< Nam1 )E^))( (INSER) IN)O ]ri1n.s(Nam1) V7YUES (C)-mC)( (INSER) IN)O ]ri1n.s(Nam1) V7YUES (CR1b1,,aC)( (INSER) IN)O ]ri1n.s(Nam1) V7YUES (C3imC)( (INSER) IN)O ]ri1n.s(Nam1) V7YUES (CR-b1rtC)( (INSER) IN)O ]ri1n.s(Nam1) V7YUES (C3u"ianC)(

r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

.e create a <riends table and fill it with data. .e do not e%plicitly start a transaction, nor do we call commit or rollbac methods. Yet the data is written to the table. This is because the default wor ing mode is autocommit. In this mode each )b' statement is immediately effective.
.b.101,ut1 (ERON )7BYE I] E^IS)S ]ri1n.s( .b.101,ut1 (5RE7)E )7BYE ]ri1n.s(I. IN)E=ER NRI\7RY ZEY< Nam1 )E^))(

.e drop the <riends table if it already e%ists. Then we create the table with the +R*8T* T8/'* statement.
.b.101,ut1 (INSER) IN)O ]ri1n.s(Nam1) V7YUES (C)-mC)( .b.101,ut1 (INSER) IN)O ]ri1n.s(Nam1) V7YUES (CR1b1,,aC)( ...

.e insert data.
$ .%aut-,-mmit.rb $ sB"it18 t1st..b S_Yit1 :1rsi-n 8. . 6011;0>;68 1@:J@:66 Ent1r (.*1"p( '-r instru,ti-ns Ent1r S_Y stat1m1nts t1rminat1. +it* a (V( sB"it1> SEYE5) Q ]RO\ ]ri1n.sV 1L)-m 6LR1b1,,a 8L3im JLR-b1rt 9L3u"ian

.e e%ecute the script and chec the table with the s;lite: command line tool. The <riends table is succesfully created.

In the second e%ample we will start a transaction with the transa,ti-n method.
#$%usr%bin%rub&

7"#

r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( .b.transa,ti-n .b.101,ut1 (ERON )7BYE I] E^IS)S ]ri1n.s( .b.101,ut1 (5RE7)E )7BYE ]ri1n.s(I. IN)E=ER NRI\7RY ZEY< Nam1 )E^))( .b.101,ut1 (INSER) IN)O ]ri1n.s(Nam1) V7YUES (C)-mC)( .b.101,ut1 (INSER) IN)O ]ri1n.s(Nam1) V7YUES (CR1b1,,aC)( .b.101,ut1 (INSER) IN)O ]ri1n.s(Nam1) V7YUES (C3imC)( .b.101,ut1 (INSER) IN)O ]ri1n.s(Nam1) V7YUES (CR-b1rtC)( .b.101,ut1 (INSER) IN)O ]ri1n.s(Nam1) V7YUES (C3u"ianC)( .b.101,ut1 (INSER) IN)O ]ri1n.s(Nam1) V7YUES (C\i,*a1"C)( .b.,-mmit r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 .b.r-""ba,H 1nsur1 .b.,"-s1 i' .b 1n.

.e recreate the <riends table. 8fter the transa,ti-n method call, every statement is within a transaction until we call the ,-mmit method. .e either save all changes or save nothing. This is the basic idea behind transactions.
.b.transa,ti-n

The transa,ti-n method begins a new transaction. The method ta es an optional mode parameter, where we can specify the transaction level. The default level is L*<*RR*L.
.b.,-mmit

The changes are written to the database. If we commented the line, the changes would not be saved.
.b.r-""ba,H

In case of an error, we rollbac the changes.


sB"it1> SEYE5) Q ]RO\ ]ri1n.sV 1L)-m 6LR1b1,,a 8L3im JLR-b1rt 9L3u"ian >L\i,*a1"

.e verify with the s;lite: command line tool that the changes were written.

77-

.hen there is an error in the transaction, the transaction is rolled bac an no changes are committed to the database.
#$%usr%bin%rub& r1Buir1 CsB"it18C b12in .b ! S_Yit18::Eatabas1.-p1n (t1st..b( .b.transa,ti-n .b.101,ut1 (UNE7)E ]ri1n.s SE) Nam1!C)*-masC WAERE I.!1( .b.101,ut1 (UNE7)E ]ri1n. SE) Nam1!CB-bC WAERE I.!J( .b.,-mmit r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 .b.r-""ba,H 1nsur1 .b.,"-s1 i' .b 1n.

In the code e%ample we want to change two names. There are two statements that form a transaction. There is an error in the second )b' statement. Therefore the transaction is rolled bac .
.b.101,ut1 (UNE7)E ]ri1n. SE) Nam1!CB-bC WAERE I.!J(

The name of the table is incorrect. There is no <riend table in the database.
$ .%r-""in2ba,H.rb E0,1pti-n -,,ur1. n- su,* tab"1: ]ri1n.

Running the e%ample will display this error message. The transaction is rolled bac .
sB"it1> SEYE5) Q ]RO\ ]ri1n.sV 1L)-m 6LR1b1,,a 8L3im JLR-b1rt 9L3u"ian

The <riends table was not changed, even though the first &(L8T* statement was correct.

.e will again try to change two rows, this time in autocommit mode.
#$%usr%bin%rub& r1Buir1 CsB"it18C

77"

b12in .b ! S_Yit18::Eatabas1.n1+ (t1st..b( .b.101,ut1 (UNE7)E ]ri1n.s SE) Nam1!C)*-masC WAERE I.!1( .b.101,ut1 (UNE7)E ]ri1n. SE) Nam1!CB-bC WAERE I.!J( r1s,u1 S_Yit18::E0,1pti-n !> 1 puts (E0,1pti-n -,,ur1.( puts 1 1nsur1 .b.,"-s1 i' .b 1n.

.e try to update two names in the <riends table, changing Tom to Thomas and Robert to /ob.
.b.101,ut1 (UNE7)E ]ri1n.s SE) Nam1!C)*-masC WAERE I.!1( .b.101,ut1 (UNE7)E ]ri1n. SE) Nam1!CB-bC WAERE I.!J(

The second of the &(L8T* statements is incorrect.


$ .%aut-,-mmit6.rb E0,1pti-n -,,ur1. n- su,* tab"1: ]ri1n.

.e receive the same error message as in the previous e%ample.


sB"it1> SEYE5) Q ]RO\ ]ri1n.sV 1L)*-mas 6LR1b1,,a 8L3im JLR-b1rt 9L3u"ian

=owever this time, the first &(L8T* statement was saved. The second one was not. In this part of the )b'ite Ruby tutorial, we have wor ed with transactions.

My%/0 Ruby tutorial


This is a Ruby programming tutorial for the !y)b' database. It covers the basics of !y)b' programming with Ruby. It uses the mys;l7 module. The e%amples were created and tested on &buntu 'inu%.

1yS6% ( Ruby
My%/0 is a leading open source database management system. It is a multi user, multithreaded database management system. !y)b' is especially popular on the web. It is one of the parts of the very popular 0+M& platform. 'inu%, 8pache, !y)b', (=(. +urrently !y)b' is owned by 2racle. !y)b' database is available on most important 2)

777

platforms. Ruby is a dynamic, reflective, general-purpose object-oriented programming language. Recently it became very popular in web programming, mainly due to the successful Ruby on Rails framewor .

mys0l7 mo#ule
The mys;l7 module is a Ruby interface to the !y)b' server. It provides the same functions for Ruby programs that the !y)b' + 8(I provides for + programs.
$ su.- 21m1.@ insta"" m&sB"6

=ere we install the Ruby module for the !y)b' database.

Be*ore "e start


.e are going to create a new database user and a new database. To do this, we use the mys;l client program.
$ m&sB" ;u r--t ;p Ent1r pass+-r.: W1",-m1 t- t*1 \&S_Y m-nit-r. 5-mman.s 1n. +it* V -r X2. Y-ur \&S_Y ,-nn1,ti-n i. is 80 S1r:1r :1rsi-n: 9.0.> ;0ubuntu> (Ubuntu) )&p1 C*1"pVC -r CX*C '-r *1"p. )&p1 CX,C t- ,"1ar t*1 bu''1r. m&sB"> SAOW E7)7B7SESV /;;;;;;;;;;;;;;;;;;;;/ L Eatabas1 L /;;;;;;;;;;;;;;;;;;;;/ L in'-rmati-n_s,*1ma L L m&sB" L /;;;;;;;;;;;;;;;;;;;;/ 6 r-+s in s1t (0.00 s1,)

.e connect to the !y)b' server using the root account. .e show all available databases with the )=2. L8T8/8)*) statement.
m&sB"> 5RE7)E E7)7B7SE m&.bV _u1r& OZ< 1 r-+ a''1,t1. (0.06 s1,)

.e create a new mydb database. .e will use this database throughout the tutorial.
m&sB"> 5RE7)E USER us1r16O"-,a"*-st IEEN)I]IEE BY C8JH"BQCV _u1r& OZ< 0 r-+s a''1,t1. (0.00 s1,) m&sB"> USE m&.bV Eatabas1 ,*an21. m&sB"> =R7N) 7YY ON m&.b.Q t- us1r16O"-,a"*-stV _u1r& OZ< 0 r-+s a''1,t1. (0.00 s1,) m&sB"> BuitV B&1

77:

.e create a new database user. .e grant all privileges to this user for all tables of the mydb database.

1yS6% server version


In the first e%ample, we will get the version of the !y)b' database.
#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC puts ,-n.21t_s1r:1r_in'rs ! ,-n.Bu1r& CSEYE5) VERSION()C puts rs.'1t,*_r-+ r1s,u1 \&sB"::Err-r !> 1 puts 1.1rrnputs 1.1rr-r 1nsur1 ,-n.,"-s1 i' ,-n 1n.

In this script, we get the server version. .e do it in two different ways.


r1Buir1 Cm&sB"C

.e import the m&sB" module. The module has the classes and methods to wor with the !y)b' database.
,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC

.e create the connection object. The parameters include the host name, user name and password. In our case the host name is localhost, e.g. our computer.
puts ,-n.21t_s1r:1r_in'-

The !ys;l object, that we have created, has a 21t_s1r:1r_in'- method. It returns the version of the !y)b' server installed.
rs ! ,-n.Bu1r& CSEYE5) VERSION()C puts rs.'1t,*_r-+

8nother way to get the version is to e%ecute the SEYE5) VERSION() )b' statement. .e fetch the data. )ince we retrieve only one record, we call the '1t,*_r-+ method.
r1s,u1 \&sB"::Err-r !> 1 puts 1.1rrnputs 1.1rr-r

.e chec for errors. This is important, since wor ing with databases is error prone.

77@

1nsur1 ,-n.,"-s1 i' ,-n 1n.

In the end, we release the resources.


$ .%:1rsi-n.rb 9.9.@ 9.9.@

The output might loo li e the above.

%isting #atabases
The !y)b' Ruby module has a "ist_.bs method, which returns available databases.
#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC ,-n."ist_.bs.1a,* .- L.bL puts .b 1n. r1s,u1 \&sB"::Err-r !> 1 puts 1.1rrnputs 1.1rr-r 1nsur1 ,-n.,"-s1 i' ,-n 1n.

In this script, we print all available databases on our !y)b' server.


,-n."ist_.bs.1a,* .- L.bL puts .b 1n.

The "ist_.bs method returns an array of available database names. &sing the each method of the array, we print each item of the array to the console.
$ .%"ist.b.rb in'-rmati-n_s,*1ma m&.b t1st +-r".

2n my system, I had the above databases created.

Creating an# populating a table


.e create a table and populate it with some data.

77$

#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC ,-n.Bu1r&((5RE7)E )7BYE I] NO) E^IS)S X Writ1rs(I. IN) NRI\7RY ZEY 7U)O_IN5RE\EN)< Nam1 V7R5A7R(69))() ,-n.Bu1r&((INSER) IN)O Writ1rs(Nam1) V7YUES(C3a,H Y-n.-nC)() ,-n.Bu1r&((INSER) IN)O Writ1rs(Nam1) V7YUES(CA-n-r1 .1 Ba"?a,C)() ,-n.Bu1r&((INSER) IN)O Writ1rs(Nam1) V7YUES(CYi-n ]1u,*t+an21rC)() ,-n.Bu1r&((INSER) IN)O Writ1rs(Nam1) V7YUES(CEmi"1 4-"aC)() ,-n.Bu1r&((INSER) IN)O Writ1rs(Nam1) V7YUES(C)ruman 5ap-t1C)() r1s,u1 \&sB"::Err-r !> 1 puts 1.1rrnputs 1.1rr-r 1nsur1 ,-n.,"-s1 i' ,-n 1n.

.e create a .riters table and add five authors to it.


,-n.Bu1r&((5RE7)E )7BYE I] NO) E^IS)S X Writ1rs(I. IN) NRI\7RY ZEY 7U)O_IN5RE\EN)< Nam1 V7R5A7R(69))()

To e%ecute an )b' statement, we use the Bu1r& method. This )b' statement creates a new database table called .riters. It has two columns. Id and 3ame.
,-n.Bu1r&((INSER) IN)O Writ1rs(Nam1) V7YUES(C3a,H Y-n.-nC)() ,-n.Bu1r&((INSER) IN)O Writ1rs(Nam1) V7YUES(CA-n-r1 .1 Ba"?a,C)() ...

.e use the INSER) statement to insert authors to the table. =ere we add two rows.
m&sB"> SEYE5) Q ]RO\ Writ1rsV /;;;;/;;;;;;;;;;;;;;;;;;;/ L I. L Nam1 L /;;;;/;;;;;;;;;;;;;;;;;;;/ L 1 L 3a,H Y-n.-n L L 6 L A-n-r1 .1 Ba"?a, L L 8 L Yi-n ]1u,*t+an21r L L J L Emi"1 4-"a L L 9 L )ruman 5ap-t1 L /;;;;/;;;;;;;;;;;;;;;;;;;/ 9 r-+s in s1t (0.00 s1,)

8fter e%ecuting the script, we use the m&sB" client tool to select all data from the .riters table.

Retrieving #ata
3ow, that we have inserted some data into the database, we can retrieve it bac .

77G

#$%usr%bin%rub& r1Buir1 (m&sB"( b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC rs ! ,-n.Bu1r&((SEYE5) Q ]RO\ Writ1rs() n_r-+s ! rs.num_r-+s puts ()*1r1 ar1 #Fn_r-+sG r-+s in t*1 r1su"t s1t( n_r-+s.tim1s .puts rs.'1t,*_r-+.D-in((Xs() 1n. r1s,u1 \&sB"::Err-r !> 1 puts 1.1rrnputs 1.1rr-r 1nsur1 ,-n.,"-s1 i' ,-n 1n.

In this e%ample, we retrieve all data from the .riters table.


,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC

The last parameter of the constructor is the database name, to which we connect.
rs ! ,-n.Bu1r&((SEYE5) Q ]RO\ Writ1rs()

This )b' statement selects all data from the .riters table.
n_r-+s ! rs.num_r-+s

.e get the number of rows in the result set using the num_r-+s method of the result set object.
n_r-+s.tim1s .puts rs.'1t,*_r-+.D-in((Xs() 1n.

=ere we fetch each row with the '1t,*_r-+ method. It returns a row as an array of fields. /y default, the fields are separated by new line, when printed. .ith the D-in method, we print each row on one line. The fields are separated by one space.
$ .%r1tri1:11.rb )*1r1 ar1 9 r-+s in t*1 r1su"t s1t 1 3a,H Y-n.-n 6 A-n-r1 .1 Ba"?a, 8 Yi-n ]1u,*t+an21r J Emi"1 4-"a 9 )ruman 5ap-t1

77H

3e%t we present another way to retrieve data from the table.


#$%usr%bin%rub& r1Buir1 (m&sB"( b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC rs ! ,-n.Bu1r&((SEYE5) Q ]RO\ Writ1rs() rs.1a,* .- Lr-+L puts r-+.D-in((Xs() 1n. r1s,u1 \&sB"::Err-r !> 1 puts 1.1rrnputs 1.1rr-r 1nsur1 ,-n.,"-s1 i' ,-n 1n.

.e print all data from the .riters table. This time we use an each method of the result set to traverse the data.
rs.1a,* .- Lr-+L puts r-+.D-in((Xs() 1n.

.e iterate through the result set using the each method.


$ 1 6 8 J 9 .%r1tri1:16.rb 3a,H Y-n.-n A-n-r1 .1 Ba"?a, Yi-n ]1u,*t+an21r Emi"1 4-"a )ruman 5ap-t1

This is the output of the e%ample. .e can traverse data in form of a Ruby hash.
#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC rs ! ,-n.Bu1r& (SEYE5) Q ]RO\ Writ1rs WAERE I. IN (1< 6< 8)( puts (W1 *a:1 #Frs.num_r-+sG r-+(s)( rs.1a,*_*as* .- Lr-+L puts r-+ICI.CK / ( ( / r-+ICNam1CK 1n. r1s,u1 \&sB"::Err-r !> 1

77>

puts 1 1nsur1 ,-n.,"-s1 i' ,-n 1n.

In the e%ample, we use the 1a,*_*as* iterator. Records from the result set can be retrieved by their column names.
rs.1a,*_*as* .- Lr-+L puts r-+ICI.CK / ( ( / r-+ICNam1CK 1n.

.e go through the result set with the 1a,*_*as* method. *ach returned row is a Ruby hashN a collection of ey-value pairs. The eys are the column names.
$ .%r1tri1:18.rb W1 *a:1 8 r-+(s) 1 3a,H Y-n.-n 6 A-n-r1 .1 Ba"?a, 8 Yi-n ]1u,*t+an21r

2uput of the e%ample.

1ultiple statements
!y)b' supports multiple statement e%ecution. This must be enabled by a special option.
#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC ,-n.s1t_s1r:1r_-pti-n \&sB"::ON)ION_\UY)I_S)7)E\EN)S_ON rs ! ,-n.Bu1r& (SEYE5) Nam1 ]RO\ Writ1rs WAERE I.!1V SEYE5) Nam1 ]RO\ Writ1rs WAERE I.!6V SEYE5) Nam1 ]RO\ Writ1rs WAERE I.!8( puts rs.'1t,*_r-+ +*i"1 ,-n.n10t_r1su"t rs ! ,-n.st-r1_r1su"t puts rs.'1t,*_r-+ 1n. r1s,u1 \&sB"::Err-r !> 1 puts 1.1rrnputs 1.1rr-r 1nsur1 ,-n.,"-s1 i' ,-n 1n.

In this e%ample, we have three )*'*+T statements in one ;uery. 77#

,-n.s1t_s1r:1r_-pti-n \&sB"::ON)ION_\UY)I_S)7)E\EN)S_ON

<irst we need to enable the multiple statements processing with the \&sB"::ON)ION_\UY)I_S)7)E\EN)S_ON.
rs ! ,-n.Bu1r& (SEYE5) Nam1 ]RO\ Writ1rs WAERE I.!1V SEYE5) Nam1 ]RO\ Writ1rs WAERE I.!6V SEYE5) Nam1 ]RO\ Writ1rs WAERE I.!8(

=ere we define three )*'*+T statements. They are separated by a semicolon.


puts rs.'1t,*_r-+

The ;uery method returns the first result set. .e fetch a row from this result set.
+*i"1 ,-n.n10t_r1su"t rs ! ,-n.st-r1_r1su"t puts rs.'1t,*_r-+ 1n.

.e get additional result sets until there are no more statements left to process.
$ .%mu"tip"1st.rb 3a,H Y-n.-n A-n-r1 .1 Ba"?a, Yi-n ]1u,*t+an21r

Running the e%ample.

1eta#ata
!etadata is information about the data in the database. !etadata in a !y)b' system contains information about the tables and columns, in which we store data. 3umber of rows affected by an )b' statement is a metadata. 3umber of rows and columns returned in a result set belong to metadata as well.
#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC rs ! ,-n.Bu1r& (SEYE5) Q ]RO\ Writ1rs WAERE I. IN (1< 6< 8)( puts (W1 *a:1 #F,-n.'i1"._,-untG 'i1".s( puts (W1 *a:1 #Frs.num_r-+sG r-+(s)( puts rs.'1t,*_r-+.D-in((Xs() r1s,u1 \&sB"::Err-r !> 1 puts 1 1nsur1 ,-n.,"-s1 i' ,-n 1n.

In this script, we find out the number of rows and columns from an )b' ;uery. 7:-

rs ! ,-n.Bu1r& (SEYE5) Q ]RO\ Writ1rs WAERE I. IN (1< 6< 8)(

This )b' statement returns three rows. *ach row has two columns.
puts (W1 *a:1 #F,-n.'i1"._,-untG 'i1".s( puts (W1 *a:1 #Frs.num_r-+sG r-+(s)(

These two lines return the number of columns and rows in the result set. 3ote that here a field is a synonym for a column. The returned data is metadata.
puts rs.'1t,*_r-+.D-in((Xs()

=ere we return one row from the result set. This is the original data stored in our database table. <or INSER), EEYE)E and UNE7)E statements there is a method called r-+s_a''1,t1.. This method returns the number of rows affected by these three statements.
#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC ,-n.Bu1r& (EEYE)E ]RO\ Writ1rs WAERE I. IN (1< 6< 8)( puts ()*1 Bu1r& *as a''1,t1. #F,-n.a''1,t1._r-+sG r-+s( r1s,u1 \&sB"::Err-r !> 1 puts 1 1nsur1 ,-n.,"-s1 i' ,-n 1n.

In our e%ample, we delete first three rows from the .riters table.
,-n.Bu1r& (EEYE)E ]RO\ Writ1rs WAERE I. IN (1< 6< 8)(

8n )b' statement, which deletes first three rows of the .riters table.
puts ()*1 Bu1r& *as a''1,t1. #F,-n.a''1,t1._r-+sG r-+s(

=ere we get the number of rows, that were affected by the above )b' statement. This number belongs to the metadata.
$ .%a''1,t1..rb )*1 Bu1r& *as a''1,t1. 8 r-+s m&sB"> SEYE5) Q ]RO\ Writ1rsV /;;;;/;;;;;;;;;;;;;;;/ L I. L Nam1 L /;;;;/;;;;;;;;;;;;;;;/ L J L Emi"1 4-"a L L 9 L )ruman 5ap-t1 L /;;;;/;;;;;;;;;;;;;;;/

7:"

6 r-+s in s1t (0.00 s1,)

.e e%ecute the affected.rb script and chec for changes in the .riters table. Three rows have been deleted. In the ne%t e%ample, we are going to chec for metadata about a field.
#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC rs ! ,-n.Bu1r& (SEYE5) Q ]RO\ Writ1rs WAERE I.!1( 'i1". ! rs.'1t,*_'i1"._.ir1,t 1 puts puts puts puts ()ab"1 (]i1". (]i1". (]i1". nam1: #F'i1"..tab"1G( nam1: #F'i1"..nam1G( "1n2t*: #F'i1".."1n2t*G( t&p1: #F'i1"..t&p1G(

r1s,u1 \&sB"::Err-r !> 1 puts 1 1nsur1 ,-n.,"-s1 i' ,-n 1n.

.e get one record from the database. .e get the fieldEs table name, colum name, length and type.
rs ! ,-n.Bu1r& (SEYE5) Q ]RO\ Writ1rs WAERE I.!1(

This ;uery returns one row. It has two columns.


'i1". ! rs.'1t,*_'i1"._.ir1,t 1

&sing the '1t,*_'i1"._.ir1,t method, we get a specific record. !ore precisely, the record from the intersection of the first row, second column.
puts puts puts puts ()ab"1 (]i1". (]i1". (]i1". nam1: #F'i1"..tab"1G( nam1: #F'i1"..nam1G( "1n2t*: #F'i1".."1n2t*G( t&p1: #F'i1"..t&p1G(

.e get the metadata using attribute readers of the field object.


$ .%m1ta.ata.rb )ab"1 nam1: Writ1rs ]i1". nam1: Nam1 ]i1". "1n2t*: 69 ]i1". t&p1: 698

This is the output of the e%ample.

7:7

In our last e%ample relating to the metadata, we will print all rows from the table with their column names.
#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC rs ! ,-n.Bu1r& (SEYE5) Q ]RO\ Writ1rs( 'i1".s ! rs.'1t,*_'i1".s puts (R8s Rs( R I'i1".sI0K.nam1< 'i1".sI1K.nam1K rs.1a,*_*as* .- Lr-+L puts (R8s Rs( R Ir-+ICI.CK< r-+ICNam1CKK 1n. r1s,u1 \&sB"::Err-r !> 1 puts 1 1nsur1 ,-n.,"-s1 i' ,-n 1n.

.e print the contents of the .riters table to the console. 3ow, we include the names of the columns too.
'i1".s ! rs.'1t,*_'i1".s puts (R8s Rs( R I'i1".sI0K.nam1< 'i1".sI1K.nam1K

In the first step, we get the column names. They are printed using the standard Ruby string formatting abilities.
rs.1a,*_*as* .- Lr-+L puts (R8s Rs( R Ir-+ICI.CK< r-+ICNam1CKK 1n.

3ow the data is fechted and printed to the console. .e do some formatting too.
$ .%,-"umn*1a.1rs.rb I. Nam1 1 3a,H Y-n.-n 6 A-n-r1 .1 Ba"?a, 8 Yi-n ]1u,*t+an21r J Emi"1 4-"a 9 )ruman 5ap-t1

2uput of the script.

Prepare# statements
3ow we will concern ourselves with prepared statements. .hen we write prepared statements, we use placeholders instead of directly writing the values into the statements. (repared statements increase security and performance.

7::

#$%usr%bin%rub& r1Buir1 Cm&sB"C nam1 ! (St1'an 4+1i2( b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC pst ! ,-n.pr1par1 (INSER) IN)O Writ1rs(Nam1) V7YUES(U)( pst.101,ut1 nam1 r1s,u1 \&sB"::Err-r !> 1 puts 1 1nsur1 ,-n.,"-s1 i' ,-n pst.,"-s1 i' pst 1n.

In the above e%ample, we insert a new row into the .riters table. .e use a prepared statement.
pst ! ,-n.pr1par1 (INSER) IN)O Writ1rs(Nam1) V7YUES(U)(

The pr1par1 method is used to create a prepared statement. The Q character is a placeholder. 'ater we bind a value to this placeholder.
pst.101,ut1 nam1

.e bind a value from the name variable to the placeholder and e%ecute the prepared statement.
pst.,"-s1 i' pst

The prepared statement is closed.


m&sB"> SEYE5) Q ]RO\ Writ1rsV /;;;;/;;;;;;;;;;;;;;;;;;;/ L I. L Nam1 L /;;;;/;;;;;;;;;;;;;;;;;;;/ L 1 L 3a,H Y-n.-n L L 6 L A-n-r1 .1 Ba"?a, L L 8 L Yi-n ]1u,*t+an21r L L J L Emi"1 4-"a L L 9 L )ruman 5ap-t1 L L > L St1'an 4+1i2 L /;;;;/;;;;;;;;;;;;;;;;;;;/ > r-+s in s1t (0.00 s1,)

8fter the script was successfully run, we see a new author in the .riters table.

Writing images
)ome people prefer to put their images into the database, some prefer to eep them on the file system for their applications. Technical difficulties arise when we wor with millions of 7:@

images. Images are binary data. !y)b' database has a special data type to store binary data called B0"B A/inary 'arge 2bjectB.
m&sB"> 5RE7)E )7BYE Ima21s(I. IN) NRI\7RY ZEY 7U)O_IN5RE\EN)< Eata \EEIU\BYOB)V _u1r& OZ< 0 r-+s a''1,t1. (0.0> s1,)

<or this e%ample, we create a new table called Images.


#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in 'in ! ]i"1.-p1n((+-man.Dp2( < (rb() im2 ! 'in.r1a. r1s,u1 S&st1m5a""Err-r !> 1 puts 1 1nsur1 'in.,"-s1 i' 'in 1n. b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC pst ! ,-n.pr1par1((INSER) IN)O Ima21s SE) Eata!CRsC( R im2.unpa,H(CAQC)) pst.101,ut1 r1s,u1 \&sB"::Err-r !> 1 puts 1 1nsur1 ,-n.,"-s1 i' ,-n pst.,"-s1 i' pst 1n.

In the above script, we read a jpg image and insert it into the Images table.
'in ! ]i"1.-p1n((+-man.Dp2( < (rb() im2 ! 'in.r1a.

.e open and read an image. The r1a. method returns the data as string.
pst ! ,-n.pr1par1((INSER) IN)O Ima21s SE) Eata!CRsC( R im2.unpa,H(CAQC))

This string data is placed into the prepared statement. /efore doing so, it is decoded using the unpa,H method of the Ruby string object. Lecoding is necessary, because the image object has many special characters which cannot be processed normally.

7:$

Rea#ing images
In the previous e%ample, we have inserted an image into the database table. 3ow we are going to read the image bac from the table.
#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC rs ! ,-n.Bu1r& (SEYE5) Eata ]RO\ Ima21s YI\I) 1( ' ! ]i"1.n1+ (+-man6.Dp2(< (+b( '.+rit1 rs.'1t,*_r-+.pa,H CAQC r1s,u1 \&sB"::Err-r< S&st1m5a""Err-r !> 1 puts 1 1nsur1 ,-n.,"-s1 i' ,-n '.,"-s1 i' ' 1n.

.e read one image from the Images table.


rs ! ,-n.Bu1r& (SEYE5) Eata ]RO\ Ima21s YI\I) 1(

.e select one record from the table.


' ! ]i"1.n1+ (+-man6.Dp2(< (+b(

.e create a writable binary file.


'.+rit1 rs.'1t,*_r-+.pa,H CAQC

.e fetch the data from the previous )b' statement and write it to the file. The '1t,*_r-+ method returns an array object. /efore the data is written to the file, it is put bac into the original format with the pa,H method of the array. <or both operations, decoding and reversing, we use the same directive, E=PE. It stands for he% string. 3ow we should have an image called woman7.jpg in our current directory. .e can chec if it is the same image, that we have inserted into the table.

-ransaction support
8 transa,ti-n is an atomic unit of database operations against the data in one or more databases. The effects of all the )b' statements in a transaction can be either all committed to the database or all rolled bac . /y default, !y)b' runs in the autocommit mode. In this mode, all changes to the tables are immediately effective. To prevent this, we have to turn off the autocommit mode. 8fter disabling autocommit, changes to transaction-aware tables are not permanent immediately.

7:G

To store the changes, we must call the 5O\\I) statement or ROYYB75Z to revert them. The Ruby !y)b' has convenience methods for these )b' statements, ,-mmit and r-""ba,H. The !y)b' database has different types of storage engines. The most common are the !yI)8! and the InnoL/ engines. There is a trade-off between data security and database speed. The !yI)8! tables are faster to process and they do not support transactions. The ,-mmit and r-""ba,H methods are not implemented. They do nothing. 2n the other hand, the InnoL/ tables are more safe against the data loss. They support transactions. They are slower to process.
m&sB"> SEYE5) )7BYE_N7\E< EN=INE ]RO\ in'-rmati-n_s,*1ma.)7BYES ;> +*1r1 )7BYE_S5AE\7 ! Cm&.bC 7NE )7BYE_N7\E!CWrit1rsCV /;;;;;;;;;;;;/;;;;;;;;/ L )7BYE_N7\E L EN=INE L /;;;;;;;;;;;;/;;;;;;;;/ L Writ1rs L Inn-EB L /;;;;;;;;;;;;/;;;;;;;;/ 1 r-+ in s1t (0.00 s1,)

The engine of the .riters table is InnoL/, which supports transactions.


#$%usr%bin%rub& r1Buir1 Cm&sB"C b12in ,-n ! \&sB".n1+ C"-,a"*-stC< Cus1r16C< C8JH"BQC< Cm&.bC ,-n.aut-,-mmit 'a"s1 pst ! ,-n.pr1par1 (UNE7)E Writ1rs SE) Nam1 ! U WAERE I. ! U( pst.101,ut1 (Y1- )-"st-&(< (1( pst.101,ut1 (B-ris Nast1rnaH(< (6( pst.101,ut1 (Y1-ni. Y1-n-:( ,-n.,-mmit r1s,u1 \&sB"::Err-r !> 1 puts 1 ,-n.r-""ba,H 1nsur1 pst.,"-s1 i' pst ,-n.,"-s1 i' ,-n 1n.

In this script, we try to update three rows.


,-n.aut-,-mmit 'a"s1

The autocommit mode is disabled.


pst ! ,-n.pr1par1 (UNE7)E Writ1rs SE) Nam1 ! U WAERE I. ! U( pst.101,ut1 (Y1- )-"st-&(< (1( pst.101,ut1 (B-ris Nast1rnaH(< (6( pst.101,ut1 (Y1-ni. Y1-n-:(

7:H

.e e%ecute three UNE7)E statements. The last one is incorrect. The second parameter is missing.
,-n.,-mmit

If all is 2M, changes are committed to the table.


r1s,u1 \&sB"::Err-r !> 1 puts 1 ,-n.r-""ba,H

In case of an error, changes are rolled bac .


$ .%up.at1.rb 101,ut1: param_,-unt(6) $! numb1r -' ar2um1nt(1) m&sB"> SEYE5) Q ]RO\ Writ1rsV /;;;;/;;;;;;;;;;;;;;;;;;;/ L I. L Nam1 L /;;;;/;;;;;;;;;;;;;;;;;;;/ L 1 L 3a,H Y-n.-n L L 6 L A-n-r1 .1 Ba"?a, L L 8 L Yi-n ]1u,*t+an21r L L J L Emi"1 4-"a L L 9 L )ruman 5ap-t1 L L > L St1'an 4+1i2 L /;;;;/;;;;;;;;;;;;;;;;;;;/ > r-+s in s1t (0.00 s1,)

Running the script gives an error. =owever, the transaction was rolled bac and the first two rows were not changed. This was !y)b' Ruby tutorial.

7:>

You might also like