Anda di halaman 1dari 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 Yukihiro Matsumoto. Ruby first appeared in 1995. 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, expressions, collections, control structures and other core features. It also describes some more advanced concepts like object-oriented programming and regular expressions. It is not a complete coverage of the language. The tutorial was created on Ubuntu Linux.

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 1995. Ruby supports various programming paradigms. This includes object orientation, reflection, imperative and reflective programming. Ruby language was influenced primarily by Perl, Smalltalk, Eiffel, and Lisp. Unlike languages like Java, C# or C, Ruby has no official specification. Instead the original C implementation of the Ruby language serves as a de facto reference. There are other implementations of the Ruby language like JRuby, IronRuby or MacRuby. 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 10th place. Ruby on 1

Rails, a very popular web application framework is the first killer application created in Ruby.

Interactive interpreter
We 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. Larger code examples are to be put in Ruby scripts.
$ irb irb(main):001:0> puts RUBY_VERSION 1.8.7 => nil

This is an example of the Ruby interactive session. We print the value of a special RUBY_VERSION constant to the console. It is set to the version of the current Ruby in use.

Ruby scripts
We will have our first simple example of a Ruby script.
#!/usr/bin/ruby # first.rb puts "This is Ruby"

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


#!/usr/bin/ruby

Every script in the UNIX starts with a shebang. The shebang is the first two characters in the script: #!. The shebang is followed by the path to the interpreter, which will execute our script. The /usr/bin/ is the most common location for the Ruby interpreter. It could also be located in /usr/local/bin/ or elsewhere.
# first.rb

Comments in Ruby are preceded by a # character.


puts "This is Ruby"

The puts method prints a string to the console.


$ which ruby /usr/bin/ruby

The path to the Ruby interpreter can be found using the which command.
$ chmod +x first.rb $ ./first.rb This is Ruby

We make the script executable with the chmod command. And execute it.

Sources
The following sources were used to create this tutorial:

ruby-lang.org ruby-doc.org Ruby article on wikipedia.org ruby.runpaint.org

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

Ruby lexical structure


Computer languages, like human languages, have a lexical structure. A source code of a Ruby program consists of tokens. Tokens are atomic code elements. In Ruby language we have various lexical structures, such as comments, variables, literals, white spaces, operators, delimiters and keywords.

Comments
Comments are used by humans to clarify the source code. There are two types of comments in Ruby. Single-line and multi-line comments. Single-line comments begin with the # character. Multi-line comments are put between the =begin and =end tokens.
#!/usr/bin/ruby =begin comments.rb author Jan Bodnar ZetCode 2011 =end # prints message to the terminal puts "Comments example"

An example showing both types of comments. Comments are ignored by the Ruby interpreter.
=begin comments.rb author Jan Bodnar ZetCode 2011 =end

This is an example of a multi-line comment. The two tokens must start at the beginning of the line.

White space
White space in Ruby is used to separate tokens and terminate statements in the source file. It is also used to improve readability of the source code.
if true then puts "A message" end

White spaces are required in some places. For example between the if keyword and the true keyword. Or between the puts method and the actual string. In other places, it is forbidden. It cannot be present in variable identifiers or language keywords.
a=1 b = 2 c = 3

The amount of space put between tokens is irrelevant for the Ruby interpreter. However, it is important to have one style throughout the project.
#!/usr/bin/ruby x = 5 + 3 puts x x = 5 puts x x = 5 + puts x 3 + 3

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


x = 5 + 3

In the first case, we have one statement. The sum of the addition is assigned to the x variable. The variable holds 8.
x = 5 + 3

Now, there are two statements. The first statement is terminated with a newline. The x variable is 5. There is another statement, +3, which has no effect.
x = 5 + 3

Finally, we have one statement. The newline is preceded with a + binary operator, so the interpreter expects another value. It looks on the second line. In this case, it takes both lines as one statement. The x variable is 8.
$ ./whitespace.rb

8 5 8

Output.

Variables
A variable is an identifier, which holds a value. In programming we say, that we assign a value to a variable. Technically speaking, 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. Variables can be assigned different values over time. Variable names in Ruby are created from alfanumeric characters and underscore (_) character. A variable cannot begin with a number. The interpreter can easier distinguish between a literal number and a variable. Variable names cannot begin with a capital letter. If an identifier begins with a capital letter, it is considered to be a constant in Ruby.
Value value2 company_name

These are valid variable names.


12Val exx$ first-name

These are examples of invalid variable names. Variable names may be preceded by two special characters, $ and @. They are used to create a specific variable scope. The variables are case sensitive. This means, that price, and pRice are two different identifiers.
#!/usr/bin/ruby number = 10 numBER = 11 puts number, numBER

In our script, we assign two numeric values to two identifiers. number and numBER are two different variables.
$ ./case.rb 10 11

This is the output of the script.

Constants
Constants are value holders, which hold only one value over time. An 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. Unlike 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 existing constant.
#!/usr/bin/ruby Name = "Robert" AGE = 23 Name = "Juliet"

In the above example, we create two constants. One of the constants is redefined later.
Name = "Robert" AGE = 23

Two constants are created. When the identifier's name begins with an uppercase letter, than we have a constant in Ruby. By convention, constants are usually written in upperacse letters.
Name = "Juliet"

We redefine a constant. Which issues a warning.


$ ./constants.rb ./constants.rb:6: warning: already initialized constant Name

Running the example.

A literal
A literal is a textual representation of a particular value of a type. Literal 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.
age = 29 nationality = "Hungarian"

Here we assign two literals to variables. Number 29 and string "Hungarian" are literals.
#!/usr/bin/ruby require 'date' sng = true name = "James" job = nil weight = 68.5 born = Date.parse("November 12, 1986")

puts "His name is #{name}" if sng == true puts "He is single" else puts "He is in a relationship" end puts "His job is #{job}" puts "He weighs #{weight} kilograms" puts "He was born in #{born}"

In the above example, 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. 68.5 is a floating point literal. Finally, the November 12, 1987 is a date literal.
$ ./literals.rb His name is James He is single His job is He weighs 68.5 kilograms He was born in 1986-11-12

This is the output of the literals.rb script.

Blocks
Ruby statements are often organized into blocks of code. A code block can be delimited using { } characters or do, end keywords.
#!/usr/bin/ruby puts [2, -1, -4, 0].delete_if { |x| x < 0 } [1, 2, 3].each do |e| puts e end

In the example, we show two code blocks. Flow control of Ruby code is often done with the if keyword. The keyword is followed by a block of code. In this case a block of code is delimited by then, end keywords, where the first keyword is optional.
#!/usr/bin/ruby if true then puts "Ruby language" puts "Ruby script" end

In the above example, we have a simple block of code. It has two statements. The block is delimited by then, end keywords. The then keyword can be omitted.

Sigils
Sigils $, @ are special characters that denote a scope in a variable. The $ is used for global variables, @ for instance variables and @@ for class variables.
$car_name = "Peugeot" @sea_name = "Black sea" @@species = "Cat"

Sigils are always placed at the beginning of the variable identifier.

Operators
An operator is a symbol used to perform an action on some value. (answers.com)
! << == < += and + >> === <= *= or & = != ~ | %= * <=> .. && ^ /= ** >= ... || -= / > not %

**= ?:

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

Delimiters
A delimiter is a sequence of one or more characters used to specify the boundary between separate, independent regions in plain text or other data stream. (wikipedia)
( ) [ , ; ' #!/usr/bin/ruby ] " { | } |

name = "Jane" occupation = 'Student' numbers = [ 2, 3, 5, 3, 6, 2 ] puts name; puts occupation puts numbers[2] numbers.each { |i| puts i } puts ( 2 + 3 ) * 5

In the above example, we show the usage of various Ruby delimiters.


name = "Jane" occupation = 'Student'

Single and double quotes are used to delimit a string in Ruby.


numbers = [ 2, 3, 5, 3, 6, 2 ]

The square brackets are used to set boundaries for an array. The commas are used to separate items in the array. 8

puts name; puts occupation

The semicolon is used in Ruby to separate two statements in a Ruby source code.
puts numbers[2]

Delimiters can be used in different contexts. Here the square brackets are used to access an item in the array.
numbers.each { |i| puts i }

Curly brackets are used to define a block of code. Pipes are used to define an element, which is filled with a current array item for each loop cycle.
puts ( 2 + 3 ) * 5

Parentheses can be used to alter the evaluation of an expression.

Keywords
A keyword is a reserved word in the Ruby programming language. Keywords are used to perform a specific task in the computer program. For example, print a value to the console, do repetitive tasks or perform logical operations. A programmer cannot use a keyword as an ordinary variable.
alias class END in redo then while and def end module rescue true yield BEGIN defined? ensure next retry undef begin do false nil return unless break else for not self until case elsif if or super when

This is a list of Ruby keywords. This was the Ruby lexical structure.

Basics
In this part of the Ruby tutorial, we will cover basic programming concepts of the Ruby language. We introduce the very basic programs. We will work with variables, constants and basic data types. We will read and write to the console; we will mention variable interpolation. We start with a very simple code example.
#!/usr/bin/ruby puts "This is Ruby"

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

#!/usr/bin/ruby

This is a path to the Ruby interpreter, which will execute the script.
puts "This is Ruby"

The puts is a Ruby keyword, which prints its argument to the terminal. In our case the argument is a string message, delimeted by double qoutes.
$ ./first.rb This is Ruby

Executing the script gives the above output.

We can read values from the terminal. (Terminal and console are synonyms)
#!/usr/bin/ruby print "What is your name? " name = gets puts "Hello #{name}"

The second program will read a value from a console and print it.
print "What is your name? "

The print keyword prints a message to the console. The difference between the print and puts keywords is that the print keyword does not start a new line. The puts keyword automatically starts a new line.
name = gets

Here we read an input from the user and store it in the name variable. The gets 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 "Hello #{name}"

In this code line, we perform variable interpolation. Variable interpolation is replacing variables with their values inside string literals. Another names for variable interpolation are: variable substitution and variable expansion.
$ ./name.rb What is your name? Jan Hello Jan

This is the output of the second program.

10

Ruby code can be run from the command line. This is inspired by Perl one-liners, where small fragments of code are run to do some petit tasks.
$ ruby -e "puts RUBY_VERSION" 1.9.3

The -e option tells Ruby to execute Ruby code specified on the line and not to search for a Ruby file name. Our example prints the version of the Ruby interpreter to the terminal.

Ruby interpreter has a -c option which checks the syntax of the code. If this option is used, the code is not executed. If there is no syntax error, Ruby will print "Syntax OK" to the standard output.
#!/usr/bin/ruby class Being end m = Test.new p m

In the above example, there is a syntax error. If we put class and end keywords on one line, we must also use the semicolon ; character.
$ ruby -c syntax_check.rb syntax_check.rb:3: syntax error, unexpected keyword_end, expecting '<' or ';' or '\n' syntax_check.rb:6: syntax error, unexpected $end, expecting keyword_end

The syntax error was found. If we put a semicolon after the Being class, the error message will disappear.

Command line arguments


Ruby programs can receive command line arguments. They follow the name of the program, when we run it.
#!/usr/bin/ruby puts ARGV

Command line arguments specified after the file name are available to a Ruby program in the global array named ARGV.
puts ARGV

Here we print all the command line arguments to the terminal.


$ ./args.rb 1 2 3 1 2 3

11

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

In the following example, we wil print all arguments and also the script name.
#!/usr/bin/ruby puts $0 puts $*

The $0 global variable contains the name of the script being executed. Global variables in Ruby begin with the $ character. The $* is another global variable. It is a synonym for the ARGV variable. It contains command line arguments given for the current script.
$ ./args2.rb Ruby Python Perl ./args2.rb Ruby Python Perl

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

Variables and constants


A variable is a place to store data. A variable has a name and a data type. Data types are different types of values. Integers, strings and floating point numbers are examples of data types. Ruby is a dynamic language. This means that we do not have to (and cannot) declare a variable to be of a certain data type. Instead, the Ruby interpreter determines the data type at the moment of the assignment. Moreover, a variable can contain different values and also different types of values over time. This differs from languages that are strongly types, like Java, C or Pascal. Unlike variables, constants (should) retain their values. Once initialized, 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/ruby city = "New York" name = "Paul"; age = 35 nationality = "American" puts puts puts puts city name age nationality

city = "London" puts city

In the above example, we work with four variables.


city = "New York"

12

We assign a string value to the city variable. The variable is dynamically created.
name = "Paul"; age = 35

We create two more variables. We can put two statements into one line. For readability, however, each statement should be on a separate line.
puts puts puts puts city name age nationality

We print the values of the variables to the terminal.


city = "London"

We assign a new value to the city variable.


$ ./variables.rb New York Paul 35 American London

Output of the example.

Constants As we already said, constants store one value over the time. Unlike in other languages, this rule is however not enforced in Ruby.
#!/usr/bin/ruby WIDTH = 100 HEIGHT = 150 var = 40 puts var var = 50 puts var puts WIDTH WIDTH = 110 puts WIDTH

In this example, we declare two constants and one variable.


WIDTH = 100 HEIGHT = 150

Constants in ruby begin with capital letter. It is a common practice to write all characters in uppercase letters.
var = 40

13

puts var var = 50

We declare and initialize a variable. Later, we assign a new value to the variable. It is legal.
WIDTH = 110

We assign a new value to a constant. Constants should not be modified, once they are created. Otherwise it has no meaning to create a constant. The Ruby interpreter will issue a warning.
$ ./constants.rb 40 50 100 ./constants.rb:13: warning: already initialized constant WIDTH 110

Output of the script.

Variable interpolation
Variable interpolation is replacing variables with their values inside string literals. Other names for variable interpolation are variable substitution and variable expansion.
#!/usr/bin/ruby age = 34 name = "William" puts "#{name} is #{age} years old"

In Ruby, strings are immutable. We cannot modify an existing string. Variable interpolation happens during string creation.
age = 34 name = "William"

Here we declare two variables.


puts "#{name} is #{age} years old"

The string message has double quotes as its boundaries. When we put a variable name between the #{ and } characters, the variable is interpolated: that is, replaced with its value.
$ ./interpolation.rb William is 34 years old

Output. This chapter covered some basics of the Ruby language.

14

Variables in Ruby
In this part of the Ruby tutorial, we will examine variables in more detail. A variable is a place to store data. Each variable is given a unique name. There are some naming conventions which apply to variable names. Variables hold objects. More precisely, they refer to a specific object located in computer memory. Each 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. Unlike strongly typed languages like Java, C or Pascal, 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. Variables in Ruby can contain different values and different types of values over time.
#!/usr/bin/ruby i = 5 puts i i = 7 puts i

The term variable comes from the fact that variables, unlike constants, can take different values over time. In the example above there is a variable called i. First it is assigned a value 5, later a different value 7.

Naming conventions
Ruby, like any other programming language, has some naming conventions for variable indentifiers. Ruby is a case sensitive language. It means that age and Age are two different variable names. Most languages are case sensitive. BASIC is an exception; it is a case insensitive language. While we can create different names by changing the case of the characters, this practice is not recommended.
#!/usr/bin/ruby i p I p = 5 i = 7 I

The code example defines two variables. I and i. They hold different values.
./case.rb 5 7

Output of the case.rb example.

15

Variable names in Ruby can be created from alpfanumeric characters and the underscore (_) character. A variable cannot begin with a number. This makes it easier for the interpreter to distinguish a literal number from a variable. Variable 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/ruby name = "Jane" placeOfBirth = "Bratislava" placeOfBirth = "Kosice" favorite_season = "autumn" n1 = 2 n2 = 4 n3 = 7 p name, placeOfBirth, favorite_season p n1, n2, n3

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

Variable names should be meaningful. It is a good programming practice to choose descriptive names for variables. The programs are more readable then.
#!/usr/bin/ruby name = "Jane" place_of_birth = "Bratislava" occupation = "student" i = 5 while i > 0 do puts name i -= 1 end

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

Sigils
Variable identifiers can start with special characters also called sigils. A sigil is a symbol attached to an identifier. Variable sigils in Ruby denote variable scope. This is in contrast to Perl, where sigils denote data type. The Ruby variable sigils are $ and @.
#!/usr/bin/ruby tree_name $car_name @sea_name @@species = = = = "pine" "Peugeot" "Black sea" "Cat"

p local_variables p global_variables.include? :$car_name

16

p self.instance_variables p Object.class_variables

We have four variables with different scopes. A scope is the range in which a variable can be referenced. We use special built-in methods to determine the scope of the variables.
tree_name = "pine"

A variable without a sigil is a local variable. A local variable is valid only locally: e.g., inside a method, block or a module.
$car_name = "Peugeot"

Global variables start with $ character. They are valid everywhere. The use of global variables should be limited in programs.
@sea_name = "Black sea"

A variable name starting with a @ sigil is an instance variable. This variable is valid inside an object.
@@species = "Cat"

Finally we have a class variable. This variable is valid for all instances of a specific class.
p local_variables

The local_variables gives an array of all local variables defined in a specific context. Our context is Ruby toplevel.
p global_variables.include? :$car_name

Similarly, the global_variables produces an array of globals. We do not print all globals to the terminal, because there are many of them. Each Ruby script starts with a bunch of predefined variables. Instead of that, we call the include? method of the array to check if our global is defined in the array. Also note that we are referencing variables with their symbols. (Symbols start with a colon character.)
p self.instance_variables

The self pseudo variable points to the receiver of the instance_variables method. The receiver in our case is the main, the Ruby toplevel execution area.
p Object.class_variables

Finally we have an array of class variables. The main is an instance of the Object class.
$ ./sigils.rb [:tree_name] true [:@sea_name] [:@@species]

17

Output of the example. We see symbolic names of the variables.

Local variables
Local variables are variables that are valid within a local area of a Ruby source code. This area is also referred to as local scope. Local variables exist within the definition of a Ruby module, method, class.
#!/usr/bin/ruby def method1 x = 5 p x end method1 p x

We have a method called method1, which has one variable. The variable is local. This means that it is valid only within the method definition. We can refer to the x variable only between the method name and the end keyword.
def method1 x = 5 p x end

This is the definition of the method1 method. Inside the method, we create a local x variable. We print the value of the variable to the terminal.
method1

The method is called.


p x

We try to refer to a local variable outside the definition of the method. This leads to a NameError. The Ruby interpreter cannot find such identifier.
$ ./locals.rb 5 ./locals.rb:11:in `<main>': undefined local variable or method `x' for main:Object (NameError)

Running the example gives the above output.

The following example is a slight modification of a previous example.


#!/usr/bin/ruby x = 5

18

def method1 x = 10 p x end method1 p x

We have two x variables. One is defined inside the method1 and the other one is defined outside. They are two distinct local variables. They do not clash with each other.
x = 5

We have created a local x variable, which holds value 5. The variable is valid in the local scope of the main execution area. It is not valid inside the method1.
def method1 x = 10 p x end

Inside the definition of the method1 a new local variable x is defined. It has value 10. It exists in the body of the method1 method. After the end keyword it ceases to exist.
$ ./locals2.rb 10 5

Output.

If a method takes parameters, a local variable is created for each of these parameters.
#!/usr/bin/ruby def rectangle_area a, b puts local_variables return a * b end puts rectangle_area 5, 6

We have a method definition, which takes two values. The method returns the area of a rectangle.
def rectangle_area a, b puts local_variables return a * b end

The rectangle_area method takes 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. We call the local_variables method to see what local variables we have in the method. 19

puts rectangle_area 5, 6

Here we pass two values to the method rectangle_area. The values will be assigned to two local variables, created inside the method.
$ ./parameters.rb a b 30

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

A method may be defined inside another method. The inner methods have their own local variables.
#!/usr/bin/ruby def method1 def method2 def method3 m5, m6 = 3 puts "Level 3" puts local_variables end m3, m4 = 3 puts "Level 2" puts local_variables method3 end m1, m2 = 3 puts "Level 1" puts local_variables method2 end method1

In this Ruby script, we create three methods. The method2 and method3 are inner methods. The method2 is defined inside the method1 and the method3 is defined inside method2. Each method's local variables are only accessible in the method in which they were defined.
$ ./lms.rb Level 1 m1 m2 Level 2 m3 m4 Level 3 m5

20

m6

From the output we can see that method1 has two local variables, m1 and m2. The inner method2 has local variables m3, m4. The method3, the innermost method, has local variables m5, m6.

The last example of this section will present several demonstrations of a local scope.
module ModuleM m1, m2 = 4 puts "Inside module" puts local_variables

end

def method1 v, w = 3 puts "Inside method" puts local_variables end class Some x, y = 2 puts "Inside class" puts local_variables end method1 t1, t2 = 7 puts "Inside toplevel" puts local_variables

In the code example, we create local variables inside a module, method, class and toplevel. The local_variables is a method of the Kernel module that returns all current local variables.
module ModuleM m1, m2 = 4 puts "Inside module" puts local_variables end

A module is a collection of methods and constants. We create two local variables m1 and m2.
def method1 v, w = 3 puts "Inside method" puts local_variables end

Two local variables, v and w, are created in method1. 21

class Some x, y = 2 puts "Inside class" puts local_variables end

The x, y local variables are created inside the definition of the Some class.
t1, t2 = 7

Finally, two local variables that belong to the Ruby toplevel's local scope are created.
$ ./locals3.rb Inside module m1 m2 Inside class x y Inside method v w Inside toplevel t1 t2

The output shows local variables for each local scope.

Global variables
Global variables are valid everywhere in the script. They start with a $ sigil in Ruby. The use of global variables is discouraged. Global variables easily lead to many programming errors. Global 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/ruby $gb = 6 module ModuleM puts "Inside module" puts $gb end def method1 puts "Inside method" puts $gb end class Some puts "Inside class" puts $gb end

22

method1 puts "Inside toplevel" puts $gb puts global_variables.include? :$gb

In the example we have a global variable $gb. We show that the variable can be referenced in a module, method, class and a toplevel. The global variable $gb is valid in all these entities.
$gb = 6

A global variable $gb is created; it has value 6.


module ModuleM puts "Inside module" puts $gb end

Inside a module's definition we print the global variable's value.


def method1 puts "Inside method" puts $gb end

Inside the defition of a method we print the value of the global variable.
class Some puts "Inside class" puts $gb end

Inside the defition of a class we print the value of the global variable.
puts $gb puts global_variables.include? :$gb

Finally, in the toplevel execution area we print the global variable's value and whether the variable is in the array produced by the global_variables method.
$ ./globals.rb Inside module 6 Inside class 6 Inside method 6 Inside toplevel 6 true

The output of the example confirms that the global variable is accessible everywhere.

23

When 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/ruby p $LOAD_PATH p $:

The script shows a $LOAD_PATH global variable. The variable lists directories which are searched by load and require methods. The $: is a short synonym for the $LOAD_PATH name. More global variables will be presented in the Predefined variables section of this chapter.

Instance, class variables


In this section we will briefly cover instance and class variables. They will be described in Object-oriented programming chapter in more detail. Instance variables are variables that belong to a particular object instance. Each object has its own object variables. Instance variables start with a @ sigil. Class variables belong to a specific class. All objects created from a particular class share class variables. Class variables start with @@ characters.
#!/usr/bin/ruby class Being @@is = true def initialize nm @name = nm end def to_s "This is #{@name}" end def does_exist? @@is end end b1 = Being.new "Being 1" b2 = Being.new "Being 2" b3 = Being.new "Being 3" p b1, b2, b3 p b1.does_exist? p b2.does_exist? p b3.does_exist?

We create a custom Being class. The Being class has one class and one instance variable.

24

class Being @@is = true

The @@is is an class variable. This variable is shared by all instances of the Being class. The logic of this example is that Being is and NotBeing is not.
def initialize nm @name = nm end

The initialize method is a constructor. The method is called when the object is created. A @name instance variable is created. This variable is specific to a concrete object.
def to_s "This is #{@name}" end

The to_s method is called, when the object is a parameter of a printing method, like p or puts. In our case, the method gives a short human readable description of the object.
def does_exist? @@is end

The does_exist? method returns the class variable.


b1 = Being.new "Being 1" b2 = Being.new "Being 2" b3 = Being.new "Being 3"

Three objects from the Being class are created. Each of the objects has a different name. The name of the object will be stored in the instance method, which is unique to each object instance. This will be used in the to_s method, which give a short description of the object.
p b1, b2, b3

The p method takes the created objects as three parameters. It calls the to_s method on each of these objects.
p b1.does_exist? p b2.does_exist? p b3.does_exist?

Finally, we call the does_exist? 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.
$ ./icvars.rb This is Being 1 This is Being 2 This is Being 3 true true

25

true

Output of the example. The first three messages are unique. 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.

Environment & command-line variables


The ENV constant gives access to environment variables. It is a Ruby hash. Each environment variable is a key to the ENV hash. The ARGV constant holds command-line argument values. They are passed by the programmer when the script is launched. The ARGV is an array that stores the arguments as strings. The $* is an alias to the ARGV. Both ENV and ARGV are global constants.
#!/usr/bin/ruby ARGV.each do |a| puts "Argument: #{a}" end

In the script we loop through the ARGV array and print each of its values.
$ ./commandline.rb 1 2 3 Argument: 1 Argument: 2 Argument: 3

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

The following example will deal with environment variables.


#!/usr/bin/ruby puts ENV['SHELL'] puts ENV['LANG'] puts ENV['TERM']

The script will print values of three environment variables to the terminal. The values depend on the OS settings of our operating system.
$ ./environment.rb /bin/bash en_US.utf8 xterm

A sample output.

26

Pseudo variables
Ruby has a few variables which are called pseudo variables. They are different from regular variables. We cannot assign values to pseudo variables. The self is the receiver of the current method. The nil is the sole instance of the NilClass. It represents the absense of a value. The true is the sole instance of the TrueClass. It represents boolean true. The false is a sole instance of FalseClass. It represents boolean false. The true and false are values of a boolean datatype. From another point of view, they are instances of specific classes. This is because everything in Ruby is an object. This looks like unnecessarily complicated. But it is the consequence of the aforementioned Ruby idiom.
#!/usr/bin/ruby p p p p p p p p self nil true false self.class nil.class true.class false.class

This is an example of pseudo variables. We print all four pseudo variables with the p method. Then we find out the class name for all of them.
p self

In this context, the self pseudo variable returns the main execution context.
$ ./pseudo.rb main nil true false Object NilClass TrueClass FalseClass

Example output.

In the second example of this section, we will further look at the self.
#!/usr/bin/ruby class Some puts self end

27

class Other puts self end puts self

As we have said, the self references the receiver of the current method. The above example shows three examples of different receivers.
class Some puts self end

The receiver is the class called Some.


class Other puts self end

Here is another receiver: a class named Other.


puts self

And the third receiver is the Ruby toplevel.


$ ./pseudoself.rb Some Other main

Example output.

The last example of the section will present other three pseudo variables.
#!/usr/bin/ruby if true puts "This message is shown" end if false puts "This message is not shown" end p $name p $age

The above example shows true, false and nil pseudo variables at work.
if true puts "This message is shown" end

The true is used in boolean expression. The message is always printed.

28

if false puts "This message is not shown" end

This message is never printed. The condition is not met. In the boolean expression we always get a negative value.
p $name p $age

If global values are referenced and have not been initialized, they contain the nil pseudo variable. It stands for the absence of a value.
$ ./pseudo2.rb This message is shown nil nil

Output of the pseudo2.rb Ruby script.

Predefined variables
Ruby has plenty of predefined global variables. This is a heritage of Perl language. Ruby was influenced strongly by Perl. They are accessible when the Ruby script starts. We have a few examples for the predefined Ruby variables.
#!/usr/bin/ruby print "Script name: ", $0, "\n" print "Command line arguments: ", $*, "\n" puts "Process number of this script: #{$$}"

Three predefined variables have been used. $0, $* and $$. The $0 stores the current script name. The $* variable stores command-line arguments. And the $$ stores the PID (process id) of the script.
$ ./predefined.rb 1 2 3 Script name: ./predefined.rb Command line arguments: ["1", "2", "3"] Process number of this script: 3122

Sample output.

The $? global variable stores the exit status of the last executed child process.
#!/usr/bin/ruby system 'echo "Ruby"' puts $? %x[exit '1'] puts $?

29

We run two external child processes and check their exit status with the $? variable.
system 'echo "Ruby"' puts $?

With the use of the system method we start a child process. It is an echo bash command, which prints a message to the terminal.
%x[exit '1'] puts $?

In the second case we execute the bash exit command with status 1. This time we use the %x operator which executes a command between two selected delimiters. We have chosen [] characters.
$ ./predefined2.rb Ruby pid 3131 exit 0 pid 3133 exit 1

The first child process terminates with status 0, the second with exit status 1.

The $; variable has the default separator of the split method of the String class.
#!/usr/bin/ruby str = "1,2,3,4,5,6,7" p str.split $; = "," p str.split

We use the $; variable to control how the string is cut with the split method. The method takes a parameter, which tells where the string should be split. If the parameter is omitted, than the value from the $; is used.
$; = "," p str.split

We specify a delimiter for the $; variable. The split method does not take a parameter, so the value of $; is used.
$ ./predefined3.rb ["1,2,3,4,5,6,7"] ["1", "2", "3", "4", "5", "6", "7"]

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 example, we show three global predefined variables that are used with regular expressions.

30

#!/usr/bin/ruby "Her name is Jane" =~ /name/ p $` p $& p $'

When we apply the =~ operator on a string, Ruby sets some variables. The $& variable has a string that matched the last last regular expression match. The $` has a string preceding $& and the $ has a string following the $&.
$ ./predefined4.rb "Her " "name" " is Jane"

Example output. In this part of the Ruby tutorial, we looked more deeply at the Ruby variables.

Objects in Ruby
In this part of the Ruby tutorial, we will briefly cover the concept of objects in Ruby language. We will learn more about objects in OOP chapter. I have written this preliminary chapter about objects because many Ruby features might be confusing to newcomers especially if they already know any other programming language. Ruby is an object-oriented programming language. This means that in Ruby programs we work with objects. From a language programmer's point of view a Ruby program is a stream of tokens. These tokens are Ruby keywords, operators, various delimiters or literals. From 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 kinds of objects: built-in objects and custom objects. Built-in objects are predefined objects that all programmers can use. They are available with the core of the Ruby language or from various libraries. Custom objects are created by application programmers for their application domains. All objects must be created before we can work with them. We often use a term object instantiation. It is a synonym for object creation. Objects consists of data and methods. Data is a static part of an object. Methods form a dynamic part of an object. Objects are modified and communicate with each other via methods.
#!/usr/bin/ruby puts "Ruby language"

We have a simple Ruby script. If we are familiar with some procedural language like Pascal or C, we might see a keyword or a function named puts and its parameter "Ruby language", which is a string.

31

Ruby is a pure object-oriented langauge and things are a bit different. The "Ruby language" is a indeed a string, which is a common data type. But it is also an object. And as with all objects, we can call its methods. This is a bit different from other languages. The puts is a method. A method is a function defined in an object. Methods do not exist on their own. In fact, the puts method is a part of the Kernel module.
#!/usr/bin/ruby Kernel.puts "Ruby language" Kernel.puts "Ruby language".size

In the above script, we have two code lines.


Kernel.puts "Ruby language"

In the first example, we were calling the puts method without the Kernel part, which may be omitted. This saves time and some typing. It is in fact a shorthand call for the Kernel.puts formal call. In C# we have Console.writeln and in Java System.println. The idea is the same. Methods must be associated with some object, or, in case of class methods, a class.
Kernel.puts "Ruby language".size

In this code line, we print the size of the "Ruby language" 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 lacks its own methods. In Ruby, a string is a full object and has its own methods. The size method is one of them. It returns the size of the string in characters.
$ ./simple2.rb Ruby language 13

Output of the code example.

In the following example, we will look at an integer number. Similarly to a string, an integer value is a Ruby object too.
#!/usr/bin/ruby puts 6.object_id puts 6.even? puts 6.zero? puts 6.class

In the example, we have an integer 6. We call a few methods on the number.


puts 6.object_id

32

The 6 is an object. The object_id is a method. The method returns an id associated to the object. Each object has an id. If we call a method on an object, we must always put a dot character between the two.
puts 6.even? puts 6.zero?

Here we call two methods on the 6 object. The even? returns true if the number is even. And the zero? method returns true, if the number is equal to zero. Note that these two methods end with a question mark. This is a Ruby convention. Methods that return a boolean value end with a question mark.
puts 6.class

The class method tells us what kind of object we are dealing with. In our case a 6 is a
Fixnum $ ./objectnumber.rb 13 true false Fixnum

Code example output.

Object creation
We have mentioned that Ruby objects must be created before we can work with them. Objects can be created implicitly or explicitly. Implicit object creation is object creation by literal notation. Explicit object creation happens with the use of the new keyword. A custom object is always created with the new keyword. Custom objects must be created from a particular class. A class is a template for an object. A class can be used to create many objects.
#!/usr/bin/ruby class Being end puts 67 puts "ZetCode" s = String.new "ZetCode" puts s # n1 = Fixnum.new 67 # puts n1 b = Being.new puts b

The code example demonstrates creation of objects in Ruby.


class Being

33

end

This is a template for our custom object called Being. The templates are created using the class keyword. The templates for custom objects are usually placed at the top of the source file or in a separate Ruby files.
puts 67 puts "ZetCode"

In these two lines we work with two objects. A 67 object of Fixnum type and "ZetCode" string of String type. 67 and "String" are what we call literals. A literal is a textual representation of a particular value of a type. These two objects are created behind the scenes by the Ruby interpreter. Some objects in Ruby are created by specifying their literals in the source code.
s = String.new "ZetCode" puts s

This is the formal way of creating a String object. It is equal to the previous, implicit creation with the string literal.
# n1 = Fixnum.new 67 # puts n1

Not all built-in objects can be created with the new method. This code does not compile. Fixnum numbers can be created only by the literal notation so far.
b = Being.new puts b

And here we create an instance of the custom object. The puts method gives us a short description of the object.
$ ./ocreation.rb 67 ZetCode ZetCode #<Being:0x9944d9c>

Output of the example.

We will continue with some formal object creations.


#!/usr/bin/ruby s1 = String.new "Ruby" puts s1.size puts s1.downcase a1 = Array.new a1.push 1, 2, 3 puts a1.include? 3 puts a1.empty?

34

r1 = Range.new 1, 6 puts r1.class puts r1.include? 4

In the example, we create three built-in objects and call a few of their methods.
s1 = String.new "Ruby" puts s1.size puts s1.downcase

A String object is created. We call two methods of the object. The size method returns the size of the string. The downcase method downcases the characters of the string.
a1 = Array.new a1.push 1, 2, 3 puts a1.include? 3 puts a1.empty?

Here we create an Array object and add three numbers to it. Later we call two array methods. The include? method checks if a particular value (3 in our case) is part of the array. The empty? method returns a boolean value indicating whether the array is empty.
r1 = Range.new 1, 6 puts r1.class puts r1.include? 4

An instance of the Range class is created. It contains numbers from 1 to 6. The class method returns the name of the object. The include? method checks if the number 4 is part of the range. It is in our case.
$ ./formal.rb 4 ruby true false Range true

Running the example gives this output.

Object literals
As we have already mentioned, some built-in objects can be created using object literals. The following example shows several object literals.
#!/usr/bin/ruby 4.times { puts "Ruby" } puts "Ruby".size puts "Ruby".downcase puts [1, 2, 3].include? 3 puts [1, 2, 3].empty?

35

puts :name.class puts :name.frozen? puts (1..6).class puts (1..6).include? 4

In the above example we use literal notation to create a Fixnum, Strings, Arrays, Symbols and Ranges.
4.times { puts "Ruby" }

We can immediately call a method on an integer literal. This line prints a "Ruby" string four times to the terminal.
puts "Ruby".size puts "Ruby".downcase

We call two methods on a String object created with a string literal.


puts [1, 2, 3].include? 3 puts [1, 2, 3].empty?

Here we create two Array objects using array literal notations. We check if a specific number is part of the array with the include? method. The empty? method checks if the array object is empty or not.
puts :name.class puts :name.frozen?

Two methods of the Symbol object are called. The symbol is created with a symbol literal, which starts with a colon.
puts (1..6).class puts (1..6).include? 4

Two Range objects are created using the range literal. We call two methods on those objects. The class method returns the name of the class and the include? method checks if a given number is part of the range.
$ ./literals.rb Ruby Ruby Ruby Ruby 4 ruby true false Symbol false Range true

Example output. 36

Object hierarchy
In many object-oriented languages objects form a hierarchy. Ruby has and object hierarchy too. It is a tree-like hierarchy, where we have parent objects and child objects. Objects inherit data and behaviour from their parent objects. At the top of the hierarchy there is the root object. It is called the Object. Each object in Ruby has at least one parent. In other words, every object inherits from the basic Object object. According to the official Ruby documentation, Object is the root of Ruby's class hierarchy. Its methods are available to all classes unless explicitly overridden.
#!/usr/bin/ruby puts puts puts puts puts 4.is_a? Object "Ruby".is_a? Object [2, 3].is_a? Object :name.is_a? Object (1..2).is_a? Object

In the above code example we demonstrate that all objects inherit from the root Object
puts 4.is_a? Object

We use the is_a? method to check if a number is a specific type: in other words, if it inherits from a given object type.
$ ./mother.rb true true true true true

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

The inheritance hierarchy may be quite complex even for the very basic Ruby objects.
#!/usr/bin/ruby puts 6.class puts puts puts puts puts 6.is_a? 6.is_a? 6.is_a? 6.is_a? 6.is_a? BasicObject Object Numeric Integer Fixnum

puts 6.is_a? Bignum puts 6.is_a? String

In this example we shed some light on the inheritance hierarchy of a small numerical value.
puts 6.class

37

We find out what kind of object is the number value 6. The line prints Fixnum to the console.
puts puts puts puts puts 6.is_a? 6.is_a? 6.is_a? 6.is_a? 6.is_a? BasicObject Object Numeric Integer Fixnum

All the above lines return true. Number 6 is a Fixnum. From the Ruby documentation we find out that the four other objects are parents of the Fixnum object.
puts 6.is_a? Bignum puts 6.is_a? String

The above two objects are not parents for the 6 value.
$ ./inheritance.rb Fixnum true true true true true false false

Output of the example.

We will finish this section with an example, demonstrating inheritance of custom user objects.
#!/usr/bin/ruby class Being def to_s "This is Being" end def get_id 9 end end class Living < Being def to_s "This is Living" end

end

l = Living.new puts l puts l.get_id puts l.is_a? Being

38

puts l.is_a? Object puts l.is_a? BasicObject

In the example we create two objects, Being and Living. The Living object inherits from the Being. The first is a parent object and the second is a child object.
class Being def to_s "This is Being" end def get_id 9 end

end

This is a definition of a custom Ruby object. The definition is placed between the class and end keywords. Inside the definition, we create two methods. When the puts method takes an object as a parameter, it calls its to_s method. It usually gives a string representation/description of the object.
class Living < Being def to_s "This is Living" end

end

We create a definition of the Living object. The object inherits from the Being object. The < operator is used to create inheritance relationships. The to_s method is overwritten.
l = Living.new

From the above Living object template, we create an instance of the Living object. The instance of a custom object is created with the new keyword.
puts l

The puts method calls the to_s method of the Living object. Had the to_s method not been defined in the Living class, the to_s method of the Being class would have been called.
puts l.get_id

The Living object has no get_id method defined. In such a case, the parent classes are checked, if there is such a method. In our case the Being method has such a method and it is called.
puts l.is_a? Being

The line returns true. The Living is a type of a Being; e.g. it inherits from the Being class.
puts l.is_a? Object puts l.is_a? BasicObject

39

For our Living custom object, we have not explicitly specified any relation to the Object or BasicObject 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.
$ ./custominher.rb This is Living 9 true true true

Output of the example.

Ruby toplevel
Ruby has a specific object referred to as Ruby toplevel. It is a default execution environment defined outside any other context like class or module definition. The toplevel's name is main. It is an instance of the Object type. There is a local space associated with main, where all local variables reside.
#!/usr/bin/ruby n1 = 3 n2 = 5 puts local_variables Kernel.puts self puts self.class

This is the first example describing the Ruby toplevel.


n1 = 3 n2 = 5

Here we have defined two numeric variables. These variables are local to the toplevel.
puts local_variables

Here we produce a list of all local variables. The local_variables is a method of the Kernel module, which is mixed into each Object, including the toplevel object.
Kernel.puts self

The self is a Ruby pseudo variable. It returns the current object receiver. The line prints "main" to the console. It is the name for the Ruby toplevel. The Kernel part of the Kernel.puts code can be omitted. By fully specifying the name we show that the puts method belongs to the Kernel module.
puts self.class

40

The line prints the class of the toplevel. We get the object type of the toplevel. It is the Object, which is the root of Ruby's class hierarchy.
$ ./toplevel.rb n1 n2 main Object

This is the output of the example. The n1, n2 are the local variables associated with toplevel. The main is the name given for the Ruby toplevel execution environment. Finally, Object is the type of the toplevel.

We will have another example related to the Ruby toplevel.


#!/usr/bin/ruby @name = "Jane" @age = 17 def info "#{@name} is #{@age} years old" end puts self.instance_variables puts self.private_methods.include? :info puts info

We show instance variables and methods that belong to the toplevel environment.
@name = "Jane" @age = 17

We define two instance variables. Instance variables begin with the @ character in Ruby. Instance variables belong to a specific object instance. In this case, they belong to the Ruby toplevel.
def info "#{@name} is #{@age} years old" end

This is a method definition. Each method must belong to some object. This method belongs to the toplevel object. All toplevel methods are private. Access to private methods is restricted.
puts self.instance_variables

The instance_variables method prints all instance variables of the self, which points to the Ruby toplevel in this context.
puts self.private_methods.include? :info

41

All toplevel methods are automatically private. The private_methods returns all private methods of the object. Since there are many methods, we call the include? method to check if the info method is among them. Note that we refer to the info method by its symbolic name.
$ ./toplevel2.rb @name @age true Jane is 17 years old

Example output. This chapter covered some basics of the objects in Ruby language.

Ruby data types


In this part of the Ruby tutorial, we will talk about data types. Computer programs of all sorts, including spreadsheets, text editors, calculators and chat clients, work with data. Tools to work with various data types are essential part of a modern computer language. A data type is a set of values, and the allowable operations on those values. Ruby has several data types. All data types are based on classes. The following are the data types recognized in Ruby:

Booleans Symbols Numbers Strings Arrays Hashes

In the following example, we have all important Ruby data types.


#!/usr/bin/ruby h = { :name => "Jane", :age => 17 } p p p p p p p p true.class, false.class "Ruby".class 1.class 4.5.class 3_463_456_457.class :age.class [1, 2, 3].class h.class

We print their class names. A class is a template from each object is created.
p true.class, false.class

42

The boolean values are presented by true and false objects.


p "Ruby".class

This is the string.


p 1.class p 4.5.class p 3_463_456_457.class

These are the numbers.


p :age.class

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


p [1, 2, 3].class p h.class

These are two containers, the array and the hash.


$ ./types.rb TrueClass FalseClass String Fixnum Float Bignum Symbol Array Hash

The program lists classes that belong to Ruby data types.

Boolean values
There is a duality built in our world. There is a Heaven and Earth, water and fire, jing and jang, man and woman, love and hatred. This is the 'boolean' nature of our existence. In Ruby the boolean data type can have one of the two values: true or false. Boolean is a fundamental data type: one that is very common in computer programs. Happy 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 Victoria.
#!/usr/bin/ruby # kid.rb bool = [true, false] male = bool[rand(2)]

43

if male puts "We will use name John" else puts "We will use name Victoria" end

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


bool = [true, false]

We have a bool variable. It is an array of two boolean values. An array is created with square brackets.
male = bool[rand(2)]

We use a rand() method to create a random number. The method returns either 0 or 1. The returned number is an index to the bool array.
if male puts "We will use name John" else puts "We will use name Victoria" end

Depending on the male variable, we print a message. If the male variable is set to true, we choose name John. Otherwise, we choose name Victoria. Control structures like if/else statements work with boolean values.
$ ./kid.rb We will use $ ./kid.rb We will use $ ./kid.rb We will use $ ./kid.rb We will use $ ./kid.rb We will use name Victoria name Victoria name John name John name John

Running the program several times.

Symbols
Symbols are used to represent other objects. Using symbols instead of strings may save some resources. A symbol is an instance object of a Symbol class. Symbols are generated by using an colon before an identifier, like :name. Several objects also have to_sym methods. These methods convert those objects to symbols. A Ruby symbol cannot be changed at runtime. Ruby symbols are often used as hash keys, because we do not need full capabilities of a string objects for a key.
#!/usr/bin/ruby p :name

44

p :name.class p :name.methods.size p "Jane".methods.size p p p p :name.object_id :name.object_id "name".object_id "name".object_id

In the first example, we show some basic operations with Ruby symbols.
p :name p :name.class

We print a symbol and its class to the console. The class of the symbol is Symbol.
p :name.methods.size p "Jane".methods.size

We compare the number of methods associated with instances of symbols and strings. A string has more than twice as many methods than symbol.
p p p p :name.object_id :name.object_id "name".object_id "name".object_id

Same symbols have the same id. Same strings have different ids.
$ ./symbols.rb :name Symbol 79 162 10328 10328 77344750 77344730

Sample output.

Symbols may be used as flags. Constants may be used in such situations as well. In C/C++ we would use enumerations.
#!/usr/bin/ruby light = :on if light == :on puts "The light is on" else puts "The light is off" end light = :off

45

if light == :on puts "The light is on" else puts "The light is off" end

A light is either on or off. For both states we might define symbols.


light = :on

The light is on.


if light == :on puts "The light is on" else puts "The light is off" end

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

Symbols are often used as keys in hash containers. They are more efficient that strings.
#!/usr/bin/ruby domains = {:sk => "Slovakia", :no => "Norway", :hu => "Hungary"} puts domains[:sk] puts domains[:no] puts domains[:hu]

In the script we have a domains hash. The keys in the hash are symbols.
puts domains[:sk] puts domains[:no] puts domains[:hu]

Keys are used to access values of a hash. Here we print three values of a hash.
$ ./symbols3.rb Slovakia Norway Hungary

Output of the example.

Ruby interpreter stores some refererences internally as symbols.


#!/usr/bin/ruby class Being def initialize

46

end

@is = true

def say "I am being" end end b = Being.new p b.method :say p b.instance_variable_get :@is

A Being class is defined. The class has a custom instance variable @is and a say method. These two entities are stored using symbols by Ruby.
p b.method :say

The method method looks up a receiver method with a given name in the b object. We look for a :say symbol.
p b.instance_variable_get :@is

We use instance_variable_get to check if @is is an instance variable of the b object. Internally the variable is stored as an :@is symbol.
$ ./symbols4.rb #<Method: Being#say> true

Generated output.

All symbols are stored in a symbol table. In the next example, we look at the table. The all_symbols method of a Symbol class returns an array of all symbols from the table.
#!/usr/bin/ruby def info "info method" end @v = "Ruby" @@n = "16" p Symbol.all_symbols.include? :info p Symbol.all_symbols.include? :@v p Symbol.all_symbols.include? :@@n

A method, an instance variable and a class variable are created in a Ruby script. We check if these entities are stored in a symbol table.
p Symbol.all_symbols.include? :info

We check if the :info symbol is in the symbol table. The line returns true. 47

$ ./symbols5.rb true true true

All 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 = {..., -2, -1, 0, 1, 2, ...} This set is infinite. In computer languages, integers are primitive data types. In practice, computers can only work with a subset of integer values, due to computers' having finite capacity. Integers are used to count discrete entities. We can have 3, 4, 6 humans, but we cannot have 3.33 humans. We can have 3.33 kilograms. Integers are instance objects of a Fixnum or a Bignum class in Ruby. Unlike in languages like Java or C, integers in Ruby are objects. The two classes differ in size. Fixnum numbers are integers up to a certain limit. The limite is machine dependent. Bignum values hold integers outside the range of the Fixnum. If any operation on a Fixnum exceeds its range, the value is automatically converted to a Bignum. The programmer usually does not need to care about the class type of the integers.
#!/usr/bin/ruby p p p p p p p p p -2 121 123265 -34253464356 34867367893463476 1.class 23453246.class 234532423563456346.class 2345324235632363463456456346.class

p 5 / 2 p 5.div 2

In this example, we deal with integers.


p p p p p -2 121 123265 -34253464356 34867367893463476

These are positive and negative integer values of various sizes.


p p p p 1.class 23453246.class 234532423563456346.class 2345324235632363463456456346.class

48

We print the classes of these integers. The first two integers are instances of a Fixnum class. The other two are instances of a Bignum class.
p 5 / 2 p 5.div 2

The two lines show integer division. When we divide two integers using the integer division operator/method, the result is an integer as well.
$ ./integers.rb -2 121 123265 -34253464356 34867367893463476 Fixnum Fixnum Bignum Bignum 2 2

Output of the example.

Integers can be specified in different notations in Ruby. Decimal, hexadecimal, octal and binary. Decimal numbers are used normally, as we know them. Hexadecimal numbers are preceded with 0x characters, octal with 0 character and binary with 0b characters.
#!/usr/bin/ruby puts puts puts puts 122 0x7a 0172 0b1111010

In the code example, we print decimal 122 in all these notation.


$ ./inotations.rb 122 122 122 122

Ouput of the example.

If we work with integers, we deal with discrete entities. We would use integers to count apples.
#!/usr/bin/ruby baskets = 16 apples_in_basket = 24

49

total = baskets * apples_in_basket puts "There are total of #{total} apples"

In our program, we count the total amount of apples. We work with integers.
$ ./apples.rb There are total of 384 apples

The output of the program.

Big numbers are difficult to read. If we have a number like 245342395423452, we find it difficult to read quickly. Outside computers, big numbers are separated by spaces or commas. For readability, Ruby allows integers to contain underscores. Underscores in integers are ignored by the Ruby interpreter.
#!/usr/bin/ruby p 23482345629 p 23_482_345_629 p 23482345629 == 23_482_345_629

The example demonstrates this use of underscores.


p 23482345629 == 23_482_345_629

This line shows that the two numbers are equal. It prints true.
$ ./underscore.rb 23482345629 23482345629 true

Example output.

Floating point numbers


Floating point numbers represent real numbers in computing. Real numbers measure continuous quantities like weight, height or speed. In Ruby, decimal numbers are objects of the Float or a BigDecimal class. The BigDecimal class, a Ruby core class, is part of Ruby's standard library. In addition, we can use Rational objects too. We need to understand that decimal numbers are not precise. The official Ruby documentation clearly says that float objects represent inexact real numbers.
#!/usr/bin/ruby p 15.4 p 0.3455 p -343.4563 p 12.5.class

50

p -12.5.class p (5.0 / 2).class p 5.fdiv 2 p 12.to_f

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


p 15.4 p 0.3455 p -343.4563

Here we print three decimal values. Decimal numbers have a decimal point character.
p 12.5.class p -12.5.class p (5.0 / 2).class

The above code lines show the types of the numbers. All are floats. Integer division applied on at least one Float produces a Float too.
p 5.fdiv 2 p 12.to_f

Here we create floating point values by using the floating point fdiv division method and the conversion to_f method.
$ ./decimals.rb 15.4 0.3455 -343.4563 Float Float Float 2.5 12.0

Output.

By default, a decimal number is shown with a maximum 16 numbers after the decimal point. We can control the format of floating point values with the sprintf or printf methods.
#!/usr/bin/ruby p 1/3.0 p 1.fdiv 2 puts sprintf "%.4f" % (1/3.0) puts sprintf "%.7f" % (5/3.0)

Formatting decimal numbers.


p 1/3.0 p 13.fdiv 4

51

p 1.fdiv 2

The first line prints a decimal with 16 places after the point. The second line prints two numbers after the point and the third one.
puts sprintf "%.4f" % (1/3.0) puts sprintf "%.7f" % (5/3.0)

Here we control the number of values after the decimal point using the sprintf method. There is a precision in the format specifier of the sprintf method. It is a number following the % character. The f is a conversion specifier that says we are dealing with floating point values.
$ ./formatfloat.rb 0.3333333333333333 3.25 0.5 0.3333 1.6666667

Output.

Ruby supports the use of scientific notation for floating point values. Also known as exponential notation, it is a way of writing numbers too large or small to be conveniently written in standard decimal notation.
#!/usr/bin/ruby p 1.2e-3 p 0.0012 p 1.5E-4 p 0.00015

The example shows two decimal numbers written in scientific notation.


$ ./scientific.rb 0.0012 0.0012 0.00015 0.00015

This is the output of the above program.

As we have already stated, floating point values are slightly inaccurate. For many computations, ordinary floating point numbers are sufficiently precise: e.g., if it is not that important if our weight is 60kg or 60.000023kg. For other computations, including many scientific and engineering applications, precision is paramount. Ruby has a BigDecimal in the standard library. This class provides arbitrary precision for very large or very accurate floating point numbers.

52

#!/usr/bin/ruby require 'bigdecimal' sum = 0 1000.times do sum = sum + 0.0001 end p sum sum = BigDecimal.new("0") 1000.times do sum = sum + BigDecimal.new("0.0001") end puts sum.to_s('F') puts sum.to_s('E')

In this simple example, we compare the precision of a Float compared to a BigDecimal.


require 'bigdecimal'

The BigDecimal class must be imported.


sum = 0 1000.times do sum = sum + 0.0001 end p sum

We 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 = BigDecimal.new("0") 1000.times do sum = sum + BigDecimal.new("0.0001") end

We do the same loop with the BigDecimal values.


puts sum.to_s('F') puts sum.to_s('E')

The sum is printed in floting point and engineering notation.


$ ./bigdecimal.rb 0.10000000000000184 0.1 0.1E0

53

The output shows that the computing with BigDecimal is more precise than with Floats.

Let's say a sprinter for 100m ran 9.87s. What is his speed in km/h?
#!/usr/bin/ruby distance = 0.1 time = 9.87 / 3600 speed = distance / time puts "The average speed of a sprinter is #{speed} km/h"

In this example, it is necessary to use floating point values.


distance = 0.1

100m is 0.1 km.


time = 9.87 / 3600

9.87s is 9.87/60*60 h
speed = distance / time

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


$ ./speed.rb The average speed of a sprinter is 36.4741641337386 km/h

This is the output of the speed.rb script.

Rational Numbers
Ruby supports rational numbers. A rational number is an exact number. Using rational numbers we avoid rounding errors. In Ruby, a rational number is an object of the Rational class. We can create rational numbers with a special to_r method from some objects. A rational number is any number that can be expressed as a fraction of two integers a/b , where b!=0. Since b may be equal to 1, every integer is a rational number.
#!/usr/bin/ruby puts 2.to_r puts "23".to_r puts 2.6.to_r p Rational 0 p Rational 1/5.0 p Rational 0.5

This example shows a few rational numbers.

54

puts 2.to_r

Here we convert a 2 integer to 2/1 rational number using the to_r method.
p Rational 0.5

We create a rational number with the Rational class.


$ ./rational.rb 2/1 23/1 5854679515581645/2251799813685248 (0/1) (3602879701896397/18014398509481984) (1/2)

Output of the example.

The nil value


Ruby has a special value nil. It is an absence of a value. The nil is a singleton object of a NilClass. There is only one nil; we cannot have more of it.
#!/usr/bin/ruby puts nil p nil p $val p [1, 2, 3][4] p $val1 == $val2

An example with the nil value.


puts nil p nil

We print the nil value to the console. The puts method prints an empty string; the p method prints 'nil' string.
p $val

When we refer to a global variable that was not set, we get the nil value.
p [1, 2, 3][3]

In this code line, we refer to the fourth element of a three-element array. We get nil. Many methods in Ruby return nil for invalid values.
p $val1 == $val2

55

The line returns true. This is a consequence of the fact that the nil value is a singleton object of a NilClass.
$ ./nilvalue.rb nil nil nil true

Output.

Strings
A string is a data type representing textual data in computer programs. A Ruby string is a sequence of unicode characters. A string is an instance of the String. String literals are characters enclosed in double or single qoutes. A string is a very important data type. It deserves a dedicated chapter. Here we include just a small example.
#!/usr/bin/ruby p "Ruby" p 'Python' p "Ruby".size p "Ruby".upcase p 23.to_s

In this program, we work with Ruby strings. We use the p method for printing because we see the data type on output.
p "Ruby" p 'Python'

We print two string literals to the terminal. The first literal is enclosed in double quotes, the second literal in single quotes.
p "Ruby".size p "Ruby".upcase

These two lines call two string methods. The size method returns the size of the string: 4 characters in our case. The upcase returns the string in uppercase letters.
p 23.to_s

The to_s method converts an integer to a string.


$ ./strings.rb "Ruby" "Python" 4

56

"RUBY" "23"

In the output we see strings enclosed in quotes. This is the consequence of using the p method. The print and puts methods don't do this.

Arrays and hashes


Arrays and hashes are collections of objects. They group objects into one place. Arrays are ordered collections of objects. Hashes are collections of key-value pairs. We will have a single chapter for both arrays and hashes. The following example just gives a quick look at both containers.
#!/usr/bin/ruby nums = [1, 2, 3, 4] puts "There are #{nums.size} items in the array" nums.each do |num| puts num end domains = { :de => "Germany", :sk => "Slovakia", :us => "United States", :no => "Norway" } puts domains.keys puts domains.values

This is a quick example for a Ruby array and hash.


nums = [1, 2, 3, 4] puts "There are #{nums.size} items in the array" nums.each do |num| puts num end

These lines create an array having 4 items. In the second line we count the items of the array and incorporate it in the message. Later we go through the array with the each method and print each of the elements to the console.
domains = { :de => "Germany", :sk => "Slovakia", :us => "United States", :no => "Norway" } puts domains.keys puts domains.values

Here we create a Ruby hash. Then we print its keys and values.
$ ./arrayshashes.rb There are 4 items in the array 1

57

2 3 4 de sk us no Germany Slovakia United States Norway

Example output.

Conversions
We often work with multiple data types at once. Converting one data type to another one is a common job in programming. Type conversion or typecasting refers to changing an entity of one data type into another. There are two types of conversion: implicit and explicit. Implicit type conversion, also known as coercion, is an automatic type conversion by the compiler. Ruby has only explicit conversion. Ruby has built-in conversion methods like to_i, to_s or to_f. The Kernel module has a few public methods for doing conversions, like Integer, String or Float. These methods should not be confused with Ruby classes.
#!/usr/bin/ruby p p p p p p Array(1..6) Complex 6 Float 12 Integer "34" Rational 6 String 22

Here we show the Kernel conversion methods.


$ ./convertmethods.rb [1, 2, 3, 4, 5, 6] (6+0i) 12.0 34 (6/1) "22"

Output of the example.


#!/usr/bin/ruby p "12".to_i p 12.5.to_i p nil.to_i p 12.to_f p "11".to_f p nil.to_f

58

In the above example, we show some numerical conversions. Some Ruby objects have to_i and to_f methods which convert objects to integers and floats, respectively.
p "12".to_i p 12.5.to_i p nil.to_i

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


p 12.to_f p "11".to_f p nil.to_f

These three lines convert an integer, string and nil to an object of decimal data type.
$ ./conversions.rb 12 12 0 12.0 11.0 0.0

Example output.

The second example shows some string conversions.


#!/usr/bin/ruby p p p p "12".to_i "13".to_f "12".to_r "13".to_c

p "Jane".to_sym v = "Ruby Python Tcl PHP Perl".split p v.class

In the above example we convert strings to objects of different data types.


p p p p "12".to_i "13".to_f "12".to_r "13".to_c

Here strings are converted to integer, decimal, rational and complex numbers.
p "Jane".to_sym

A string becomes a symbol.


v = "Ruby Python Tcl PHP Perl".split p v.class

59

Here we use a split method of the String class to convert a string to an array.
$ ./stringconv.rb 12 13.0 (12/1) (13+0i) :Jane Array

And this is what we get.

The next small example shows array hash conversions.


#!/usr/bin/ruby h = {:de => "Germany", :sk => "Slovakia"} p h.to_a a = [:de, "Germany", :sk, "Slovakia", :hu, "Hungary", :no, "Norway"] p Hash[*a]

In the example code, we create a hash and covert it to array. Then we create an array and convert it to a hash.
h = {:de => "Germany", :sk => "Slovakia"} p h.to_a

A hash is created and converted to an array using the to_a method.


a = [:de, "Germany", :sk, "Slovakia", :hu, "Hungary", :no, "Norway"] p Hash[*a]

An array is created and converted to a hash. The asterisk in this context is a splat operator. It is one of the Ruby idioms taken from Perl. It splits an array into a few variables.
$ ./h2a.rb [[:de, "Germany"], [:sk, "Slovakia"]] {:de=>"Germany", :sk=>"Slovakia", :hu=>"Hungary", :no=>"Norway"}

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

Strings in Ruby
In this part of the Ruby tutorial, we will work with string data in more detail. Strings are one of the most important data types in computer languages. That is why we dedicate a whole chapter to working with strings in Ruby. 60

A string is a sequence of unicode characters. It is a data type that stores a sequence of data values in which elements usually stand for characters according to a character encoding. When a string appears literally in source code, it is known as a string literal.

First example
In Ruby string literals are enclosed by single or double quotes.
#!/usr/bin/ruby # first.rb puts 'Python language' puts "Ruby language"

The example has two string literals. The first one is enclosed in single qoutes. The other one is enclosed in double quotes.
$ ./first.rb Python language Ruby language

Output.

Using quotes
What if we wanted to display quotes, for example in a direct speech? There are basically two ways to do this.
#!/usr/bin/ruby puts "There are many stars" puts "He said, \"Which one is your favourite?\"" puts 'There are many stars' puts 'He said, "Which one is your favourite?"'

We use the (\) character to escape additional quotes. Normally the double quote character is used to delimit a string literal. However, 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 quotes within quotes is to mix single and double quotes.
$ ./quotes.exe There are many stars. He said, "Which one is your favourite?"

Output.

Escape sequences
Escape sequences are special characters that have a specific meaning when used within a string literal.

61

#!/usr/bin/ruby puts "one two three four" puts "one\ntwo\nthree\nfour"

One of the most common escape sequences is the newline character \n. It is available in many programming languages. The next character after the newline will appear on the new line.
$ ./newline.rb one two three four one two three four

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

The r, b and t characters are normal alphabetical characters. When preceded with a \ character, they have a special meaning.
#!/usr/bin/ruby puts " bbb\raaa" puts "Joan\b\b\bane" puts "Towering\tinferno"

In the above example, we use three different escape characters.


puts " bbb\raaa"

The carriage return \r is a control character for end of line return to beginning of line. Before the string is printed to the console, it is first processed. The escape sequence causes the aaa characters to be placed before the bbb characters. The output is aaabbb.
puts "Joan\b\b\bane"

The \b control character is a backspace. It deletes a preceding character. The string printed to the console is 'Jane' not 'Joan'.
puts "Towering\tinferno"

Finally, the \t escape sequence places a tab space between the two words.
$ ./escapes.rb aaabbb Jane Towering

inferno

Output of the example.

The backslash character \ is a special character used to create escape sequences. When there is a need to print a backslash itself, it is preceded with another backslash. Its default meaning 62

is escaped and it is printed. The single and double quotes are used to delimit strings in Ruby. In order to print them, they are preceded by \ too.
#!/usr/bin/ruby puts "The special character \\" puts "The special character \'" puts "The special character \""

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


$ ./specials.rb The special character \ The special character ' The special character "

Output.

Accessing string elements


It is possible to access string elements in Ruby. For this we use the square brackets []. Inside the brackets, we can put strings, indexes or ranges.
#!/usr/bin/ruby msg = "Ruby language" puts msg["Ruby"] puts msg["Python"] puts msg[0] puts msg[-1] puts msg[0, 3] puts msg[0..9] puts msg[0, msg.length]

This code example shows, how we can access parts of a string.


msg = "Ruby language"

Here is the string, that we will be accessing.


puts msg["Ruby"]

In this code line we test, whether string 'Ruby' is a substring of the msg string. If it is true, then the string that we are looking for is returned.
puts msg[0]

The characters of the string can be accessed by their index. The numbers start from 0. In other words, the 0 is the index of the first character. The msg[0] returns the first character of the string, namely R.

63

puts msg[-1]

Here we access the last character of the string. The -1 stands for the last index of the string.
puts msg[0, 3]

Two indexes separated by a comma return characters starting from the first index and ending with the second index, excluded.
puts msg[0..9]

A range operator can be used as well. Here we print the first ten characters of the msg string.
puts msg[0, msg.length]

This line returns the whole string. The msg.length returns the size of the string.
$ ./access.rb Ruby R e Rub Ruby langu Ruby language

Output of the example.

Multiline strings
In many programming languages creating multiline strings requires additional effort. This is especially true in Visual Basic. In Ruby, multiline strings are created easily.
#!/usr/bin/ruby puts "I And the And I'm And I'm " hear Mariachi static on my radio tubes they glow in the dark there with her in Ensenada here in Echo Park

puts %/ Carmelita hold me tighter I think I'm sinking down And I'm all strung out on heroin On the outskirts of town/ puts <<STRING Well, I'm sittin' here playing solitaire With my pearl-handled deck The county won't give me no more methadone And they cut off your welfare check STRING

64

In the example, we have lyrics of a Carmelita song. We show three ways to print multiline strings. They can be used within double quotes. We can use a % character to build a multiline string. The character following the % also encloses the string. Finally, we can use the heredoc syntax. In this syntax, we use << followed by some string. The string encloses the multiline strings. It must also be left aligned.

Variable interpolation
Variable interpolation is replacing variables with their values inside string literals. To substitute a variable with a value, the variable name is put between #{ and } characters inside the string literal.
#!/usr/bin/ruby name = "Jane" age = 17 puts "#{name} is #{age} years old"

In this example, we substitute for two variables in the string: name and age.
$ ./interpolation.rb Jane is 17 years old

In the substitution it is possible to use expressions.


#!/usr/bin/ruby x = 5 y = 6 puts "The product of #{x} and #{y} is #{x*y}"

This is an example of the expression in the substitution.


$ ./interpolation2.rb The product of 5 and 6 is 30

Running the example.

There is another way to substitute variables in a string. It is similar to how Python 2.x supports interpolation.
#!/usr/bin/ruby name = "Jane" age = 17 message = "%s is %d years old" % [name, age] puts message

Example.

65

message = "%s is %d years old" % [name, age]

We build a string before we use it. The %s and %d are formatting characters that expect a string and a number, respectively. The values are provided in square brackets after the % character.

Concatenating strings
Concatenating strings is creating one string from multiple strings.
#!/usr/bin/ruby lang = "Ruby" + " programming" + " languge" puts lang lang = "Python" " programming" " language" puts lang lang = "Perl" << " programming" << " language" puts lang lang = "Java".concat(" programming").concat(" language") puts lang

Ruby provides multiple ways of concatenating strings.


lang = "Ruby" + " programming" + " languge"

The plus operator is the most common operator used to add strings in computer languages. Perl and PHP use the dot (.) operator to concatenate strings.
lang = "Python" " programming" " language"

Ruby automatically concatenates subsequent strings.


lang = "Perl" << " programming" << " language"

Another operator which can be used to concatenate strings is <<.


lang = "Java".concat(" programming").concat(" language")

Each string literal is in fact an object. We can call various methods on each Ruby object. On string objects, we can call the concat method, which adds two string objects. It also returns the final object, on which we can call another method. So we can place these methods in a chain.
$ ./concatenate.rb Ruby programming languge Python programming language Perl programming language Java programming language

Output.

66

Freezing strings
In Java or C#, the strings are immutable. This means, that we cannot modify an existing string. We can only create a new string out of an existing one. In Ruby, the strings are not immutable by default. String objects in Ruby have a freeze method, which makes them immutable.
#!/usr/bin/ruby msg = "Jane" msg << " is " msg << "17 years old" puts msg msg.freeze #msg << "and she is pretty"

In this example, we demonstrate that strings can be modified. However, after calling the freeze method on a string object, we cannot modify the string anymore. If we uncomment the code line, we will get 'can't modify frozen string' error message.

Comparing strings
Comparing strings is a common job in programming. We can compare two strings with a == operator or with a eql? method. They return true if the strings are equal and false if not.
#!/usr/bin/ruby puts "12" == "12" puts "17" == "9" puts "aa" == "ab" puts "Jane".eql? "Jan" puts "Jane".eql? "Jane"

In this code example, we compare some strings.


puts "12" == "12"

These two strings are equal, the line returns true.


puts "aa" == "ab"

The first two characters of both strings are equal. Next the following characters are compared. They are different so the line returns false.
puts "Jane".eql? "Jan"

67

The eql? method is used to compare two strings. Strings are objects and all have a built-in eql? method. The method takes one parameter, the string to which we are comparing our first string.
$ ./comparing.rb true false false false true

Output of the program.

Ruby has a spaceship operator <==>. The operator comes from the Perl language. Unlike the above two ways of comparing strings, which return either true or false, this operator will return 1, 0, or 1. Depending 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 1. If the left argument is less than the right argument, the operator returns 1. If the two arguments are equal, the operator returns 0. What does it mean that a character is greater than another character? Characters are ordered in tables. Each character has a position in a table. When comparing characters, we compare their positions in such a table. For example in a ASCII table, the character a comes before the character b. So comparing a <==> b returns -1, because the left argument has a lower position than b.
#!/usr/bin/ruby puts "a" <==> "b" puts "b" <==> "a" puts "a" <==> "a"

Comparing characters with a spaceship operator.


$ ./spaceship.rb -1 1 0

Output of the example.

In is possible to compare strings regardless of the case. For this Ruby has a casecmp method. The method works the same way as the spaceship operator.
#!/usr/bin/ruby puts "Jane".casecmp "Jane" puts "Jane".casecmp "jane" puts "Jane".casecmp "Jan"

Example.
puts "Jane".casecmp "Jane"

68

puts "Jane".casecmp "jane"

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

Output of the example.

Strings are objects


Ruby is an object-oriented language. Objects are basic building blocks of an OOP program. Strings are objects too. An object is a combination of data and methods. In a OOP program, objects are created and they communicate among themselves.
#!/usr/bin/ruby website = "google.com" puts website website = String.new "zetcode.com" puts website

In the example above, we show two basic ways of creating a string in Ruby.
website = "google.com"

Here a string literal is assigned to a website variable. Under the hood, the Ruby interpreter creates a string object.
website = String.new "zetcode.com"

This is the standard way of creating string objects. However, 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/ruby puts "zetcode".upcase puts "zetcode".size puts "zetcode".reverse

In this code example, we call three methods on a string literal. For people who are familiar with Java, C 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.
$ ./stringobject2.rb ZETCODE 7 edoctez

69

Output of the example.

String methods
Ruby string objects have useful methods that can be used for working with strings. We have already seen several string methods like concat or eql?.
#!/usr/bin/ruby word = "Determination" puts "The word #{word} has #{word.size} characters" puts word.include? "tion" puts word.include? "tic" puts puts word.empty? word.clear puts word.empty?

We have a string variable. Four string methods are presented.


puts "The word #{word} has #{word.size} characters"

The size method returns the number of characters in the string.


puts word.include? "tion"

The include? method determines whether a substring is present in the tested string. In this case, the code line returns true.
puts word.empty? word.clear

The empty? method checks whether the string is empty. It returns a boolean true or false. The clear method makes string empty.
$ ./basicmethods.rb The word Determination has 13 characters true false false true

Output.

In the next example, we will have methods that work with the case of the characters.
#!/usr/bin/ruby

70

ruby = "Ruby programming language" puts puts puts puts ruby.upcase ruby.downcase ruby.capitalize ruby.swapcase

Ruby has four methods for character case. The upcase method returns a copy of the string in which all characters are in uppercase. The downcase method returns a copy of the string in which all characters are in downcase. The capitalize method returns a copy of string with the first character converted to uppercase and the remainder to lowercase. Finally, the swapcase method returns a copy of the string where the uppercase letters are converted to downcase and vice versa.
$ ./rubylang.rb RUBY PROGRAMMING ruby programming Ruby programming rUBY PROGRAMMING LANGUAGE language language LANGUAGE

Output.

Next we present two Ruby string methods: start_with? and end_with?. Both methods return a boolean true or false. They determine whether a string starts or ends with a specific string, respectively.
#!/usr/bin/ruby ws1 = "zetcode.com" ws2 = "www.gnome.org" puts ws1.start_with? "www." puts ws2.start_with? "www." puts puts ws1.end_with? ".com" puts ws2.end_with? ".com"

This is an example for the aforementioned methods.


puts ws1.start_with? "www."

Here we check if a string starts with a "www." prefix. It does not, so the output to the console is a boolean false.
puts ws1.end_with? ".com"

We check whether the ws1 string variable ends with a ".com" suffix. It does, so we see a true in the console.
$ ./startend.rb false true

71

true false

Output.

In the following example, we will deal with the inspect method. The method returns a raw string, surrounded by quote marks, with special characters not interpreted. It is useful when we want to examine what characters form the string.
#!/usr/bin/ruby msg = "Jane\t17\nThomas\t23" puts msg puts msg.inspect

An example of the inspect string method.


msg = "Jane\t17\nThomas\t23"

This is a string with some special characters.


puts msg puts msg.inspect

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.
$ ./inspectmethod.rb Jane 17 Thomas 23 "Jane\t17\nThomas\t23"

Output of the example.

The chomp method returns a new string with the record separator removed from the end of the string. The default separator is the newline (\n).
#!/usr/bin/ruby print "Are you sure to download? (Yes/No) " response = gets if (response.downcase == "yes") puts "Downloaded" else puts "Download cancelled" end puts response.inspect

72

In the above script, we get an input from the user. We react to the user response.
$ ./chomp.rb Are you sure to download? (Yes/No) Yes Download cancelled "Yes\n"

The script does not work correctly. The reason becomes clear when we consider what inspect returns. The input from the user is ended with an enter key. The newline character is included in the response variable too. And "yes" does not equal to "yes\n". To correct the script, we use the chomp method. It removes the newline from the variable.
#!/usr/bin/ruby print "Are you sure to download? (Yes/No) " response = gets if (response.downcase.chomp == "yes") puts "Downloaded" else puts "Download cancelled" end puts response.inspect

This is the corrected example.


if (response.downcase.chomp == "yes")

Here we process the input before it is compared with the "yes" string. The chomp method removes the newline character.
$ ./chomp.rb Are you sure to download? (Yes/No) Yes Downloaded "Yes\n"

Now the example works correctly.

Formatting strings
Ruby has format specifiers. A format specifier determines how the string is going to look like. It begins with a % character. Format specifiers are put inside single or double quotes. The format specifier has the following fields:
%[flags][field width][precision]conversion specifier

Fields in square brackets are optional. A conversion specifier specifies how the data is going to be converted into displayable form.
#!/usr/bin/ruby

73

puts "There are %d oranges in the basket." % 12 puts "There are %d oranges and %d apples in the basket." % [12, 10]

Here is an example of some format specifiers.


puts "There are %d oranges in the basket" % 12

When we use the %d notation inside a string, we expect a number at that point. The d is a conversion specifier for decimal numbers. The number is given after the % character.
puts "There are %d oranges and %d apples in the basket" % [12, 10]

We can use multiple format specifiers inside a string. Each begins with a % character. Multiple values are placed between [] characters and separated by comma character.
$ ./formatspecifiers.rb There are 12 oranges in the basket. There are 12 oranges and 10 apples in the basket.

Output of the example.

In the following example, we will cover some basic conversion specifiers.


#!/usr/bin/ruby puts puts puts puts "There are %d apples." % 5 "I can see %i oranges." % 3 "The width of iPhone 3G is %f mm." % 62.1 "This animal is called a %s" % "rhinoceros."

We have conversion specifiers for integers, floating point numbers and strings.
puts "There are %d apples." % 5 puts "I can see %i oranges." % 3

Both d an i can be used for integers.


puts "The width of iPhone 3G is %f mm." % 62.1

The f is a conversion specifier for floating point values. By default, floats have six decimal places.
puts "This animal is called a %s" % "rhinoceros."

The s character is used for strings.


$ ./basicspecifiers.rb There are 5 apples. I can see 3 oranges. The width of iPhone 3G is 62.100000 mm. This animal is called a rhinoceros.

74

Output of the example.

Next we have a practical example of using a format specifier.


#!/usr/bin/ruby website = "zetcode.com" website.each_char do |c| print "#{c} has ASCII code %d\n" % c.ord end

In this example, we go through all characters of a string and print their ASCII values to the terminal.
website.each_char do |c| print "#{c} has ASCII code %d\n" % c.ord end

The each_char method passes each character of a website string to the block, one character per cycle, with current character stored in c variable. We get the ASCII code of the character using the ord method, which returns the ordinal of a one character string.
$ z e t c o d e . c o m ./character.rb has ASCII code has ASCII code has ASCII code has ASCII code has ASCII code has ASCII code has ASCII code has ASCII code has ASCII code has ASCII code has ASCII code 122 101 116 99 111 100 101 46 99 111 109

Output of the example.

Numbers can be displayed in various forms. The conversion specifier can be used to format numbers.
#!/usr/bin/ruby # decimal puts "%d" % 300 # hexadecimal puts "%x" % 300 # octal puts "%o" % 300 # binary puts "%b" % 300

75

# scientific puts "%e" % (5/3.0)

In the above example, we print numbers in decimal, hexadecimal, octal, binary and scientific formats.
# hexadecimal puts "%x" % 300

The x conversion specifier is used to transform a number into a hexadecimal format.


# binary puts "%b" % 300

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


$ ./various.rb 300 12c 454 100101100 1.666667e+00

Output.

Precision 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. When used with integers, it indicates the minimum number of digits to be printed. If the number has fewer digits than the precision, zeros are prefixed. The default precision for integers is 1, meaning that no zeros are filled. When used with a float number, the precision is the number of digits displayed after the decimal point. Finally, with strings, the precision is the maximum number of characters printed.
#!/usr/bin/ruby puts 'Height: %f %s' % [172.3, 'cm'] puts 'Height: %.1f %s' % [172.3, 'cm'] puts "%d" % 16 puts "%.5d" % 16 puts "%s" % "zetcode" puts "%.5s" % "zetcode"

In this example, we will work with the precision field.


puts 'Height: %f %s' % [172.3, 'cm'] puts 'Height: %.1f %s' % [172.3, 'cm']

172.3 is a floating point number. If no precision is specified, there will be 6 decimal places after a decimal point. In our case, there will be 5 zeros. The .1 in the second code line is the precision. For a floating point value, it reduces the number of decimal places to 1.

76

puts "%d" % 16 puts "%.5d" % 16

The default precision for integers is 1. In the second line, we have specified precision .5, which adds (prepends) 3 zeros to the 16 number.
puts "%s" % "zetcode" puts "%.5s" % "zetcode"

The first line prints all characters of the string. The second line prints only five of them. Two characters are dropped.
$ ./precision.rb Height: 172.300000 cm Height: 172.3 cm 16 00016 zetcode zetco

Output.

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/ruby puts puts puts puts puts puts puts puts puts puts "%d" "%d" "%d" "%d" "%d" % % % % % 1 16 165 1656 16567 % % % % % 1 16 165 1656 16567

"%10d" "%10d" "%10d" "%10d" "%10d"

In the first case, we print five numbers without specifying the field width. The width of the output is equal to the number of the characters being displayed. In the second case we have a field width of 10. Each of the 5 outputs has a minimum length of 10 characters. The numbers are right aligned.
puts "%d" % 1 puts "%d" % 16

We print two numbers. The width of the output has 1, 2 characters, respectively.
puts "%10d" % 1 puts "%10d" % 16

77

Here the length in both cases is 10 characters. The two numbers are padded with 9 and 8 spaces in the given order.
$ ./fieldwidth.rb 1 16 165 1656 16567 1 16 165 1656 16567

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

The flag qualifier modifies the format's behaviour. The # flag adds a 0b, 0, and 0x prefix to binary, octal and hexadecimal 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/ruby puts "%#b" % 231 puts "%#x" % 231 puts "%#o" % 231 puts "%.0e" % 231 puts "%#.0e" % 231 puts "%.0f" % 231 puts "%#.0f" % 231

In the code example, we use the x flag.


puts "%#b" % 231 puts "%#x" % 231 puts "%#o" % 231

The decimal 231 is printed in binary, octal, and hexadecimal formats. The # flags adds a prefix for them.
puts "%.0e" % 231 puts "%#.0e" % 231

Here, the .0 precision supresses the decimal places of a number. However, when used with a # flag, the decimal point is displayed, even though there are no decimal digits.
$ ./flags1.rb 0xe7 0b11100111 0347

78

2e+02 2.e+02 231 231.

Output.

The + flag adds a plus sign for positive decimal numbers. For binary, octal and hexadecimal negative numbers it adds a minus sign and uses an absolute value.
#!/usr/bin/ruby puts puts puts puts "%d" % 231 "%+d" % 231 "%d" % -231 "%+d" % -231

puts "%b" % -231 puts "%o" % -231 puts "%x" % -231 puts "%+b" % -231 puts "%+o" % -231 puts "%+x" % -231

An example demonstrating the + flag of the format specifier.


puts "%d" % 231 puts "%+d" % 231

Usually, positive numbers have their sign omitted. If we want to show a plus sign for positive numbers, we specify the + flag.
puts "%d" % -231 puts "%+d" % -231

The + flag has no effect on negative numbers. The output is the same.
puts "%b" % -231 puts "%o" % -231 puts "%x" % -231

Binary, octal and hexadecimal numbers have their own way to create negative numbers.
puts "%+b" % -231 puts "%+o" % -231 puts "%+x" % -231

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.
$ ./flags2.rb 231 +231

79

-231 -231 ..100011001 ..7431 ..f19 -11100111 -347 -e7

Output of the example.

Here we introduce the 0 flag and the - flag. The 0 flag causes the number to be padded with zeros instead of spaces. The - flag makes the output left aligned.
#!/usr/bin/ruby puts puts puts puts puts puts puts puts puts puts "%010d" "%010d" "%010d" "%010d" "%010d" "%-10d" "%-10d" "%-10d" "%-10d" "%-10d" % % % % % % % % % % 1 16 165 1656 16567 1 16 165 1656 16567

Example.
puts "%010d" % 1 puts "%010d" % 16

Numbers will be padded with zeros.


puts "%-10d" % 1 puts "%-10d" % 16

The number, being shorter than the field width, is aligned. And the - flag makes it left aligned.
$ ./fieldwidth2.rb 0000000001 0000000016 0000000165 0000001656 0000016567 1 16 165 1656 16567

Ouput of the example.

80

The * flag can be used for the precision and for the width. Whenever we use the * flag, we have to specify the precision or the width as an argument.
#!/usr/bin/ruby puts "%.*f" % [3, 1.1111111] puts "%0*d" % [10, 2] puts "%0*.*f" % [10, 3, 1.1111]

Example for the * flag.


puts "%.*f" % [3, 1.1111111]

Here we use the * flag for the precision. The first number, 3, is the argument for the precision. It says only three decimal digits will be displayed for the 1.1111111 float number.
puts "%0*d" % [10, 2]

In this code line, we use the * flag for the width. We have to add the width between the [] brackets. The first number is the width and the second number is the value for the conversion specifier.
puts "%0*.*f" % [10, 3, 1.1111]

The * flag can be used for both the width and the precision. We have to specify them both in the [] brackets.
$ ./flags3.rb 1.111 0000000002 000001.111

Output of the example. This part of the Ruby tutorial covered strings.

Expressions in Ruby
In this part of the Ruby tutorial, we will talk about expressions. Expressions are constructed from operands and operators. The operators of an expression indicate which operations to apply to the operands. The order of evaluation of operators in an expression is determined by the precedence and associativity of the operators. An operator is a special symbol which indicates a certain process is carried out. Operators in programming languages are taken from mathematics. Programmers work with data. The operators are used to process data. An operand is one of the inputs (arguments) of an operator. The following table shows common Ruby operators ordered by precedence (highest precedence first): 81

Category Resolution, access operators Array operators Exponentiation Not, complement, unary plus, minus Multiply, divide, modulo Addition, substraction Shift operators Bitwise and Bitwise or, logical or Relational operators Bitwise or, logical or Equality, pattern match operators Logical and Logical or Range operators Ternary Assignment operators Alternate negation Alternate logical or, and

Symbol
:: . [ ] [ ]= ** ! ~ + * / % + << >> & ^ | > >= < <= ^ | <=> == === != =~ !~ && || .. ... ?: = += -= *= **= /= %= &= |= ^= <<= >>= ||= &&= not or and

Operators on the same row of the table have the same precedence. An operator usually has one or two operands. Those operators that work with only one operand are called unary operators. Those who work with two operands are called binary operators. There is also one ternary operator (?:), which works with three operands. Certain operators may be used in different contexts. For example the + operator. From the above table we can see that it is used in different cases. It adds numbers, concatenates strings, indicates the sign of a number. We 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/ruby puts +2 puts -2

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 example, we will work with a minus sign.


#!/usr/bin/ruby a = 1

82

puts a puts -(a) puts -(-(a))

The minus sign changes the sign of a value.


$ ./sign.rb 1 -1 1

This is the output of the example.

The assignment operator


The assignment operator = assigns a value to a variable. A variable is a placeholder for a value. In mathematics, the = operator has a different meaning. In an equation, the = operator is an equality operator. The left side of the equation is equal to the right one.
x = 1 puts x # prints 1

Here we assign a number to the x variable.


x = x + 1 puts x # prints 2

The previous expression does not make sense in mathematics. But it is legal in programming. The expression adds 1 to the x variable. The right side is equal to 2 and 2 is assigned to x.
3 = x;

This code example results in syntax error. We 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. Which means, that they are always evaluated first.
#!/usr/bin/ruby class MyMath Pi = 3.1415926535 end module People Name = "People" end puts MyMath::Pi puts People::Name

83

In the first example, we present the :: 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 don't conflict with other classes by different authors.
class MyMath Pi = 3.1415926535 end module People Name = "People" end

We have a simple module and a class. Each has one constant defined.
puts MyMath::Pi puts People::Name

We use the :: operator to access constants from both.


$ ./resolution.rb 3.1415926535 People

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/ruby class Person def initialize name, age @name = name @age = age end def info "#{@name} is #{@age} years old" end end p = Person.new "Jane", 17 puts p.info puts "ZetCode".reverse

In our example, we have two objects. One user defined and one predefined. We use the dot operator to work with these objects.
p = Person.new "Jane", 17 puts p.info

In these two lines, the dot operator calls two methods: new and info. 84

puts "ZetCode".reverse

A string is a built-in object, which has a reverse method. This is being called.
$ ./memberaccess.rb Jane is 17 years old edoCteZ

This is the output of the example.

Concatenating strings
In Ruby the + operator is also used to concatenate strings. When an operator is used in different contexts differently, we say that it is overloaded.
#!/usr/bin/ruby puts "Return " + "of " + "the " + "King" puts "Return ".+"of ".+ "the ".+"King"

We join three strings together using string concatenation operator.


puts "Return " + "of " + "the " + "King"

We join four strings using + operator.


puts "Return ".+"of ".+ "the ".+"King"

Under the hood, the + operator is a Ruby method. The string literal is an object. We call a method of an object using the access (.) operator.
$ ./catstrings.rb Return of the King Return of the King

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

Increment, decrement operators


Ruby has no such operators.
x++; x = x + 1; ... y--; y = y - 1;

These are increment, decrement operators in C. If you are familiar with Java, C, C++, you know these operators. They are not available in Ruby. Python language does not have them too.

85

Arithmetic operators
The following is a table of arithmetic operators in Ruby. Symbol Name + Addition Subtraction * Multiplication / Division % Remainder ** Power In the next example, we use arithmetic operations.
#!/usr/bin/ruby a = 10 b = 11 c = 12 puts puts puts puts puts puts a c a c c c + b + c - a * b / 3 % a ** a

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

The % operator is called the remainder or the modulo operator. It finds the remainder of division of one number by another. For example, 9 % 4, 9 modulo 4 is 1, because 4 goes into 9 twice with a remainder of 1.
$ ./arithmetic.rb 33 2 110 4 2 61917364224

This is the output of the example.

Next we will show the distinction between integer and floating point division.
#!/usr/bin/ruby puts 5 / 2

86

puts 5 / 2.0 puts 5.0 / 2 puts 5.to_f / 2

In the preceding example, we divide two numbers.


puts 5 / 2

Both operands in the expression are integers. We have done integer division. The returned value of the division operation is an integer. When we divide two integers the result is an integer.
puts 5 / 2.0 puts 5.0 / 2 puts 5.to_f / 2

If one of the values is a a float (or both), we perform a floating point division. A floating point value has a decimal point. We can also call a to_f method to convert an integer to a float.
$ ./division.rb 2 2.5 2.5 2.5

Here we see the result of the division.rb program.

Ruby has other ways to perform divisions. These are available as method calls.
#!/usr/bin/ruby puts puts puts puts 5.div 2.0 5.fdiv 2 5.quo 2 5.0.quo 2.0

In the above example, we have a div, a fdiv and a quo methods.


puts 5.div 2.0

The div method always performs integer division. Even if the operands are floting point values.
puts 5.fdiv 2

The fdiv method always performs float division.


puts 5.quo 2 puts 5.0.quo 2.0

87

The quo method performs the most accurate division. It returns a float if either operand is float, otherwise rational.
$ ./otherdivision.rb 2 2.5 5/2 2.5

Boolean operators
In Ruby, we have the following logical operators. Boolean operators are also called logical. Symbol Name && logical and || logical or ! negation Boolean operators deal with truth values. Ruby has additional alternative boolean operators. These are and, or & not. They do the same except for the thing that they have a lower precedence level. This duplicity is taken from the Perl language, where there was a need for boolean operators with a lower precedence.
#!/usr/bin/ruby x = 3 y = 8 puts x == y puts y > x if y > x then puts "y is greater than x" end

Many expressions result in a boolean value. Boolean values are used in conditional statements.
puts x == y puts y > x

Relational operators always result in a boolean value. These two lines print false and true.
if y > x then puts "y is greater than x" end

The body of the if statement is executed only if the condition inside the parentheses is met. The x > y returns true, so the message "y is greater than x" is printed to the terminal.

The next example shows the logical and operator.

88

#!/usr/bin/ruby puts puts puts puts true && true true && false false && true false && false

The and operator evaluates to true only if both operands are true.
$ ./andoperator.rb true false false false

Only one of the expressions results in true.

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


#!/usr/bin/ruby puts puts puts puts true || true true || false false || true false || false

If one of the sides of the operator is true, the outcome of the operation is true.
$ ./oroperator.rb true true true false

Three expressions result in a boolean true.

The negation operator ! makes true false and false true.


#!/usr/bin/ruby puts puts puts puts !0 !1 !true !false

puts ! (4<3) puts ! "Ruby".include?("a")

The example shows the negation operator in action.


$ ./not.rb false false false

89

true true true

This is the output of the example.

The ||, and && 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 expression: when the first argument of the logical and evaluates to false, the overall value must be false; and when the first argument of logical or evaluates to true, the overall value must be true. Short circuit evaluation is used mainly to improve performance. An example may clarify this a bit more.
#!/usr/bin/ruby def one puts "Inside one" false end def two puts "Inside two" true end puts "Short circuit" if one && two puts "Pass" end puts "##############################" if two || one puts "Pass" end

We have two methods in the example. They are used as operands in boolean expressions. We will see if they are called or not.
if one && two puts "Pass" end

The one method returns false. The short circuit && does not evaluate the second method. It is not necessary. Once an operand is false, the result of the logical conclusion is always false. Only "Inside one" is only printed to the console.
puts "##############################" if two || one puts "Pass" end

90

In the second case, we use the || operator and use the two method as the first operand. In this case, "Inside two" and "Pass" 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.
$ ./shortcircuit.rb Short circuit Inside one ############################## Inside two Pass

We see the result of the shortcircuit.rb program.

Relational Operators
Relational operators are used to compare values. These operators always result in boolean value. Symbol Meaning < less than <= less than or equal to > greater than >= greater than or equal to Relational operators are also called comparison operators.
#!/usr/bin/ruby p 3 < 4 p 3 > 5 p 3 >= 3

The 3 < 4 expression returns true, since 3 is smaller than 4. The 3 > 5 expression returns false because it is not true that 3 is greater than 5.

Bitwise operators
Decimal numbers are natural to humans. Binary numbers are native to computers. Binary, octal, decimal or hexadecimal symbols are only notations of the same number. Bitwise operators work with bits of a binary number. Symbol Meaning ~ bitwise negation ^ bitwise exclusive or & bitwise and | bitwise or << left shift >> right shift

91

Bitwise operators are seldom used in higher level languages like Ruby.
#!/usr/bin/ruby puts ~ 7 puts ~ -8 puts 6 & 3 puts 3 & 6 puts 6 ^ 3 puts 3 ^ 6 puts 6 | 3 puts 3 | 6 puts 6 << 1 puts 1 << 6 puts 6 >> 1 puts 1 >> 6 # prints -8 # prints 7 # prints 2 # prints 2 # prints 5 # prints 5 # prints 7 # prints 7 # prints 12 # prints 64 # prints 3 # prints 0

In the above code example, we show all 6 operators.


puts ~ 7 puts ~ -8 # prints -8 # prints 7

The bitwise negation operator changes each 1 to 0 and 0 to 1. The operator reverts all bits of a number 7. One of the bits also determines, whether the number is negative or not. If we negate all the bits one more time, we get number 7 again.
puts 6 & 3 puts 3 & 6 # prints 2 # prints 2

The bitwise and operator performs bit-by-bit comparison between two numbers. The result for a bit position is 1 only if both corresponding bits in the operands are 1.
puts 6 ^ 3 puts 3 ^ 6 # prints 5 # prints 5

The bitwise exclusive or operator performs bit-by-bit comparison between two numbers. The result for a bit position is 1 if one or the other (but not both) of the corresponding bits in the operands is 1.
puts 6 | 3 puts 3 | 6 # prints 7 # prints 7

The bitwise or operator performs bit-by-bit comparison between two nubmers. The result for a bit position is 1 if either of the corresponding bits in the operands is 1.
puts 6 << 1 puts 1 << 6 puts 6 >> 1 puts 1 >> 6 # prints 12 # prints 64 # prints 3 # prints 0

92

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

Compound assignment operators


The compound assignment operators consist of two operators. They are shorthand operators.
#!/usr/bin/ruby a = 0 a = a + 1 a += 1 puts a b = 0 b = b - 8 b -= 8 puts b

The += and -= compound operators are one of these shorthand operators. They are less readable than the full expressions but experienced programmers often use them.
a = a + 1 a += 1

These two lines do the same; they add 1 to the a variable. Other compound operators are:
-= *= **= /= %= &= |= <<= >>=

Operator precedence
The operator precedence tells us which operators are evaluated first. The precedence level is necessary to avoid ambiguity in expressions. What is the outcome of the following expression? 28 or 40?
3 + 5 * 5

Like in mathematics, the multiplication operator has a higher precedence than addition operator. So the outcome is 28.
(3 + 5) * 5

To change the order of evaluation, we can use parentheses. Expressions inside parentheses are always evaluated first.
#!/usr/bin/ruby puts 3 + 5 * 5

93

puts (3 + 5) * 5 puts ! true | true puts ! (true | true)

In this code example, we show some common expressions. The outcome of each expression is dependent on the precedence level.
puts 3 + 5 * 5

This line prints 28. The multiplication operator has a higher precedence than addition. First the product of 5*5 is calculated. Then 3 is added.
puts ! true | true

In this case, the negation operator has a higher precedence. First, the first true value is negated to false, than the | operator combines false and true, which gives true in the end.
$ ./precedence.rb 28 40 true false

Associativity
Sometimes the precedence is not satisfactory to determine the outcome of an expression. There is another rule called associativity. The associativity of operators determines the order of evaluation of operators with the same precedence level.
9 / 3 * 3

What is the outcome of this expression? 9 or 1? The multiplication, deletion and the modulo operator are left to right associated. So the expression is evaluated this way: (9 / 3) * 3 and the result is 9. Arithmetic, boolean, relational and bitwise operators are all left to right associated. On the other hand, the assignment operator is right associated.
a = b = c = d = 0 print a, b, c, d # prints 0000

If the association was left to right, the previous expression would not be possible. The compound assignment operators are right to left associated.
j = 0 j *= 3 + 1 puts j

94

You might expect the result to be 1. But the actual result is 0, because of the associativity. The expression 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 quickly create a range of objects. Most often a range of numbers or letters. The .. range operator (two dots) creates an inclusive range. The ... operator (three dots) creates an exclusive range, where the high value of the range is excluded.
#!/usr/bin/ruby p (1..3).to_a p (1...3).to_a p ('a' .. 'l').to_a

In the example, we use both range operators to create a range of numbers and characters.
p (1..3).to_a p (1...3).to_a

These two lines create two ranges using both range operators. The range objects are converted to arrays. The first range has values 1, 2 and 3 while the second range has values 1 and 2.
p ('a' .. 'l').to_a

Here we use the .. range operator to create an array of letters from 'a' to 'l'.
$ ./range.rb [1, 2, 3] [1, 2] ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"]

This is the example output.

The ternary operator


The ternary operator (?:) is a conditional operator. It is a convenient operator for cases where we want to pick up one of two values, depending on the conditional expression.
cond-exp ? exp1 : exp2

If cond-exp is true, exp1 is evaluated and the result is returned. If the cond-exp is false, exp2 is evaluated and its result is returned.
#!/usr/bin/ruby age = 32

95

adult = age >= 18 ? true : false if adult then puts "Adult" else puts "Not adult" end

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.
adult = age >= 18 ? true : false

First, the expression on the right side of the assignment operator is evaluated. The first phase of the ternary operator is the condition expression evaluation. So if the age is greater or equal to 18, the value following the ? character is returned. If not, the value following the : character is returned. The returned value is then assigned to the adult variable.
$ ./ternary.rb Adult

A 32 years old person is adult.

Calculating prime numbers


We are going to calculate prime numbers.
#!/usr/bin/ruby nums = (4..50).to_a puts "Prime numbers:" print "2 3 " nums.each do |i| not_prime = false (2..Math.sqrt(i).ceil).each do |j| not_prime = true if i % j == 0 end print i, " " unless not_prime end puts

In the above example, we deal with several operators. A prime number (or a prime) is a natural number that has exactly two distinct natural number divisors: 1 and itself. We pick up a number and divide it by numbers, from 2 up to the picked up number. Actually, we don't have to try all smaller numbers, we can divide by numbers up to the square root of the chosen number. The formula will work. At the core, of the algorithm we use the remainder division operator, called also a modulo operator.

96

nums = (4..50).to_a

We will calculate primes from these numbers.


print "2 3 "

We skip the calculations for the 2, 3 numbers. They are primes.


not_prime = false

The not_prime is a flag to indicate that the chosen number is not a prime. We assume that the chosen number is a prime, untill it is proven otherwise later.
(2..Math.sqrt(i).ceil).each do |j| not_prime = true if i % j == 0 end

We are OK if we only modulo divide by numbers smaller than the square root of a number in question. If the remainder division operator returns 0 for any of the i values, then the number in question is not a prime.
print i, " " unless not_prime

We print the number if the not_prime flag is not set.

The above example 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/ruby require 'prime' Prime.each(50) do |i| print i, " " end puts

An example calculating prime numbers up to 50 using the Ruby prime module.


require 'prime'

We include the prime module.


Prime.each(50) do |i| print i, " " end

We calculate primes up to the upper bound 50.


$ ./primes.rb 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

97

From this ouput we see primes between numbers 2 and 50. In this part of the Ruby tutorial, we covered the expressions.

Flow control in Ruby


In this part of the Ruby tutorial, we will talk about the flow control. We will define several keywords that enable us to control the flow of a Ruby program. Conditionals and loops alter the flow of a Ruby program. Conditionals are keywords that execute a certain statement under a specific condition. Loops are blocks of program that are executed multiple times. When the program is run, the statements are executed from the top of the source file to the bottom. One by one.

The if statement
The if keyword is used to check if an expression is true. If it is true, a statement is then executed. The statement can be a single statement or a compound statement. A compound statement consists of multiple statements enclosed by the block. A block is code enclosed by the end keyword. The then keyword is optional.
#!/usr/bin/ruby num = gets.to_i if num > 0 then puts "num variable is positive" puts "num variable equals to #{num}" end

We read a number from a user. If the number is greater than zero, then we print two messages to the console. If not, nothing is done.
$ ./simpleif.rb 4 num variable is positive num variable equals to 4

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

We can use the else keyword to create a simple branch. If the expression inside the square brackets following the if keyword evaluates to false, the statement following the else keyword is automatically executed. The block of code is enclosed by the end keyword.
#!/usr/bin/ruby age = 17 if age > 18

98

else end

puts "Driving licence issued" puts "Driving licence not permitted"

We have an age variable. The boolean expression evaluates to false and we get "Driving licence not permitted" in the console.
$ ./licence.rb Driving licence not permitted

We can create multiple branches using the elsif keyword. The elsif keyword tests for another condition, if and only if the previous condition was not met. Note that we can use multiple elsif keywords in our tests.
#!/usr/bin/ruby print "Enter a number: " num = gets.to_i if num < 0 puts "#{num} is negative" elsif num == 0 puts "#{num} is zero" elsif num > 0 puts "#{num} is positive" end

We have a numerical variable and we test it, if it is a negative number or positive or if it equals to zero. Depending on the value read from the user, we print one of the messages to the console.

The case statement


The case statement is a selection control flow statement. It allows the value of a variable or expression to control the flow of program execution via a multi way branch. It creates multiple branches in a simpler way than using the combination of if, elsif statements. We have a variable or an expression. The case keyword is used to test a value from the variable or the expression against a list of values. The list of values is presented with the when keyword. If the values match, the statement following the when is executed. There is an optional else statement. It is executed if no other match is found.
#!/usr/bin/ruby print "Enter top level domain: " domain = gets.chomp case domain

99

when "us" puts "United States" when "de" puts "Germany" when "sk" puts "Slovakia" when "hu" puts "Hungary" else puts "Unknown" end

In our program, we have a domain variable. We read a value for the variable from the command line. We use the when statement to test for the value of the variable. There are several options. If the value equals for example to "us", the "United States" string is printed to the console.
domain = gets.chomp

We get an input from the user with the gets method. The input also includes the newline character. The newline is excluded with the chomp method.
$ ./domains.rb Enter top level domain: hu Hungary

We have entered "hu" string to the console and the program responded with "Hungary".

The while, until statements


The while statement is a control flow statement that allows code to be executed repeatedly based on a given boolean condition. It executes the code while the condition is true. The while keyword executes the statements inside the block enclosed by the end keyword. The statements are executed each time the expression is evaluated to true.
#!/usr/bin/ruby i = 0 sum = 0 while i < 10 do i = i + 1 sum = sum + i end puts "The sum of 0..9 values is #{sum}"

In the code example, we calculate the sum of values from a range of numbers. The while loop has three parts: initialization, testing and updating. Each execution of the statement is called a cycle.
i = 0 sum = 0

100

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


while i < 10 ... end do

The expression between the while and do keywords is the second phase, the testing. Note that the do keyword is optional. The statements in the body are executed until the expression is evaluated to false.
i = i + 1

This is the last, third phase of the while loop the updating. We increment the counter. Note that improper handling of the while loops may lead to endless cycles.
$ ./while.rb The sum of 0..9 values is 55

This is the output of the example.

The until is a control flow statement which executes code while the condition is false. The loop stops when the condition is true.
#!/usr/bin/ruby hours_left = 12 until hours_left == 0 if hours_left == 1 puts "There is #{hours_left} hour left" else puts "There are #{hours_left} hours left" end hours_left -= 1 end

In our example, we have a variable hours_left. We begin a count down. In each loop cycle, we print how many hours are left there. When the variable equals zero, the loop is stopped.
$ ./until.rb There are 12 hours left There are 11 hours left There are 10 hours left There are 9 hours left There are 8 hours left There are 7 hours left There are 6 hours left There are 5 hours left There are 4 hours left There are 3 hours left There are 2 hours left There is 1 hour left

101

Running the example we get this outcome.

The for statement


When the number of cycles is know before the loop is initiated, we can use the for statement. The for loop is used in conjuction with ranges. For each element of a range a block of statements is executed. The statements are enclosed with the end keyword. The do keyword is optional.
#!/usr/bin/ruby for i in 0..9 do end puts "#{i}"

In this example, we print numbers 0..9 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.
$ ./forloop.rb 0 1 2 3 4 5 6 7 8 9

This is the output of the example.

To go through an array of elements using the for loop, we can use the length method of the array.
#!/usr/bin/ruby planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"] for i in 0...planets.length puts planets[i] end

In this example, we have an array of planets. We traverse the array and print each element of the array.
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]

This is an array of planets. 102

for i in 0...planets.length

The length method returns the length of the array. Since arrays begin with 0, the last index is n-1. The ... range operator creates a range of numbers, excluding the last high value.
puts planets[i]

We print the element having a specific index in the array.


$ ./planets2.rb Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune

Running the above Ruby program gives this output.

The each method


In Ruby, we can use the each method to iterate through items of an array. It takes two parameters. An element and a block. The element is put between pipes. It is a placeholder for the item of the current iteration. The block is the code which is executed on each iteration.
#!/usr/bin/ruby planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"] planets.each do |planet| end puts planet

In this example, we go through an array of planets using the each iterator.


planets.each do |planet| end puts planet

The each iterator is a method which works on the planets array. The planet is a placeholder for a current item of the iteration. We could put there any character we wanted. We could use {} characters instead of do, end keywords.

The break, next statements


The break statement can be used to terminate a block defined by while, for or case statements.
#!/usr/bin/ruby

103

while true r = 1 + rand(30) print "#{r} " if r == 22 break end

end puts

We define an endless while loop. We use the break statement to get out of this loop. We choose a random value from 1 to 30. We print the value. If the value equals to 22, we finish the endless while loop.
while true ... end

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 break out.
r = 1 + rand(30) print "#{r} "

We compute a random number from 1 to 30 and print it to the console.


if r == 22 break end

If the number equals to 22, we break the loop. The while cycle terminates.
$ ./break.rb 20 14 6 26 30 12 2 10 18 29 28 11 30 26 20 22

We might get something like this.

The next statement is used to skip a part of the loop and continue with the next iteration of the loop. It can be used in combination with for and while statements. In the following example, we will print a list of numbers that cannot be divided by 2 without a remainder.
#!/usr/bin/ruby num = 0 while num < 100 num += 1

104

if (num % 2 == 0) next end end puts print "#{num} "

We iterate through numbers 1..99 with the while loop.


if (num % 2 == 0) next end

If the expression num % 2 returns 0, the number in question can be divided by 2. The next statement is executed and the rest of the cycle is skipped. In our case, the last statement of the loop is skipped and the number is not printed to the console. The next iteration is started.
$ ./next.rb 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99

This is a sample output of the program.

The redo statement


The redo statement restarts an iteration of a loop, without checking the loop condition. The last example will be a more complex one. It will demonstrate the redo statement and other features as well.
#!/usr/bin/ruby options = ["rock", "scissors", "paper"] while true print <<TEXT 1 - rock 2 - scissors 3 - paper 9 - end game TEXT val = gets.to_i r = rand(3) + 1 if val == 9 puts "End" exit end if ![1, 2, 3, 9].include?(val) puts "Invalid option" redo

105

end computer = options[r-1] human = options[val-1] puts "I have #{computer}, you have #{human}" if val == r puts "Tie, next throw" redo end if val == 1 and r == 2 puts "Rock blunts scissors, you win" elsif val == 2 and r == 1 puts "Rock blunts scissors, you loose" elsif val == 2 and r == 3 puts "Scissors cut paper, you win" elsif val == 3 and r == 2 puts "Scissors cut paper, you loose" elsif val == 3 and r == 1 puts "Paper covers rock, you win" elsif val == 1 and r == 3 puts "Paper covers rock, you loose" end end

We have a simple Rock-paper-scissors game. In this code example, we will utilize the redo statement, conditionals, random numbers, arrays and user input.
options = ["rock", "scissors", "paper"]

We have all possibilities of the game in the options array. These three words will be used when printing messages to the console.
print <<TEXT 1 - rock 2 - scissors 3 - paper 9 - end game TEXT

We print the menu to the console using the heredoc syntax. The heredoc starts with << followed by a string. The same string closes the construct; it must be left aligned. This allows us to print multiple lines in one step. This menu is printed each game cycle.
val = gets.to_i r = rand(3) + 1

106

In these code lines, we read a value from the terminal. Then we select randomly a number among 1, 2, 3. Note that rand(3) returns a number from 0, 1, 2. This is why we add 1.
if val == 9 puts "End" exit end

If the input from the user equals 9, we print 'End' to the terminal and end the game. The exit method terminates the program.
if ![1, 2, 3, 9].include?(val) puts "Invalid option" redo end

In case the user selects a different value than offered in the menu, we inform about the invalid option and redo the cycle.
computer = options[r-1] human = options[val-1] puts "I have #{computer}, you have #{human}"

The numbers are transformed into strings. We print both the user's and the computer's selection.
if val == r puts "Tie, next throw" redo end

If both parties have the same option, there is a tie. We start a new game cycle. We utilize the redo keyword.
if val == 1 and r == 2 puts "Rock blunts scissors, you win" elsif val == 2 and r == 1 puts "Rock blunts scissors, you loose" ...

Using multiple if, elsif branches, we compare the selections of the user and the computer. We decide, who is the winner.
$ ./redo.rb 1 - rock 2 - scissors 3 - paper 9 - end game 3 I have paper, you have paper Tie, next throw 1 - rock 2 - scissors 3 - paper

107

9 - end game 2 I have rock, you have scissors Rock blunts scissors, you loose 1 - rock 2 - scissors 3 - paper 9 - end game 1 I have scissors, you have rock Rock blunts scissors, you win 1 - rock 2 - scissors 3 - paper 9 - end game 9 End

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

Arrays in Ruby
In this part of the Ruby tutorial, we will cover arrays. Arrays are ordered collections of objects. A variable can hold only one item at a time. Arrays can hold multiple items. These items are called elements of the array. Arrays can hold objects of any data type. Each element can be referred to by an index. Arrays are zero based. The index of the first element is zero. Note that Ruby arrays are very different from arrays in languages like C, C++ or Java.
#!/usr/bin/ruby nums = [1, 2, 3, 4, 5] nums.each do |num| puts num end

Our first example will create an array of five integers. The elements of the array are printed to the console.
nums = [1, 2, 3, 4, 5]

This line creates an array of five integers. The elements are separated by commas and placed between square brackets.
nums.each do |num| puts num end

We go through the array with the each method and print each element to the console. 108

$ ./array.rb 1 2 3 4 5

This is the output of the program.

Array creation
An array in Ruby is an object. Arrays can be instantiated with the new method.
#!/usr/bin/ruby nums = Array.new nums.push nums.push nums.push nums.push nums.push puts nums 1 2 3 4 5

In the script we first create a nums array. Then we add five integers to it.
nums = Array.new

An array object is created.


nums.push 1

The push method appends an item to the end of the array.

We will continue with the array object creation using the new method.
#!/usr/bin/ruby a1 a2 a3 a4 a5 = = = = = Array.new Array.new Array.new Array.new Array.new 3 6, "coin" [11] (15) {|e| e*e}

puts [a1, a2, a3, a4, a5].inspect

The new method of the Array class may take some options.
a1 = Array.new

An empty array is created. We are supposed to fill it with data later on.
a2 = Array.new 3

109

Here we create an array of three nil objects.


a3 = Array.new 6, "coin"

An array containing six "coin" strings is created. The first option is the size of the array. The second option is the object to fill the array.
a4 = Array.new [11]

The fourth array will have one item.


a5 = Array.new (15) {|e| e*e}

We create an array with 15 elements. Each element is created in the block. There we compute a sequence of squared integers.
puts [a1, a2, a3, a4, a5].inspect

We put all our arrays into one array. Arrays may be put into other arrays. Then we call the inspect method on the array. This will call the method on all its elements. The inspect method returns the string representation of the array. This is useful when we need to quickly check the contents of an array.
$ ./arraynew.rb [[], [nil, nil, nil], ["coin", "coin", "coin", "coin", "coin", "coin"], [11], [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196]]

We can see the contents of all the arrays created.

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


#!/usr/bin/ruby integers = [1, 2, 3, 4, 5] animals = %w( donkey dog cat dolphin eagle ) weights = Array.new weights << 4.55 << 3.22 << 3.55 << 8.55 << 3.23 puts integers.inspect puts animals.inspect puts weights.inspect

We create three arrays of integers, strings and decimals.


integers = [1, 2, 3, 4, 5]

This line creates an array having 5 integers. This is the classic array creation. The elements of the array are put between square brackets and separated by commas.
animals = %w( donkey dog cat dolphin eagle )

110

The code line creates a string array with five elements. In this mode, we save some typing. We do not use the commas and double quotes.
weights = Array.new weights << 4.55 << 3.22 << 3.55 << 8.55 << 3.23

In the third way, there are two steps. First we creaet an Array object, then we initialize it with data. This is a formal array creation. The above ways were in fact shorthands for this notation.
puts integers.inspect

The inspect method prints the string representation of the array to the terminal.
$ ./creation.rb [1, 2, 3, 4, 5] ["donkey", "dog", "cat", "dolphin", "eagle"] [4.55, 3.22, 3.55, 8.55, 3.23]

This is the output of the code example.

Array items are not limited to numbers and strings. Arrays can contain all Ruby data types.
#!/usr/bin/ruby class Empty end nums = [1, 2, 3, 4, 5] various = [1, -1, "big", 3.4, Empty.new, nums, :two] puts various.inspect

We put various Ruby objects inside the various array.


various = [1, -1, "big", 3.4, Empty.new, nums, :two]

The array contains numbers, a string, a custom object, another array and a symbol.
$ ./arrayobjects.rb [1, -1, "big", 3.4, #<Empty:0x987f704>, [1, 2, 3, 4, 5], :two]

Running the arrayobjects.rb example, we receive this output.

The last example showed a nested array; an array within another array. In Ruby, it is possible to nest arrays into arrays.
#!/usr/bin/ruby numbers = [1, 2, 3, [2, 4, 6, [11, 12]]]

111

puts numbers.length puts numbers[0], numbers[1] puts numbers[3][0] puts numbers[3][1] puts numbers[3][3][0] puts numbers[3][3][1] puts numbers.flatten!.inspect

The array [11, 12] is nested within the [2, 4, 6, ...] array, which is also nested in the [1, 2, 3, ...] array.
puts numbers.length

The length method returns 4. The inner array is counted as one element.
puts numbers[0], numbers[1]

The [] characters serve in this context the purpose of accessing array elements. The above line returns the first and the second element (numbers 1 and 2) of the numbers array. The numbers within the square brackets are indexes to the array. The first index is 0, which returns the first element.
puts numbers[3][0] puts numbers[3][1]

Here we access elements from the nested array. The [3] grabs the fourth element, which is an array, [2, 4, 6, [11, 12]]. The [3][0] returns the first element of the inner array, which is number 2 in our case. In a similar fashion, the [3][1] returns the second element of the inner array, the number 4.
puts numbers[3][3][0] puts numbers[3][3][1]

Now we go even deeper. We access the elements of the innermost array. The [3][3] return the [11, 12] array. And from this array we get the first (11) and the second (12) element.
puts numbers.flatten!.inspect

The flatten! method flattens the array. It takes all elements from the inner arrays and creates a new one, without any inner arrays.
$ ./arrayofarrays.rb 4 1 2 2 4 11 12 [1, 2, 3, 2, 4, 6, 11, 12]

112

This is the output of the code example.

Printing array contents


A common job is to print array elements to to console. We have several ways to accomplish this task.
#!/usr/bin/ruby integers = [1, 2, 3, 4, 5] puts integers puts integers.inspect integers.each do |e| puts e end

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


puts integers

The array as a parameter to the puts/print method is the simplest way to print the contents of the array. Each element is printed on a separate line.
puts integers.inspect

Using the inspect method, the output is more readable. The line prints the string representation of the array to the terminal.
integers.each do |e| puts e end

The each method calls a block once for each element in array, passing that element as a parameter. We simply use the puts method on each element.
$ ./printarray1.rb 1 2 3 4 5 [1, 2, 3, 4, 5] 1 2 3 4 5

The array is printed three times to the console.

In the second example, we provide additional two ways to print array elements.

113

#!/usr/bin/ruby integers = [1, 2, 3, 4, 5] integers.length.times do |idx| puts integers[idx] end integers.each_with_index do |num, idx| puts "value #{num} has index #{idx}" end

In the first case, we use the combination of the length and times methods. In the second case, we use the each_with_index method.
integers.length.times do |idx| puts integers[idx] end

The length method returns the size of the array. The times method iterates the following block length times, passing in values from 0 to length-1. These numbers serve as indexes to the array in question.
integers.each_with_index do |num, idx| puts "value #{num} has index #{idx}" end

The each_with_index iterates the array and passes the element and its index to the given block. This way we can easily print the element and its index in one shot.
$ ./printarray2.rb 1 2 3 4 5 value 1 has index 0 value 2 has index 1 value 3 has index 2 value 4 has index 3 value 5 has index 4

This is the output of the example.

Reading array elements


In this section, we will read data from the arrays.
#!/usr/bin/ruby lts = %w{ a b c d e f g h} puts lts.first puts lts.last puts lts.at(3)

114

In the first example, we show three simple methods for data retrieval.
puts lts.first puts lts.last

The first method reads the first element of the array. The last method reads the last element of the array.
puts lts.at(3)

The at method returns the array element having a specific index. This line reads the fourth element of the array.
$ ./retrieval.rb a h d

This is the output of the retrieval.rb program.

The [] 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/ruby lts = %w{ a b c d e f g h } puts puts puts puts puts lts[0] lts[-1] lts[0, 3].inspect lts[2..6].inspect lts[2...6].inspect

We show five examples of reading data using the [] characters.


puts lts[0] puts lts[-1]

We get the first and the last item of the array. We put the index number of an item between the [] characters. The first item has index 0, the last item has index -1.
puts lts[0, 3].inspect

When we have two numbers between the square brackets, the first is the start index and the second is the length. In this code line, we return 3 elements starting from index 0. Note that the inspect method is optional and it is only used to produce more readable output.
puts lts[2..6].inspect puts lts[2...6].inspect

We can use range operator inside the square brackets. In the first line we read elements from index 2 to 6, in the second line elements from 2 to 5.

115

Next we will demonstrate the values_at method. The advantage of this method is that we can place multiple indexes between the [] characters to get various elements.
#!/usr/bin/ruby lts = %w{ a b c d e f g h} puts puts puts puts lts.values_at(1..5).inspect lts.values_at(1, 3, 5).inspect lts.values_at(1, 3, 5, 6, 8).inspect lts.values_at(-1, -3).inspect

The values_at method returns an array containing the elements which corresponding to the given selector(s). The inspect method is optional. It is used to get a more readable output.
puts lts.values_at(1..5).inspect

This code line returns elements which have indexes 1 to 5.


puts lts.values_at(1, 3, 5).inspect

Here we read elements with indexes 1, 3 and 5.


puts lts.values_at(1, 3, 5, 6, 8).inspect

We put as many indexes as we want. If there is no element with the specific index, we get nil.
puts lts.values_at(-1, -3).inspect

Negative indexes return elements from the end of the array.


$ ./retrieval3.rb ["b", "c", "d", "e", "f"] ["b", "d", "f"] ["b", "d", "f", "g", nil] ["h", "f"]

This is the output of the script.

We will use the fetch method to read data from an array.


#!/usr/bin/ruby lts = [0, 1, 2, 3, 4, 5, 6] puts puts puts puts lts.fetch(0) lts.fetch(-2) lts.fetch(8, 'undefined') lts.fetch(8) { |e| -2*e }

We show several forms of using the fetch method.

116

puts lts.fetch(0) puts lts.fetch(-2)

The first line prints the first element from the array. The second line prints the second element from the end of the array.
puts lts.fetch(8, 'undefined')

The third form of the fetch method returns the element with the given index. If the index lies outside the array elements, the method returns the default value, 'undefined' in our case. Without the second parameter, the fetch method throws an IndexError.
puts lts.fetch(8) { |e| -2*e }

In the last form of the fetch method, we have a block. In case a value with a given index is not found, the method returns a value of invoking the block, passing in the index.
$ ./retrieval4.rb 0 5 undefined -16

This is the output of the script.

We will show the usage of the take and take_while methods.


#!/usr/bin/ruby lts = %w{ a b c d e f g h} puts lts.take(4).inspect lts2 = lts.take_while { |e| e < 'f' } puts lts2.inspect

The take n method returns the first n elements of the array. The take_while method passes elements to the block until the block returns nil or false, then stops iterating and returns an array of all prior elements.
puts lts.take(4).inspect

Here we return the first four elements of the array.


lts2 = lts.take_while { |e| e < 'f' } puts lts2.inspect

Here we create a new array from the original array. In the new array we have all characters that come before the 'f' character.
$ ./retrieval5.rb ["a", "b", "c", "d"]

117

["a", "b", "c", "d", "e"]

Here we see the output of the retrieval5.rb program.

The slice method is identical to the [] characters. The method returns one or more elements from the array.
#!/usr/bin/ruby lts = %w{ a b c d e f g h} puts puts puts puts puts lts.slice(0) lts.slice(-1) lts.slice(0, 3).inspect lts.slice(2..6).inspect lts.slice(2...6).inspect

We present five examples of the slice method.


puts lts.slice(0) puts lts.slice(-1)

These forms of the slice 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 lts.slice(0, 3).inspect

The first parameter is the start index and the second parameter is the length. In this code line, we return 3 elements starting from index 0.
puts lts.slice(2..6).inspect puts lts.slice(2...6).inspect

We can use range operator with the slice method. In the first line we read elements from index 2 to 6, in the second line elements from 2 to 5.
$ ./retrieval6.rb a h ["a", "b", "c"] ["c", "d", "e", "f", "g"] ["c", "d", "e", "f"]

The slice 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 sample method for this.
#!/usr/bin/ruby lts = %w{ a b c d e f g h} puts lts.sample

118

puts lts.sample(3).inspect

The sample 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.
$ ./random.rb b ["c", "f", "d"] $ ./random.rb d ["c", "d", "e"]

Running the example twice gives different results.

Working with arrays


In the following examples, we will introduce several Ruby array methods.
#!/usr/bin/ruby num1 = [1, 2, 3, 4, 5] num2 = [6, 7, 8, 9, 10] puts num1 + num2 puts num1.concat num2

We have two arrays. We add these two arrays.


puts num1 + num2 puts num1.concat num2

There are two ways to add arrays. We can use the + operator or the concat method. The result is the same.

Ruby has plenty of methods for working with arrays. For example, the length method returns the number of elements in the array.
#!/usr/bin/ruby lts = %w{ a b c d e f} puts puts puts puts lts.inspect "Array has #{lts.length} elements" "The first element is #{lts.first}" "The last element is #{lts.last}"

puts lts.eql? lts.dup puts lts.eql? lts.dup.delete_at(0) lts.clear puts lts.inspect puts lts.empty?

In the above script, we introduce seven new methods.

119

puts "Array has #{lts.length} elements"

The length method determines the size of the array.


puts "The first element is #{lts.first}" puts "The last element is #{lts.last}"

Here we get the first and the last element of the array.
puts lts.eql? lts.dup

The eql? method figures out if two arrays are equal. In our case the line returns true. The dup method creates a shallow copy of an object. It is inherited from the Object parent.
puts lts.eql? lts.dup.delete_at(0)

The delete_at method deletes the first element of the array. This time the two arrays do not equal.
lts.clear

The clear method deletes all elements from the array.


puts lts.empty?

The empty? method checks, whether the array is empty. In our case the code line returns true, because we have just deleted all its elements.
$ ./basics.rb ["a", "b", "c", "d", "e", "f"] Array has 6 elements The first element is a The last element is f true false [] true

This is the output of the example.

Some Ruby array methods end with an exclamation mark. This is a Ruby idiom. The exclamation mark tells the programmer that the method will modify data. The exclamation mark itself does not have any effect. It is merely a naming convention.
#!/usr/bin/ruby chars = %w{a b c d e} reversed_chars = chars.reverse puts reversed_chars.inspect puts chars.inspect reversed_chars = chars.reverse!

120

puts reversed_chars.inspect puts chars.inspect

Ruby has, among others, two similar methods, the reverse method and reverse! method. These two methods change the order of the elements, they reverse it. The difference is, that the reverse method returns a reversed array and leaves the original array intact, while the reverse! method both modifies the contents of the original array.
$ ./twotypes.rb ["e", "d", "c", ["a", "b", "c", ["e", "d", "c", ["e", "d", "c", "b", "d", "b", "b", "a"] "e"] "a"] "a"]

We can clearly see that the first two arrays are different. The third and fourth arrays are same.

A few other methods will be presented in the coming code example.


#!/usr/bin/ruby numbers = [1, 2, 2, 2, 3, 4, 5, 8, 11] puts numbers.index 2 puts numbers.index 11 puts numbers.rindex 2 puts numbers.include? 3 puts numbers.include? 10 puts numbers.join '-' puts numbers.uniq!.inspect

We introduce additional five methods.


puts numbers.index 2 puts numbers.index 11

The index method returns the index of the array element. It returns the index of the first element from the left. The first line returns 1, which is the index of the first 2 in the array. There is only one 11 in the array and its index is 8.
puts numbers.rindex 2

The rindex returns the index of the first element from the right. In our case, the rightmost 2 has index 3.
puts numbers.include? 3 puts numbers.include? 10

The include? method checks if an element is present in the array. The first line returns true; 3 is present. The second line returns false; there is no 10 in our array. By convention, Ruby methods ending with question mark return a boolean value. Again, the question mark has no effect on the array. It is merely a hint for the programmer.

121

puts numbers.join '-'

The join method returns a string created from the array elements, separated by a provided separator.
puts numbers.uniq!.inspect

The uniq! method removes duplicate elements from the array. We have three times number 2 in the array. After the method call, there will be only one 2 left.
$ ./methods2.rb 1 8 3 true false 1-2-2-2-3-4-5-8-11 [1, 2, 3, 4, 5, 8, 11]

Notice the product of the join method. It is a string in which the numbers of the array are joined by the - character.

Modifying arrays
In this section, we will look closer at the methods that modify an array. Basically, we will do various insertion and deletion operations on the arrays.
#!/usr/bin/ruby lts = [] lts.insert 0, 'E', 'F', 'G' lts.push 'H' lts.push 'I', 'J', 'K' lts << 'L' << 'M' lts.unshift 'A', 'B', 'C' lts.insert(3, 'D') puts lts.inspect

We start with an empty array. We build the array using different insertion methods.
lts.insert 0, 'E', 'F', 'G'

The insert method inserts three elements into the lts array. The first letter has index 0, the second 1 and the third 3.
lts.push 'H' lts.push 'I', 'J', 'K'

The push method appends the elements to the array. We can append one or more elements.
lts << 'L' << 'M'

122

The << is a synonym for the push method. It appends an element to the array. This operator/method can be called in a chain.
lts.unshift 'A', 'B', 'C'

The unshift method prepends elements to the front of the array.


lts.insert(3, 'D')

In this case, the insert method inserts the 'D' character at a specific index.
$ ./insertion.rb ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"]

Using the above mentioned array insertion methods, we have built this array of uppercase letters.

There are several methods for deleting array elements.


#!/usr/bin/ruby lts = %w{ a b c d e f g h} lts.pop lts.pop puts lts.inspect lts.shift lts.shift puts lts.inspect lts.delete_at(0) lts.delete('d') puts lts.inspect puts lts.clear puts lts.inspect

In this script we demonstrate five methods that delete elements from an array.
lts = %w{ a b c d e f g h}

We have an array of 8 elements.


lts.pop

The pop method removes the last element from the array.
lts.shift

The shift method removes the first element from the array. 123

lts.delete_at(0)

The delete_at deletes an element at a specific position. We delete the first element of the remaining elements.
puts lts.clear

The clear method clears all the elements from the array.
lts.delete('d')

The delete method deletes a specific item from the array.


$ ./deletion.rb ["a", "b", "c", "d", "e", "f"] ["c", "d", "e", "f"] ["e", "f"] []

Here we see the output of the example.

So far we have worked with methods (with an exception of the clear method) that modified an array by adding or deleting an item a time. Ruby has methods that affect multiple array items at once.
#!/usr/bin/ruby nms = [2, -1, -4, 0, 4, 3, -2, 3, 5] nms.delete_if { |x| x < 0 } puts nms.inspect

The example introduces a delete_if method that deletes all items that meet a condition presented in the block.
nms.delete_if { |x| x < 0 }

This line deletes all negative numbers from the array.


$ ./delete_if.rb [2, 0, 4, 3, 3, 5]

We have dropped all negative numbers from the nms array.

We present another two methods that process multiple array items.


#!/usr/bin/ruby lts = %w{ a b c d e f g} puts lts.inspect

124

lts.reject! do |e| e =~ /[c-y]/ end puts lts.inspect lts.replace(["x", "y", "z"]) puts lts.inspect

We use two methods, the reject! method and the replace method.
lts.reject! do |e| e =~ /[c-y]/ end

The reject! method removes all array items that meet a specific condition inside the block. In our case, we delete all letters that comply with the regular expression; any letter from c to y. The =~ operator matches strings against regular expressions.
lts.replace(["x", "y", "z"])

The replace method will replace items with other given items. It truncates or expands the array if necessary.
$ ./modify.rb ["a", "b", "c", "d", "e", "f", "g"] ["a", "b"] ["x", "y", "z"]

This is the output of the modify.rb example.

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/ruby A = [1, 2, 3, 4, 5] B = [4, 5, 6, 7, 8] union = A | B isect = A & B diff1 = A - B diff2 = B - A sdiff = (A - B) | (B - A) puts puts puts puts puts "Union of arrays: #{union}" "Intersection of arrays: #{isect}" "Difference of arrays A - B: #{diff1}" "Difference of arrays B - A: #{diff2}" "Symmetric difference of arrays: #{sdiff}"

125

In the above script, we demonstrate several set operations, union, intersection, difference and symmetric difference.
nums1 = [1, 2, 3, 4, 5] nums2 = [4, 5, 6, 7, 8]

We define two arrays of integers. Both are sets, because each element in the array is presented only once. The two arrays have two numbers in common, the 4 and 5.
union = nums1 | nums2

This operation is a union of two arrays. The two arrays are added. Each element in the final array is presented only once.
isect = A & 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, 4 and 5.
diff1 diff2 = A - B = B - A

Here we have two difference operations, also called complements. In the first line, we get all elements that are present in A and not present in B. In the second line, we get all elements which are members of B and not A.
sdiff = (A - B) | (B - A)

Here we have a symmetric difference. A symmetric difference gives elements that are either in A or in B, but not in both sets.
$ ./setoperations.rb Union of arrays: [1, 2, 3, 4, 5, 6, 7, 8] Intersection of arrays: [4, 5] Difference of arrays A - B: [1, 2, 3] Difference of arrays B - A: [6, 7, 8] Symmetric difference of arrays: [1, 2, 3, 6, 7, 8]

This is the output of the example.

The select, collect, map methods


In the next example, we will present three methods: the select, collect and map method.
#!/usr/bin/ruby nums = [1, 3, 2, 6, 7, 12, 8, 15] selected = nums.select do |e| e > 10 end puts selected.inspect

126

collected = nums.collect do |e| e < 10 end puts collected.inspect mapped = nums.map do |e| e*2 end puts mapped.inspect

All these methods execute mass operations on the elements of an array.


selected = nums.select do |e| e > 10 end

In the above code, we create a new array using the select method. For the newly created array, we choose elements that comply with the condition inside the block. In our case, we select all elements that are greater than 10.
collected = nums.collect do |e| e < 10 end

The collect method works a bit differently. It invokes the appended block for each element and returns the value from the block. The new array contains true, false values.
mapped = nums.map do |e| e*2 end

The map method works the same as the collect method. In the above lines we create a new array from the existing array. Each element is multiplied by 2.
$ ./mass.rb [12, 15] [true, true, true, true, true, false, true, false] [2, 6, 4, 12, 14, 24, 16, 30]

These are the newly created arrays.

Ordering elements
Finally, we will be ordering elements in our array.
#!/usr/bin/ruby planets = %w{ Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune Pluto } puts "#{planets.sort}" puts "#{planets.reverse}" puts "#{planets.shuffle}"

127

The example uses three Ruby array methods to reorganize elements in the array.
puts "#{planets.sort}"

The sort method alphabetically sorts the array elements.


puts "#{planets.reverse}"

The reverse method returns a new array with all elements in a reverse order.
puts "#{planets.shuffle}"

The shuffle method randomly reorganizes the array elements.


$ ./ordering.rb ["Earth", "Jupiter", "Mars", "Mercury", "Neptune", "Pluto", "Saturn", ...] ["Pluto", "Neptune", "Uranus", "Saturn", "Jupiter", "Mars", "Earth", ...] ["Earth", "Jupiter", "Mercury", "Saturn", "Mars", "Venus", "Uranus", ...]

This is a sample output of the code example. In this chapter, we worked with Ruby arrays.

Hashes in Ruby
This part of the Ruby tutorial will mention Ruby hashes. A hash is a collection of key-value pairs. It is similar to an array. Unlike arrays, hashes can have arbitrary objects as indexes. Arrays have can only have integers. Hashes are sometimes called associated arrays. Hashes are powerful collections. They have many methods that programmers can use to do their work.

Hash creation
A hash can be created in two basic ways: with the new keyword or with the hash literal.
#!/usr/bin/ruby names = Hash.new names[1] = "Jane" names[2] = "Thomas" puts names

The first script creates a hash and adds two key-value pairs into the hash object.
names = Hash.new

A hash object is created.


names[1] = "Jane" names[2] = "Thomas"

128

We add two pairs of values to the hash. The numbers 1, 2 are the keys to the hash. The keys are placed inside the square brackets. The names are the values that belong to the keys.
puts names

The puts method prints the string representation of the hash to the console. It is also the string literal of the hash.
$ ./create.rb {1=>"Jane", 2=>"Thomas"}

From the output we can see the literal representation of the names hash. A hash is bounded by curly brackets. The keys and the values are paired with the => characters.

A store method can be used to initialize the hash with some values. It can be use instead of the square brackets.
#!/usr/bin/ruby names = Hash.new names.store(1, "Jane") names.store(2, "Thomas") names.store(3, "Rebecca") puts names

We have a similar script. This time we use the store method. The method associates the given key with the given value and stores the pair in the hash.
names.store(1, "Jane")

The first parameter of the store method is the key 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 brackets. And the key-value pairs are associated with the => characters.
#!/usr/bin/ruby domains = { "de" "sk" "hu" "us" "no" } => => => => => "Germany", "Slovakia", "Hungary", "United States", "Norway"

puts domains["de"] puts domains["sk"]

We create a domains hash with 5 pairs. This time both keys and values are string types.
domains = { "de" => "Germany", "sk" => "Slovakia",

129

"hu" => "Hungary", "us" => "United States", "no" => "Norway"

This is a hash literal notation. The key-value pairs are put between the curly brackets. The items are separated by the comma character. And the keys are associated with values using the => characters combination.
puts domains["de"]

Here we print the domain value name associated with the "de" key.
$ ./create3.rb Germany Slovakia

This is the output of the code example.

Basic work
In this section, we present some methods for the very basic work with Ruby hashes.
#!/usr/bin/ruby names = Hash.new names[1] names[2] names[3] names[4] names[5] = = = = = "Jane" "Thomas" "Robert" "Julia" "Rebecca"

puts "The size of the hash is #{names.size}" puts names.keys.inspect puts names.values.inspect

In the above Ruby script, we create a hash with five values. We introduce three hash methods.
puts "The size of the hash is #{names.size}"

The size method returns the size of the hash. It is a synonym for the length method.
puts names.keys.inspect puts names.values.inspect

The keys method returns all keys of the hash. In a similar fashion, the values 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 inspect method on the returned arrays.
$ ./basic.rb The size of the hash is 5 [1, 2, 3, 4, 5]

130

["Jane", "Thomas", "Robert", "Julia", "Rebecca"]

We see the ouput of the example. Note that the output of the last two methods are two arrays.

The second example of the section presents three distinct hash methods.
#!/usr/bin/ruby names1 = Hash.new names1[1] names1[2] names1[3] names1[4] names1[5] = = = = = "Jane" "Thomas" "Robert" "Julia" "Rebecca"

names2 = names1.dup puts names1.eql? names2 puts names1.empty? names1.clear puts names1.empty?

The Ruby script creates a names hash. It calls three hash methods on the object.
names2 = names1.dup

We create a duplicate of the hash by calling the dup method. The method is inherited by the hash from the parent object.
puts names1.eql? names2

The eql? method compares two hash objects. In our case the hashes are equal and the line prints true.
puts names1.empty?

The empty? method checks whether the hash is empty or not. The line print false because the names1 hash has five items.
names1.clear puts names1.empty?

The clear method deletes all items from the hash. The successive call of the empty? method returns true.
$ ./basic2.rb true false true

This is the example output.

131

We have methods that can determine whether a key or a value is present in the hash.
#!/usr/bin/ruby domains = { :de => "Germany", :sk => "Slovakia", :no => "Norway", :us => "United States" } puts puts puts puts domains.has_key? :de domains.include? :no domains.key? :me domains.member? :sk

puts domains.has_value? "Slovakia" puts domains.value? "Germany"

We create a domains hash with four pairs. The keys are symbols. Symbols are often used as keys, because they are more efficient.
puts puts puts puts domains.has_key? :de domains.include? :no domains.key? :me domains.member? :sk

Here we have four methods that determine whether a key is in the hash. They all do the same; they are synonyms.
puts domains.has_value? "Slovakia" puts domains.value? "Germany"

These two methods check if the two strings are inside the hash.
$ ./has.rb true true false true true true

This is the output of the example.

In the final example of the section, we will read values from the hash.
#!/usr/bin/ruby stones = { 1 => "garnet", 2 => "topaz", 3 => "opal", 4 => "amethyst" } puts stones.fetch 1 puts stones[2] puts stones.values_at 1, 2, 3

132

The Ruby script presents three hash methods for reading values of a hash.
puts stones.fetch 1

The fetch method reads a value for a given key.


puts stones[2]

Square brackets can be used to get a value. In our case, the line prints "topaz" to the console.
puts stones.values_at 1, 2, 3

The values_at method can be used to get multiple values at one step. The method returns an array of the values for the given keys.
$ ./read.rb garnet topaz garnet topaz opal

This is the output of the example.

Looping through a hash


There are several methods that can be used to loop through a Ruby hash.
#!/usr/bin/ruby stones = { 1 => "garnet", 2 => "topaz", 3 => "opal", 4 => "amethyst" } stones.each { |k, v| puts "Key: #{k}, Value: #{v}" } stones.each_key { |key| puts "#{key}" } stones.each_value { |val| puts "#{val}" } stones.each_pair { |k, v| puts "Key: #{k}, Value: #{v}" }

In the above example, we present four methods. We use them to display all keys, values and both keys and values of a hash.
stones.each { |k, v| puts "Key: #{k}, Value: #{v}" }

The each method calls the given block for each key in the hash, passing key-value pair as parameter.
stones.each_key { |key| puts "#{key}" }

We use the each_key method to loop throug all keys of a hash. They are printed to the console.
stones.each_value { |val| puts "#{val}" }

133

The each_value can be used to loop throug the values of a hash.


stones.each_pair { |k, v| puts "Key: #{k}, Value: #{v}" }

The each_pair method is a synonym for the each method. We loop through the keys and values of the stones hash.
$ ./loop.rb Key: 1, Value: Key: 2, Value: Key: 3, Value: Key: 4, Value: 1 2 3 4 garnet topaz opal amethyst Key: 1, Value: Key: 2, Value: Key: 3, Value: Key: 4, Value: garnet topaz opal amethyst

garnet topaz opal amethyst

The output shows the keys and values, keys, values of the stones hash.

Deleting pairs
In the following examples, 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 key-values at one step.
#!/usr/bin/ruby names = Hash.new names[1] names[2] names[3] names[4] names[5] = = = = = "Jane" "Thomas" "Robert" "Julia" "Rebecca"

names.delete 4 names.shift puts names

In the script we have two methods: delete and shift. The delete method removes and returns a value for a specified key. The shift method deletes the first pair from the hash. It also returns the removed pair as an array.
names.delete 4

Here we delete a pair 4 => "Julia".

134

names.shift

This code line removes the first pair, namely 1 => "Jane".
$ ./deleteitem.rb {2=>"Thomas", 3=>"Robert", 5=>"Rebecca"}

In the output we can see the pairs of the hash that are left.

The reject and the delete_if methods can remove multiple pairs from a hash. The methods delete pairs that return true for the given condition in the block. There is an important distinction between the two methods. The reject method works on a copy of a hash while the delete_if works on the original hash.
#!/usr/local/bin/ruby names1 = Hash.new names1[1] names1[2] names1[3] names1[4] names1[5] puts puts puts puts = = = = = "Jane" "Thomas" "Robert" "Julia" "Rebecca"

names1.reject { |k, v| v =~ /R.*/ } names1 names1.delete_if { |k, v| k<=3 } names1

The example deletes multiple pairs using the previously mentioned methods.
puts names1.reject { |k, v| v =~ /R.*/ }

The reject method removes all values that fit the regular expression in the block. The modified hash is returned and the original hash is not changed.
puts names1

The output of this line confirms that the original hash was intact.
puts names1.delete_if { |k, v| k<=3 }

In this case, we delete all pairs, for which the key is lower or equal to 3. The method modifies the original hash.
$ ./massdelete.rb {1=>"Jane", 2=>"Thomas", 4=>"Julia"} {1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia", 5=>"Rebecca"} {4=>"Julia", 5=>"Rebecca"} {4=>"Julia", 5=>"Rebecca"}

Output of the example.

135

Adding hashes
Ruby's merge and update methods add (key, value) pairs to hashes. Ruby has methods for hash addition.
#!/usr/bin/ruby names1 = Hash.new names1[1] = "Jane" names1[2] = "Thomas" names2 = Hash.new names2[3] = "Robert" names2[4] = "Julia" names = names1.merge names2 puts names names = names1.update names2 puts names

In the Ruby script, we create two hashes. Then we apply merge and update methods on them.
names = names1.merge names2 puts names

The names1 and names2 hashes are combined. The result is assigned to the names hash. We print the newly created hash.
$ ./merge.rb {1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"} {1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"}

As we can see, the final hashes contain pairs from the names1 and names2 hashes.

The merge vs merge!


In the final section, we recap a common Ruby idiom. Several Ruby methods have counterparts that end with an exclamation point. This mark, which has no syntactic significance, indicates that a method modifies the object on which that method is called.
#!/usr/bin/ruby names1 = Hash.new names1[1] = "Jane" names1[2] = "Thomas" names2 = Hash.new names2[3] = "Robert" names2[4] = "Julia"

136

names = names1.merge names2 puts names puts names1 names = names1.merge! names2 puts names puts names1

We will demonstrate the difference on the merge and merge! methods.


names = names1.merge names2

The merge does not modify the names1 hash. It works on its copy.
names = names1.merge! names2

The merge! method works on the original hash. The names1 hash is changed.
$ ./merge2.rb {1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"} {1=>"Jane", 2=>"Thomas"} {1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"} {1=>"Jane", 2=>"Thomas", 3=>"Robert", 4=>"Julia"}

This is the output of the merge2.rb program. In this chapter, we worked with Ruby hashes.

Object-oriented programming in Ruby


In this part of the Ruby tutorial, we will talk about object-oriented programming in Ruby. Programming 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 OOP are:

Abstraction Polymorphism Encapsulation Inheritance

The abstraction is simplifying complex 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.

137

Objects
Objects are basic building blocks of a Ruby OOP program. An object is a combination of data and methods. In a OOP program, we create objects. These objects communicate together through methods. Each object can receive messages, send messages and process data. There are two steps in creating an object. First, we define a class. A 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. A class can be used to create many objects. Objects created at runtime from a class are called instances of that particular class.
#!/usr/bin/ruby class Being end b = Being.new puts b

In our first example, we create a simple object.


class Being end

This is a simple class definition. The body of the template is empty. It does not have any data or methods.
b = Being.new

We create a new instance of the Being class. For this we have the new method. The b variable stores the newly created object.
puts b

We print the object to the console to get some basic description of the object. When we print an object, we in fact call its to_s method. But we have not defined any method yet. It is because every object created inherits from the base Object. It has some elementary functionality, which is shared among all objects created. One of this is the to_s method.
$ ./simple.rb #<Being:0x9f3c290>

We get the object class name.

The constructor
A constructor is a special kind of a method. It is automatically called when an object is created. Constructors do not return values. The purpose of the constructor is to initiate the state of an object. The constructor in Ruby is called initialize. Constructors do not return any values.

138

Constructors cannot be inherited. The constructor of a parent object is called with a super method. They are called in the order of inheritance.
#!/usr/bin/ruby class Being def initialize puts "Being is created" end end Being.new

We have a Being class.


class Being def initialize puts "Being is created" end end

The Being class has a constructor method called initialize. It prints a message to the console. The definition of a Ruby method is placed between the def and end keywords.
Being.new

An instance of the Being class is created. At the moment of the object creation, the constructor method is called.
$ ./constructor.rb Being is created

This is the output of the program.

An object's attributes are the data items that are bundled inside that object. These items are also called instance variables or member fields. An instance variable is a variable defined in a class, for which each object in the class has a separate copy. In the next example, we initiate data members of the class. Initiation of variables is a typical job for constructors.
#!/usr/bin/ruby class Person def initialize name @name = name end def get_name

139

end end

@name

p1 = Person.new "Jane" p2 = Person.new "Beky" puts p1.get_name puts p2.get_name

In the above Ruby code, we have a Person class with one member field.
class Person def initialize name @name = name end

In the constructor of the Person class, we set a member field to a value name. The name parameter is passed to the constructor at creation. A constructor is a method called initialize that is being called at the creation of an instance object. The @name is an instance variable. Instance variables start with @ character in Ruby.
def get_name @name end

The get_name method returns the member field. In Ruby member fields are accessible only via methods.
p1 = Person.new "Jane" p2 = Person.new "Beky"

We create two objects of a Person class. A string parameter is passed to each object constructor. The names are stored inside instance variables that are unique to each object.
puts p1.get_name puts p2.get_name

We print the member fields by calling the get_name on each of the objects.
$ ./person.rb Jane Beky

We see the output of the program. Each instance of the Person class has its own name member field.

We can create an object without calling the constructor. Ruby has a special allocate method for this. The allocate method allocates space for a new object of a class and does not call initialize on the new instance.

140

#!/usr/bin/ruby class Being def initialize puts "Being created" end

end

b1 = Being.new b2 = Being.allocate puts b2

In the example, we create two objects. The first object using the new method, the second object using the allocate method.
b1 = Being.new

Here we create an instance of the object with the new keyword. The constructor method initialize is called and the message is printed to the console.
b2 = Being.allocate puts b2

In case of the allocate method, the constructor is not called. We call the to_s method with the puts keyword to show, that the object was created.
$ ./allocate.rb Being created #<Being:0x8ea0044>

Here we see the output of the program.

Constructor overloading
Constructor 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 know from some programming languages. This behaviour can be simulated to some extent with default parameter values in Ruby.
#!/usr/bin/ruby class Person def initialize name="unknown", age=0 @name = name @age = age end def to_s "Name: #{@name}, Age: #{@age}" end

141

end p1 p2 p3 p4 = = = = Person.new Person.new "unknown", 17 Person.new "Becky", 19 Person.new "Robert"

p p1, p2, p3, p4

This example shows how we could simulate constructor overloading on a Person class that has two member fields. When the name parameter is not specified, the string "unknown" is used instead. For unspecified age we have 0.
def initialize name="unknown", age=0 @name = name @age = age end

The constructor takes two parameters. They have a default value. The default value is used, if we do not specify our own values at the object creation. Note that the order of parameters must be kept. First comes the name, then the age.
p1 p2 p3 p4 = = = = Person.new Person.new "unknown", 17 Person.new "Becky", 19 Person.new "Robert"

p p1, p2, p3, p4

We create four objects. The constructors take different number of parameters.


$ ./consover.rb Name: unknown, Age: 0 Name: unknown, Age: 17 Name: Becky, Age: 19 Name: Robert, Age: 0

This is the output of the example.

Methods
Methods are functions defined inside the body of a class. They are used to perform operations with the attributes of our objects. Methods are essential in the encapsulation concept of the OOP paradigm. For example, we might have a connect method in our AccessDatabase class. We need not to be informed how exactly the method connects to the database. We only have to know 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/ruby class Person

142

def initialize name @name = name end def get_name @name end end per = Person.new "Jane" puts per.get_name puts per.send :get_name

The example shows two basic ways to call a method.


puts per.get_name

The common way is to use a dot operator on an object followed by a method name.
puts per.send :get_name

The alternative is to use a built-in send method. It takes a symbol of the method to be called as a parameter.

Methods typically perform some action on an object's data.


#!/usr/bin/ruby class Circle @@PI = 3.141592 def initialize @radius = 0 end def set_radius radius @radius = radius end def area @radius * @radius * @@PI end end c = Circle.new c.set_radius 5 puts c.area

In the code example, we have a Circle class. We define two methods.


@@PI = 3.141592

143

We have defined a @@PI variable in our Circle class. It is a class variable. Class variables start with @@ sigils in Ruby. Class variables belong to a class, not to an object. Each object has access to its class variables. We use the @@PI to compute the area of the circle.
def initialize @radius = 0 end

We 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 set_radius method. The data is protected.
def set_radius radius @radius = radius end

This is the set_radius method. It gives the @radius instance variable a new value.
def area @radius * @radius * @@PI end

The area method returns the area of a circle. This is a typical task for a method. It works with data and produces some value for us.
c = Circle.new c.set_radius 5 puts c.area

We create an instance of the Circle class, and set its radius by calling the set_radius method on the object of the circle. We use the dot operator to call the method.
$ ./circle.rb 78.5398

Running the example we get this output.

Access modifiers
Access modifiers set the visibility of methods and member fields. Ruby has three access modifiers: public, protected and private. In Ruby, all data members are private. Access modifiers can be used only on methods. Ruby methods are public, unless we say otherwise. The public methods can be accessed from inside the definition of the class as well as from the outside of the class. The difference between the protected and the private methods is subtle. Neither can be accessed outside the definition of the class. They can be accessed only within the class itself and by inherited or parent classes. Note that unlike in other object-oriented programming languages, inheritance does not play role in Ruby access modifiers. Only two things are important. First, if we call the method inside or outside the class definition. Second, if we use or do not use the self keyword which points to the current receiver. 144

Access modifiers protect data against accidental modifications. They make 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. Over the years users are accustomed to using specific methods and breaking backward compatibility is generally frowned upon.
#!/usr/bin/ruby class Some def method1 puts "public method1 called" end public def method2 puts "public method2 called" end def method3 puts "public method3 called" method1 self.method1 end

end

s = Some.new s.method1 s.method2 s.method3

The example explains the usage of public Ruby methods.


def method1 puts "public method1 called" end

The method1 is public, even if we did not specify the public access modifier. It is because methods are public by default, if not specified otherwise.
public def method2 puts "public method2 called" end ...

Methods following the public keyword are public.


def method3 puts "public method3 called" method1 self.method1 end

145

From inside the public method3, we call other public method, with and without the self keyword.
s = Some.new s.method1 s.method2 s.method3

Public methods are the only methods that can be called outside the definition of a class as shown here.
$ ./public_methods.rb public method1 called public method2 called public method3 called public method1 called public method1 called

Running the example we have this output.

The next example looks at private methods.


#!/usr/bin/ruby class Some def initialize method1 # self.method1 end private def method1 puts "private method1 called" end end s = Some.new # s.method1

Private methods are tightest methods in Ruby. They can be called only inside a class definition and without the self keyword.
def initialize method1 # self.method1 end

In the constructor of the method, we call the private method1. Calling the method with the self is commented. Private methods cannot be specified with a receiver.

146

private def method1 puts "private method1 called" end

Methods following the private keyword are private in Ruby.


s = Some.new # s.method1

We create an instance of the Some class. Calling the method outside the class definition is prohibited. If we uncomment the line, the Ruby interpreter gives an error.
$ ./private_methods.rb private method called

Output of the example code.

Finally, we will work with protected methods. The distinction between protected and private methods in Ruby is subtle. Protected methods are like private. There is only one small difference. They can be called with the self keyword specified.
#!/usr/bin/ruby class Some def initialize method1 self.method1 end protected def method1 puts "protected method1 called" end end s = Some.new # s.method1

The above example shows protected method in usage.


def initialize method1 self.method1 end

Protected methods can be called with and without the self keyword.
protected

147

def method1 puts "protected method1 called" end

Protected methods are preceded by the protected keyword.


s = Some.new # s.method1

Protected methods cannot be called outside the class definition. Uncommenting 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 complexity of a program. The derived classes (descendants) override or extend the functionality of base classes (ancestors).
#!/usr/bin/ruby class Being def initialize puts "Being class created" end end class Human < Being def initialize super puts "Human class created" end end Being.new Human.new

In this program, we have two classes: a base Being class and a derived Human class. The derived class inherits from the base class.
class Human < Being

In Ruby, we use the < operator to create inheritance relations. The Human class inherits from the Being class.
def initialize super puts "Human class created" end

The super method calls the constructor of the parent class.

148

Being.new Human.new

We instantiate the Being and the Human class.


$ ./inheritance.rb Being class created Being class created Human class created

First the Being class is created. The derived Human class also calls the costructor of its parent.

An Object may be involved in comlicated relationships. A single object can have multiple ancestors. Ruby has a method ancestors which gives a list of ancestors for a specific class. Each Ruby object is automatically a descendant of Object, BasicObject classes and Kernel Module. They are built-in the core of the Ruby language.
#!/usr/bin/ruby class Being end class Living < Being end class Mammal < Living end class Human < Mammal end p Human.ancestors

We have four classes in this example. A Human is a Mammal a Living and a Being.
p Human.ancestors

We print the ancestors of a Human class.


$ ./ancestors.rb [Human, Mammal, Living, Being, Object, Kernel, BasicObject]

A Human class has three custom and three built-in ancestors.

A more complex example follows.


#!/usr/bin/ruby class Being

149

@@count = 0 def initialize @@count += 1 puts "Being class created" end def show_count "There are #{@@count} beings" end end class Human < Being def initialize super puts "Human is created" end end class Animal < Being def initialize super puts "Animal is created" end end class Dog < Animal def initialize super puts "Dog is created" end end Human.new d = Dog.new puts d.show_count

We have four classes. The inheritance hierarchy is more complicated. The Human and the Animal classes inherit from the Being class. And the Dog class inherits directly from the Animal class and further from the Being class. We also use a class variable to count the number of beings created.
@@count = 0

We define a class variable. A class variable begins with @@ sigils and it belongs to the class, not to the instance of the class. We use it to count the number of beins created.
def initialize @@count += 1 puts "Being class created" end

150

Each time the Being class is instantiated, we increase the @@count variable by one. This way we keep track of the number of instances created.
class Animal < Being ... class Dog < Animal ...

The Animal inherits from the Being and the Dog inherits from the Animal. Further, the Dog inherits from the Being as well.
Human.new d = Dog.new puts d.show_count

We create instances from the Human and from the Dog classes. We call the show_count method on the Dog object. The Dog class has no such method; the grandparent's (Being) method is called then.
$ ./inheritance2.rb Being class created Human is created Being class created Animal is created Dog is created There are 2 beings

The Human object calls two constructors. The Dog object calls three constructors. There are two Beings 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 C# or Java, public and protected data members and methods are inherited; 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/ruby class Base def initialize @name = "Base" end private def private_method puts "private method called" end protected

151

def protected_method puts "protected_method called" end public def get_name return @name end end class Derived < Base def public_method private_method protected_method end

end

d = Derived.new d.public_method puts d.get_name

In the example we have two classes. The Derived class inherits from the Base class. It inherits all three methods and one data field.
def public_method private_method protected_method end

In the public_method of the Derived class we call one private and one protected method. They were defined in the parent class.
d = Derived.new d.public_method puts d.get_name

We create an instance of the Derived class. We call public_method, as well as also get_name, which returns the private @name variable. Remember that all instance variables are private in Ruby. The get_name method returns the variable, regardless of @name's being private and defined in the parent class.
$ ./inheritance3.rb private method called protected_method called Base

The output of the example confirms that in Ruby language, public, protected, private methods and private member fields are inherited by child objects from their parents.

152

The super method


The super method calls a method of the same name in the parent's class. If the method has no arguments it automatically passes all its arguments. If we write super() no arguments are passed to parent's method.
#!/usr/bin/ruby class Base def show x=0, y=0 p "Base class, x: #{x}, y: #{y}" end

end

class Derived < Base def show x, y super super x super x, y super() end

end

d = Derived.new d.show 3, 3

In the example, we have two classes in a hierarchy. They both have a show method. The show method in the Derived class calls the show method in the Base class using the super method.
def show x, y super super x super x, y super() end

The super method without any arguments calls the parent's show method with the arguments that were passed to the show method of the Derived class: here, x=3 and y=3. The super() method passes no arguments to the parent's show method.
$ ./super.rb "Base class, "Base class, "Base class, "Base class, x: x: x: x: 3, 3, 3, 0, y: y: y: y: 3" 0" 3" 0"

This is the output of the example. This was the first part of the description of OOP in Ruby.

153

Object-oriented programming II in Ruby


In this part of the Ruby tutorial, we will continue talking about object-oriented programming in Ruby. We start with attribute accessors. We will cover class constants, class methods and operator overloading. We will define polymorphism and will show how it is used in Ruby. We will also mention modules and exceptions.

Attribute accessors
All Ruby variables are private. It is possible to access them only via methods. These methods are often called setters and getters. Creating a setter and a getter method is a very common task. Therefore Ruby has convenient methods to create both types of methods. They are attr_reader, attr_writer and attr_accessor. The attr_reader creates getter methods. The attr_writer method creates setter methods and instance variables for this setters. The attr_accessor method creates both getter, setter methods and their instance variables.
#!/usr/bin/ruby class Car attr_reader :name, :price attr_writer :name, :price def to_s "#{@name}: #{@price}" end end c1 = Car.new c2 = Car.new c1.name = "Porsche" c1.price = 23500 c2.name = "Volkswagen" c2.price = 9500 puts "The #{c1.name} costs #{c1.price}" p c1 p c2

We have a Car class. In the definition of the class, we use the attr_reader and attr_writer to create two getter and setter methods for the Car class.
attr_reader :name, :price

154

Here we create two instance methods named name and price. Note that the attr_reader takes symbols of methods as parameters.
attr_writer :name, :price

The attr_writer creates two setter methods named name and price and two instance variables, @name and @price.
c1.name = "Porsche" c1.price = 23500

In this context, two setter methods are called to fill instance variables with some data.
puts "The #{c1.name} costs #{c1.price}"

Here two getter methods are called to get data from the instance variables of the c1 object.
$ ./arw.rb The Porsche costs 23500 Porsche: 23500 Volkswagen: 9500

This is the output of the example.

As we already stated above, the attr_accessor method creates getter, setter methods and their instance variables.
#!/usr/bin/ruby class Book attr_accessor :title, :pages end b1 = Book.new b1.title = "Hidden motives" b1.pages = 255 p "The book #{b1.title} has #{b1.pages} pages"

We have a Book class in which the attr_accessor creates two pairs of methods and two instance variables.
class Book attr_accessor :title, :pages end

The attr_accessor method that sets up title and pages methods and @title and @pages instance variables.
b1 = Book.new b1.title = "Hidden motives" b1.pages = 255

155

An object of a Book class is created. Two setter methods fill the instance variables of the object.
p "The book #{b1.title} has #{b1.pages} pages"

In this code line we use two getter methods to read the values of the instance variables.
$ ./accessor.rb "The book Hidden motives has 255 pages"

This is example output.

Class constants
Ruby enables you to create class constants. These constants do not belong to a concrete object. They belong to the class. By convention, constants are written in uppercase letters.
#!/usr/bin/ruby class MMath PI = 3.141592 end puts MMath::PI

We have a MMath class with a PI constant.


PI = 3.141592

We create a PI constant. Remember that constants in Ruby are not enforced.


puts MMath::PI

We access the PI constant using the :: operator.


$ ./classconstant.rb 3.141592

Running the example we see this output.

The to_s method


Each object has a to_s method. It returns a string representation of the object. Note that when the puts method takes an object as a parameter, the to_s of the object is being called.
#!/usr/bin/ruby class Being def to_s "This is Being class" end

156

end b = Being.new puts b.to_s puts b

We have a Being class in which we override the default implementation of the to_s method.
def to_s "This is Being class" end

Each class created inherits from the base Object. The to_s method belongs to this class. We overwrite the to_s method and create a new implementation. We provide a human-readable description of our object.
b = Being.new puts b.to_s puts b

We create a Being class and call the to_s method twice. The first time explicitly, the second time implicitly.
$ ./tostring.rb This is Being class This is Being class

This is what we get when we run the example.

Operator overloading
Operator 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/ruby class Circle attr_accessor :radius def initialize r @radius = r end def +(other) Circle.new @radius + other.radius end def to_s "Circle with radius: #{@radius}" end

end

157

c1 = Circle.new 5 c2 = Circle.new 6 c3 = c1 + c2 p c3

In the example, we have a Circle class. We overload the + operator in the class. We use it to add two circle objects.
def +(other) Circle.new @radius + other.radius end

We define a method with a + name. The method adds the radiuses of two circle objects.
c1 = Circle.new 5 c2 = Circle.new 6 c3 = c1 + c2

We create two circle objects. In the third line, we add these two objects to create a new one.
$ ./operatoroverloading.rb Circle with radius: 11

Adding these two circle objects creates a third with a radius of 11.

Class methods
Ruby methods can be divided into class methods and instance methods. Class methods are called on a class. They cannot be called on an instance of a class. Class methods cannot access instance variables.
#!/usr/bin/ruby class Circle def initialize x @r = x end def self.info "This is a Circle class" end def area @r * @r * 3.141592 end end p Circle.info c = Circle.new 3 p c.area

158

The above code example presents a Circle class. Apart from a constructor method, it has one class and one instance method.
def self.info "This is a Circle class" end

Methods that start with a self keyword are class methods.


def area "Circle, radius: #{@r}" end

Instance methods do not start with the self keyword.


p Circle.info

We call a class method. Note that we call the method on a class name.
c = Circle.new 3 p c.area

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. We utilize a dot operator.
$ ./classmethods.rb "This is a Circle class" 28.274328

Output of the code example describing class methods in Ruby.

There are three ways to create a class method in Ruby.


#!/usr/bin/ruby class Wood def self.info "This is a Wood class" end end class Brick class << self def info "This is a Brick class" end end

end

class Rock end

159

def Rock.info "This is a Rock class" end p Wood.info p Brick.info p Rock.info

The example has three classes. Each of them has one class method.
def self.info "This is a Wood class" end

Class methods may start with a self keyword.


class << self def info "This is a Brick class" end end

Another way is to put a method definition after the class << self construct.
def Rock.info "This is a Rock class" end

This is the third way to define a class method in Ruby.


$ ./classmethods2.rb "This is a Wood class" "This is a Brick class" "This is a Rock class"

We see the output of calling all three class methods on a Wood, Brick and Rock classes.

Three ways to create an instance method


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/ruby class Wood def info "This is a wood object" end

end

wood = Wood.new p wood.info

160

class Brick end attr_accessor :info

brick = Brick.new brick.info = "This is a brick object" p brick.info class Rock end rock = Rock.new def rock.info "This is a rock object" end p rock.info

In the example we create three instance objects from a Wood, a Brick and a Rock class. Each object has one instance method defined.
class Wood def info "This is a wood object" end

end

wood = Wood.new p wood.info

This is probably the most common way to define and call an instance method. The info method is defined inside the Wood class. Later, the object is created and we call the info method on the object instance.
class Brick attr_accessor :info end brick = Brick.new brick.info = "This is a brick object" p brick.info

Another way is to create a method using the attribute accessors. This is a convenient way which saves some typing for the programmer. The attr_accessor creates two methods, the getter and the setter method It also creates an instance variable which stores the data. The brick object is created and the data is stored in the @info variable using the info setter method. Finally, the message is read by the info getter method.
class Rock end

161

rock = Rock.new def rock.info "This is a rock object" end p rock.info

In the third way we create an empty Rock class. The object is instantiated. Later, a method is dynamically created and placed into the object.
$ ./threeways.rb "This is a wood object" "This is a brick object" "This is a rock object"

Example 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 B inherits from class A, it doesn't have to inherit everything about class A; it can do some of the things that class A does differently. (Wikipedia) In general, polymorphism is the ability to appear in different forms. Technically, it is the ability to redefine methods for derived classes. Polymorphism is concerned with the application of specific implementations to an interface or a more generic base class. Note that there is some difference in the definition of the polymorphism in statically typed languages like C++, Java or C# and dynamically typed languages like Python 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/ruby class Animal def make_noise "Some noise" end def sleep puts "#{self.class.name} is sleeping." end end class Dog < Animal def make_noise 'Woof!' end

162

end class Cat < Animal def make_noise 'Meow!' end

end

[Animal.new, Dog.new, Cat.new].each do |animal| puts animal.make_noise animal.sleep end

We have a simple inheritance hierarchy. There is an Animal base class and two descendants, a Cat and a Dog. Each of these three classes has its own implementation of the make_noise method. The implementation of the method of the descendants replaces the definition of a method in the Animal class.
class Dog < Animal def make_noise 'Woof!' end end

The implementation of the make_noise method in the Dog class replaces the implementation of the make_noise of the Animal class.
[Animal.new, Dog.new, Cat.new].each do |animal| puts animal.make_noise animal.sleep end

We create an instance of each class. We call make_noise and sleep methods on the objects.
$ ./polymorhism.rb Some noise Animal is sleeping. Woof! Dog is sleeping. Meow! Cat is sleeping.

This is the output of the polymorhism.rb script.

Modules
A Ruby Module is a collection of methods, classes and constants. Modules are similar to classes with a few differences. Modules cannot have instances and cannot subclasses. Modules 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 C# namespaces and Java packages.

163

Modules also support the use of mixins in Ruby. A mixin is a Ruby facility to create multiple inheritance. If a class inherits functionality from more than one class, we speak of multiple inheritance.
#!/usr/bin/ruby puts Math::PI puts Math.sin 2

Ruby has a built-in Math module. It has multiple methods and a constant. We access the PI constant by using the :: operator. Methods are accessed by a dot operator as in classes.
#!/usr/bin/ruby include Math puts PI puts sin 2

If we include a module in our script, we can refer to the Math objects directly, omitting the Math name. Modules are added to a script using the include keyword.
$ ./modules.rb 3.141592653589793 0.9092974268256817

Output of the program.

In the following example, we show how modules can be used to organize code.
#!/usr/bin/ruby module Forest class Rock ; end class Tree ; end class Animal ; end end module Town class class class class end p Forest::Tree.new p Forest::Rock.new p Town::Cinema.new p Forest::Animal.new p Town::Animal.new Pool ; Cinema Square Animal end ; end ; end ; end

164

Ruby code can be grouped semantically. Rocks and trees belong to a forest. Pools, cinemas, squares belong to a town. By using modules our code has some order. Animals can be in a forest and in a town too. In a single script, we cannot define two animal classes. They would clash. Putting them in different modules we solve the issue.
p Forest::Tree.new p Forest::Rock.new p Town::Cinema.new

We are creating objects that belong to a forest and to a town. To access an object in a module, we use the :: operator.
p Forest::Animal.new p Town::Animal.new

Two different animal objects are created. The Ruby interpreter can tell between them. It identifies them by their module name.
$ ./modules3.rb #<Forest::Tree:0x97f35ec> #<Forest::Rock:0x97f35b0> #<Town::Cinema:0x97f3588> #<Forest::Animal:0x97f3560> #<Town::Animal:0x97f3538>

This is the output of the modules3.rb program.

The final code example of this section will demonstrate multiple inheritance using Ruby modules. In this context the modules are called mixins.
#!/usr/bin/ruby module Device def switch_on ; puts "on" end def switch_off ; puts "off" end end module Volume def volume_up ; puts "volume up" end def vodule_down ; puts "volume down" end end module Pluggable def plug_in ; puts "plug in" end def plug_out ; puts "plug out" end end class CellPhone include Device, Volume, Pluggable def ring puts "ringing" end

end

165

cph = CellPhone.new cph.switch_on cph.volume_up cph.ring

We have three modules and one class. The modules represent some functionality. A device can be swiched on and off. Many objects can share this functionality, including televisions, mobile phones, computers or refrigerators. Rather than creating this ability to be swiched on/off 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 organized and more compact.
module Volume def volume_up ; puts "volume up" end def vodule_down ; puts "volume down" end end

A Volume module organizes methods that are responsible for controlling the volume level. If a device needs these methods, it simply includes the module to its class.
class CellPhone include Device, Volume, Pluggable def ring puts "ringing" end end

A cell phone adds all three modules with the include method. The methods of the modules are mixed in the CellPhone class. And are available for the instances of the class. The CellPhone class has also its own ring method that is specific to it.
cph = CellPhone.new cph.switch_on cph.volume_up cph.ring

A CellPhone object is created and we call three methods upon the object.
$ ./mixins.rb on volume up ringing

Running the example gives this output.

Exceptions
Exceptions are objects that signal deviations from the normal flow of program execution. Exceptions are raised, thrown or initiated. During the execution of our application, many things might go wrong. A disk might get full and we cannot save our file. An Internet connection might go down and our application tries to connect to a site. All these might result in a crash of our application. To prevent this from

166

happening, we should anticipate and respond to errors in expected program operation. For this, we can use the exception handling. Exceptions are objects. They are descendants of a built-in Exception class. Exception objects carry information about the exception. Its type (the exceptions class name), an optional descriptive string, and optional traceback information. Programs may subclass Exception, or more often StandardError, to obtain custom Exception objects that provide additional information about operational anomalies.
#!/usr/bin/ruby x = 35 y = 0 begin z = x / y puts z rescue => e puts e p e end

In the above program, we intentionally divide a number by zero. This leads to an error.
begin z = x / y puts z

Statements that can fail are placed after the begin keyword.
rescue => e puts e p e end

In the code following the rescue keyword, we deal with an exception. In this case, we print the error message to the console. The e is an exception object that is created when the error occurs.
$ ./zerodivision.rb divided by 0 #<ZeroDivisionError: divided by 0>

In the output of the example, we see the message of the exception. The last line shows the exception object called ZeroDivisionError.

A programmer may raise exceptions himself using the raise keyword.


#!/usr/bin/ruby age = 17 begin if age < 18

167

end

raise "Person is a minor"

puts "Entry allowed" rescue => e puts e p e exit 1 end

The entrance to a club is not allowed for people younger than 18 years. We simulate this situation in our Ruby script.
begin if age < 18 raise "Person is a minor" end puts "Entry allowed"

If the person is a minor, an exception is raised. If the raise keyword does not have a specific exception as a parameter, a RuntimeError exception is raised setting its message to the given string. The code does not reach the puts "Entry allowed" line. The execution of the code is interrupted and it continues at the rescue block.
rescue => e puts e p e exit 1 end

In the rescue block, we print the error message and the string representation of the RuntimeError object. We also call the exit method to inform the environment that the execution of the script ended in error.
$ ./raise_exception.rb Person is a minor #<RuntimeError: Person is a minor> $ echo $? 1

The person, a minor, was not allowed to enter the club. The bash $? variable is set to the exit error of the script.

Ruby's ensure clause creates a block of code that always executes, whether there is an exception or not.
#!/usr/bin/ruby begin f = File.open("stones", "r") while line = f.gets do puts line end

168

rescue => e puts e p e ensure f.close if f end

In the code example, we try to open and read the stones file. I/O operations are error prone. We could easily have an exception.
ensure f.close if f end

In the ensure block we close the file handler. We check if the handler exists because it might not have been created. Allocated resources are often placed in the ensure block.

We can create our own custom exceptions if we want. Custom exceptions in Ruby should inherit from the StandardError class.
#!/usr/bin/ruby class BigValueError < StandardError ; end LIMIT = 333 x = 3_432_453 begin if x > LIMIT raise BigValueError, "Exceeded the maximum value" end puts "Script continues" rescue => e puts e p e exit 1 end

Let's say we have a situation in which we cannot deal with big numbers.
class BigValueError < StandardError ; end

We have a BigValueError class. This class derives from the built-in StandardError class.
LIMIT = 333

Numbers which exceed this constant are considered to be "big" by our program.
if x > LIMIT raise BigValueError, "Exceeded the maximum value" end

169

If the value is bigger than the limit, we throw our custom exception. We give the exception a message "Exceeded the maximum value".
$ ./custom_exception.rb Exceeded the maximum value #<BigValueError: Exceeded the maximum value>

Running the program. In this chapter we finished talking about object-oriented programming in Ruby language.

Regular expressions in Ruby


In this part of the Ruby tutorial, we will talk about Regular expressions in Ruby. Regular expressions are used for text searching and more advanced text manipulation. Regular expressions are built into tools like grep, sed; text editors like vi, emacs; programming languages like Tcl, Perl, Python. Ruby has a built-in support for regular expressions too. From another point of view, regular expression syntax constitutes a domain specific language for matching text. A pattern is a regular expression that defines the text we are searching for or manipulating. It consists of text literals and metacharacters. The pattern is placed inside two delimiters. In Ruby these are // characters. They inform the regex function where the pattern starts and ends. Here is a partial list of metacharacters: . * [] [^ ] ^ $ | Matches any single character. Matches the preceding element zero or more times. Bracket expression. Matches a character within the brackets. Matches a single character, that is not contained within the brackets. Matches the starting position within the string. Matches the ending position within the string. Alternation operator.

The =~ operator matches the regular expression against a string, and it returns either the offset of the match from the string if it is found, otherwise nil. The Regexp class is used to develop regular expressions. There are also two shorthand ways to create regular expressions. The following example will show them.
#!/usr/bin/ruby re = Regexp.new 'Jane' p "Jane is hot".match re p "Jane is hot" =~ /Jane/ p "Jane is hot".match %r{Jane}

170

In the first example, we show three ways of applying regular expressions on a string.
re = Regexp.new 'Jane' p "Jane is hot".match re

In the above two lines, we create a Regexp object cointaining a simple regular expression text. Using the match method, we apply this regular expression object on the "Jane is hot" sentence. We check, if the word 'Jane' is inside the sentence.
p "Jane is hot" =~ /Jane/ p "Jane is hot".match %r{Jane}

These two lines do the same. Two forward slashes // and the %r{} 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.
$ ./regex.rb #<MatchData "Jane"> 0 #<MatchData "Jane">

In all three cases there is a match. The match method returns a matched data, or nil if there is no match. The =~ operator returns the first character of the matched text, or nil otherwise.

The dot character


The dot character is a regular expression character, which matches any single character. Note that there must be some character; it may not be omitted.
#!/usr/bin/ruby p p p p "Seven".match /.even/ "even".match /.even/ "eleven".match /.even/ "proven".match /.even/

In the first example, we will use the match method to apply regular expression on strings. The match method returns the matched data on success or nil otherwise.
p "Seven".match /.even/

The "Seven" is the string on which we call the match method. The parameter of the method is the pattern. The /.even/ regular pattern looks for a text that starts with an arbitrary character followed by the 'even' characters.
$ ./dot.rb #<MatchData "Seven"> nil #<MatchData "leven"> nil

From the output we can see which strings did match and which did not.

171

As we have said above, if there is a dot character, there must be an arbitrary character. It may not be omitted. What if we wanted to search for a text, in which the character might be omitted? In other words, we want a pattern for both 'seven' and 'even'. For this, we can use a ? repetition character. The ? repetition character tells that the previous character may be present 0 or 1 time.
#!/usr/bin/ruby p "seven".match /.even/ p "even".match /.even/ p "even".match /.?even/

The script uses the ? repetition character.


p "even".match /.even/

This line prints nil since the regular expression expects one character before the 'even' string.
p "even".match /.?even/

Here we have slightly modified the regular expression. The '.?' stands for no character or one arbitrary character. This time there is a match.
$ ./dot2.rb #<MatchData "seven"> nil #<MatchData "even">

This is the example output.

Regular expression methods


In the previous two examples, we have used the match method to work with regular expressions. Other methods besides match accept regular expressions as parameters.
#!/usr/bin/ruby puts "motherboard" =~ /board/ puts "12, 911, 12, 111"[/\d{3}/] puts "motherboard".gsub /board/, "land" p "meet big deep nil need".scan /.[e][e]./ p "This is Sparta!".split(/\s/)

The example shows some methods that can work with regular expressions.
puts "motherboard" =~ /board/

The =~ is an operator that applies the regular expression on the right to the string on the left.
puts "12, 911, 12, 111"[/\d{3}/]

172

Regular expressions can be placed between the square brackets following the string. This line prints the first string which has three digits.
puts "motherboard".gsub /board/, "land"

With the gsub method we replace a 'board' string with a 'land' string.
p "meet big deep nil need".scan /.[e][e]./

The scan method looks for matches in the string. It looks for all occurences, not just the first one. The line prints all strings that match the pattern.
p "This is Sparta!".split(/\s/)

The split method splits a string using a given regular expression as a separator. The \s character type stands for any whitespace character.
$ ./apply.rb 6 911 motherland ["meet", "deep", "need"] ["This", "is", "Sparta!"]

We see the output of the apply.rb script.

Special variables
Some of the methods that work with regular expressions 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 make the job easier for a programmer.
#!/usr/bin/ruby puts "Her name is Jane" =~ /name/ p $` p $& p $'

The example shows three special variables.


puts "Her name is Jane" =~ /name/

In this line we have a simple regular expression matching. We look for a 'name' string inside the 'Her name is Jane' sentence. We use the =~ operator. This operator also sets three special variables. The line returns number 4, which is the position on which the match starts.
p $`

The $` special variable contains the text before the last match.
p $&

173

The $& has the matched text.


p $'

And the $' variable contains the text after the last match.
$ ./svars.rb 4 "Her " "name" " is Jane"

This is the output of the example.

Anchors
Anchors match positions of characters inside a given text. We present three anchoring characters. The ^ character matches the beginning of the line. The $ character matches the end of the line. The \b character matches word boundaries.
#!/usr/bin/ruby sen1 = "Everywhere I look I see Jane" sen2 = "Jane is the best thing that happened to me" p sen1.match /^Jane/ p sen2.match /^Jane/ p sen1.match /Jane$/ p sen2.match /Jane$/

In the first example, we work with the ^ and the $ anchoring characters.
sen1 = "Everywhere I look I see Jane" sen2 = "Jane is the best thing that happened to me"

We have two sentences. The word 'Jane' is located at the beginning of the first one and at the end of the second one.
p sen1.match /^Jane/ p sen2.match /^Jane/

Here we look if the word 'Jane' is at the beginning of the two sentences.
p sen1.match /Jane$/ p sen2.match /Jane$/

Here we look for a match of a text at the end of the sentences.


$ ./anchors.rb nil #<MatchData "Jane"> #<MatchData "Jane"> nil

174

These are the results.

A common request is to include only a match of a whole word. By default we count any match, including a match in larger or compound words. Let us look at an example to clarify things.
#!/usr/bin/ruby text = "The cat also known as the domestic cat is a small, usually furry, domesticated, carnivorous mammal." p text.scan /cat/ p $` p $& p $'

We have a sentence. And within this sentence, we look for a string cat. Using scan, we look for all 'cat' strings in the sentencenot just the first occurence.
text = "The cat also known as the domestic cat is a small, usually furry, domesticated, carnivorous mammal."

The problem is that inside the text there are three 'cat' strings. In addition to matching the 'cat' that refers to the mammal, /cat/ matches letters 8-10 inside the word 'domesticated'. Which is not what we are looking for in this case.
$ ./boudaries.rb ["cat", "cat", "cat"] "The cat also known as the domestic cat is a small, \nusually furry, domesti" "cat" "ed, carnivorous mammal."

This last match on 'domesticated' will be eliminated in the next example, using the \b anchor.

The \b character is used to set boundaries to the words we are looking for.
#!/usr/bin/ruby text = "The cat also known as the domestic cat is a small, usually furry, domesticated, carnivorous mammal." p text.scan /\bcat\b/ p $` p $& p $'

The example is improved by including the \b metacharacter.


p text.scan /\bcat\b/

175

With the above regular expression, we look for 'cat' strings as whole words. We do not count subwords.
$ ./boudaries2.rb ["cat", "cat"] "The cat also known as the domestic " "cat" " is a small, \nusually furry, domesticated, carnivorous mammal."

This time there are two matches. And the special variables show correctly the text before and after the last match.

Character classes
We can combine characters into character classes with the square brackets. A character class matches any character that is specified in the brackets. The /[ab]/ pattern means a or b, as opposed to /ab/ which means a followed by b.
#!/usr/bin/ruby words = %w/ sit MIT fit fat lot pad / pattern = /[fs]it/ words.each do |word| if word.match pattern puts "#{word} matches the pattern" else puts "#{word} does not match the pattern" end end

We have an array of six three letter words. We apply a regular expression on the strings of the array with a specific character set.
pattern = /[fs]it/

This is the pattern. The pattern looks for 'fit' and 'sit' strings in the array. We use either 'f' or 's' from the character set.
$ ./classes.rb sit matches the pattern MIT does not match the pattern fit matches the pattern fat does not match the pattern lot does not match the pattern pad does not match the pattern

There are two matches.

In the next example we will further explore the character classes.


#!/usr/bin/ruby

176

p "car".match %r{[abc][a][rs]} p "car".match /[a-r]+/ p "23af 433a 4ga".scan /\b[a-f0-9]+\b/

The example has three regular expressions with character classes.


p "car".match %r{[abc][a][rs]}

The regular expression in this line consists of three character classes. Each is for one character. The [abc] is either a, b or c. The [a] is only a. The third one, [rs], is either r or s. There is a match with the 'car' string.
p "car".match /[a-r]+/

We can use a hyphen character inside the character class. The hyphen is a metacharacter denoting an inclusive range of characters: here, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, or r. Since 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 'car' strings meets these conditions.
p "23af 433a 4ga".scan /\b[a-f0-9]+\b/

In this line, we have a string consisting of three substrings. With the scan method we check for hexadicimal numbers. We have two ranges. The first, [a-f] stands for characters from a to f. The second one, [0-9] stands for numbers 0 to 9. The + specifies that these characters can be repeated multiple times. Finally, the \b metacharacters create boundaries, which accept only strings that consists of only these characters.
$ ./classes2.rb #<MatchData "car"> #<MatchData "car"> ["23af", "433a"]

This is the example output.

If the first character of a character class is a caret (^) the class is inverted. It matches any character except those which are specified.
#!/usr/bin/ruby p "ABC".match /[^a-z]{3}/ p "abc".match /[^a-z]{3}/

In the example, we use a caret character inside a character class.


p "ABC".match /[^a-z]{3}/

We look for a string having 3 letters. These letters may not be letters from a to z. The "ABC" string matches the regular expression because all three characters are uppercase characters.
p "abc".match /[^a-z]{3}/

177

This "abc" string does not match. All three characters are in the range, that is excluded from the search.
$ ./caret.rb #<MatchData "ABC"> nil

Here we have the example output.

Quantifiers
A quantifier after a token or group specifies how often that preceding element is allowed to occur.
? * + {n} {n,} {,n} {n,m} 0 or 1 match 0 or more 1 or more exactly n n or more n or less (??) range n to m

The above is a list of common quantifiers.


#!/usr/bin/ruby p "seven dig moon car lot fire".scan /\w{3}/ p "seven dig moon car lot fire".scan /\b\w{3}\b/

In the example, we want to select those words that have exactly three characters. The \w character is a word character, and \w{3} means three times the prevoius word character.
p "seven dig moon car lot fire".scan /\w{3}/

The first line simply cuts first three characters from each string. This is not exactly what we want.
p "seven dig moon car lot fire".scan /\b\w{3}\b/

This is an improved search. We put the previous pattern between the \b boundary metacharacter. Now the search will find only those words that have exactly three characters.
$ ./nchars.rb ["sev", "dig", "moo", "car", "lot", "fir"] ["dig", "car", "lot"]

Output of the example.

The {n,m} is a repetition structure for strings having from n to m characters.


#!/usr/bin/ruby

178

p "I dig moon lottery it fire".scan /\b\w{2,4}\b/

In the above example we choose words that have two, three of four characters. We again use the boundary \b metacharacter to choose whole words.
$ ./rchars.rb ["dig", "moon", "it", "fire"]

The example prints an array of words having 2-4 characters.

In the next example, we will present the ? metacharacter. A character followed by a ? is optional. Formally, the character preceding the ? may be present once or 0 times.
#!/usr/bin/ruby p "color colour colors colours".scan /colou?rs/ p "color colour colors colours".scan /colou?rs?/ p "color colour colors colours".scan /\bcolor\b|\bcolors\b|\bcolour\b|\bcolours\b/

Say we have a text in which we want to look for the colour word. The word has two distinct spellings, english 'colour' and american 'color'. We want to find both occurences, plus we want to find their plurals too.
p "color colour colors colours".scan /colou?rs/

The colou?rs pattern finds both 'colours' and 'colors'. The u character, which precedes the ? metacharacter is optional.
p "color colour colors colours".scan /colou?rs?/

The colou?rs? pattern makes the u and s characters optional. And so we find all four colour combinations.
p "color colour colors colours".scan /\bcolor\b|\bcolors\b|\bcolour\b|\bcolours\b/

The same request could be written using alternations.


$ ./qmark.rb ["colors", "colours"] ["color", "colour", "colors", "colours"] ["color", "colour", "colors", "colours"]

This is the example output.

In the last example of this section, we will show the + metacharacter. It allows the preceding character to be repeated 1 or more times.
#!/usr/bin/ruby

179

nums = %w/ 234 1 23 53434 234532453464 23455636 324f 34532452343452 343 2324 24221 34$34232/ nums.each do |num| m = num.match /[0-9]+/ if m.to_s.eql? num puts num end end

In the example, we have an array of numbers. Numbers can have one or more number characters.
nums = %w/ 234 1 23 53434 234532453464 23455636 324f 34532452343452 343 2324 24221 34$34232/

This is an array of strings. Two of them are not numbers, because they contain non-numerical characters. They must be excluded.
nums.each do |num| m = num.match /[0-9]+/ if m.to_s.eql? num puts num end

end

We go through the array and apply the regular expression on each string. The expression is [0-9]+, which stands for any character from 0..9, repeated 0 or multiple times. By default, the regular expression looks for substrings as well. In the 34$34232 the engine considers 34 to be a number. The \b boundaries do not work here because we do not have concrete characters and the engine does not know, where to stop looking. This is why we have included an if condition in the block. The string is considered a number only if the match is equal to the original string.
$ ./numbers.rb 234 1 23 53434 234532453464 23455636 34532452343452 343 2324 24221

These values are numbers.

180

Case insensitive search


We can perform a case insensitive search. A regular expression 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/ruby p "Jane".match /Jane/ p "Jane".match /jane/ p "Jane".match /JANE/ p "Jane".match /jane/i p "Jane".match /Jane/i p "Jane".match /JANE/i

The example show both case sensitive and case insensitive search.
p "Jane".match /Jane/ p "Jane".match /jane/ p "Jane".match /JANE/

In these three lines the characters must exactly match the pattern. Only the first line gives a match.
p "Jane".match /jane/i p "Jane".match /Jane/i p "Jane".match /JANE/i

Here we use the i option, which followes the second / character. We do case insensitive search. All three lines do match.
$ ./icase.rb #<MatchData "Jane"> nil nil #<MatchData "Jane"> #<MatchData "Jane"> #<MatchData "Jane">

This is the output of the example.

Alternation
The next example explains the alternation operator (|). This operator enables to create a regular expression with several choices.
#!/usr/bin/ruby names = %w/Jane Thomas Robert Lucy Beky John Peter Andy/ pattern = /Jane|Beky|Robert/ names.each do |name|

181

if name =~ pattern puts "#{name} is my friend" else puts "#{name} is not my friend" end end

We have 8 names in the names array. We will look for a multiple combination of strings in that array.
pattern = /Jane|Beky|Robert/

This is the search pattern. It says, Jane, Beky and Robert are my friends. If you find either of them, you have found my friend.
$ ./alternation.rb Jane is my friend Thomas is not my friend Robert is my friend Lucy is not my friend Beky is my friend John is not my friend Peter is not my friend Andy is not my friend

Here we see the output of the script.

Subpatterns
We can use parentheses () to create subpatterns inside patterns.
#!/usr/bin/ruby p p p p "bookworm" =~ /book(worm)?$/ "book" =~ /book(worm)?$/ "worm" =~ /book(worm)?$/ "bookstore" =~ /book(worm)?$/

We have the following regex pattern: book(worm)?$. The (worm) is a subpattern. Only two strings can match: either 'book' or 'bookworm'. The ? character follows the subpattern, which means, that the subpattern might appear 0, 1 time in the final pattern. The $ character is here for the exact end match of the string. Without it, words like bookstore and bookmania would match too.
#!/usr/bin/ruby p p p p "book" =~ /book(shelf|worm)?$/ "bookshelf" =~ /book(shelf|worm)?$/ "bookworm" =~ /book(shelf|worm)?$/ "bookstore" =~ /book(shelf|worm)?$/

Subpatterns are often combined with alternation to create multiple word combinations. For example, book(shelf|worm) matches 'bookshelf' and 'bookworm', and book(shelf|worm)? matches 'bookshelf', 'bookworm', and 'book'. 182

$ ./subpatterns2.rb 0 0 0 nil

The last subpattern does not match. Remember that the 0s do not mean that there was no match. For the =~ operator, it is the index of the first character of the matched string.

Email example
In the final example, we create a regex pattern for checking email addresses.
#!/usr/bin/ruby emails = %w/ luke@gmail.com andy@yahoo.com 23214sdj^as f3444@gmail.com / pattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,5}$/ emails.each do |email| if email.match pattern puts "#{email} matches" else puts "#{email} does not match" end end

Note that this example provides only one solution. It does not have to be the best one.
emails = %w/ luke@gmail.com andy@yahoocom 23214sdj^as f3444@gmail.com /

This is an array of emails. Only two of them are valid.


pattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,5}$/

This is the pattern. The first ^ and the last $ characters are here to get an exact pattern match. No 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 nickname. The [a-zA-Z0-9._-]+ 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 @ character. The third part is the domain part. It is usually the domain name of the email provider: e.g., yahoo or gmail. The character set [a-zA-Z0-9-]+ specifies all characters that can be used in the domain name. The + quantifier makes use of one or more of these characters. The fourth part is the dot character. It is preceded by the escape character. (\.) This is because the dot character is a metacharacter and has a special meaning. By escaping it, we get a literal dot. The final part is the top level domain. The pattern is as follows: [a-zA-Z.]{2,5} Top level domains can have from 2 to 5 characters, like sk, net, info, travel. There is also a dot character. This is because some top level domains like co.uk have two parts.
$ ./email.rb

183

luke@gmail.com matches andy@yahoocom does not match 23214sdj^as does not match f3444@gmail.com matches

The regular expression marked two strings as valid email adresses. In this chapter, we have covered regular expressions in Ruby.

Input & output in Ruby


In this part of the Ruby tutorial, we will talk about input & output operations in Ruby. Input is any data that is read by the program, either from a keyboard, file or other programs. Output is data that is produced by the program. The output may go to the screen, to a file or to another program. Input & output is a large topic. We bring forward some examples to give you a general idea of the subject. Several classes in Ruby have methods for doing input & output operations. For example Kernel, IO, Dir or File.

Writing to console
Ruby has several methods for printing output on the console. These methods are part of the Kernel module. Methods of the Kernel are available to all objects in Ruby.
#!/usr/bin/ruby print "Apple " print "Apple\n" puts "Orange" puts "Orange"

The print and puts methods produce textual output on the console. The difference between the two is that the latter adds a new line character.
print "Apple " print "Apple\n"

The print method prints two consecutive "Apple" strings to the terminal. If we want to create a new line, we must explicitly include a newline character. The newline character is '\n'. Behind the scenes, the print method actually calls the to_s method of the object being printed.
puts "Orange" puts "Orange"

The puts method prints two strings to the console. Each is on its own line. The method includes automatically the newline character.
$ ./printing.rb Apple Apple

184

Orange Orange

This the output of the printing.rb script file. According to the Ruby documentation, the print method is an equivalent to the $stdout.print. The $stdout is a global variable which holds the standard output stream.
#!/usr/bin/ruby $stdout.print "Ruby language\n" $stdout.puts "Python language"

We print two lines using the $stdout variable. Ruby has another three methods for printing output.
#!/usr/bin/ruby p "Lemon" p "Lemon" printf "There are %d apples\n", 3 putc 'K' putc 0xA

In the example, we present the p, printf and putc methods.


p "Lemon"

The p calls the inspect method upon the object being printed. The method is useful for debugging.
printf "There are %d apples\n", 3

The printf method is well known from the C programming language. It enables string formatting.
putc 'K' putc 0xA

The putc method prints one character to the console. The second line prints a newline. The 0xA is a hexadecimal code for the newline character.
$ ./printing3.rb "Lemon" "Lemon" There are 3 apples K

This is the output of the printing3.rb program.

185

Printing data to the console using the kernel methods is a shortcut: a convenient way to print data. The following example shows a more formal way to print data to the terminal.
ios = IO.new STDOUT.fileno ios.write "ZetCode\n" ios.close

In the example, we open a standard output stream and write a string into it.
ios = IO.new STDOUT.fileno

The new method returns a stream to which we can write data. The method takes a numeric file descriptor. The STDOUT.fileno gives us the file descriptor for the standard output stream. We could also simply write 2.
ios.write "ZetCode\n"

We write a string to the opened stream.


ios.close

The input stream is closed. On Unix systems the standard terminal output is connected to a special file called /dev/tty. By opening it and writing to it, we write to a console.
#!/usr/bin/ruby fd = IO.sysopen "/dev/tty", "w" ios = IO.new(fd, "w") ios.puts "ZetCode" ios.close

A small example in which we write to a /dev/tty file. This only works on Unix.
fd = IO.sysopen "/dev/tty", "w"

The sysopen method opens the given path, returning the underlying file descriptor number.
ios = IO.new(fd, "w")

The file descriptor number is used to open a stream.


ios.puts "ZetCode" ios.close

We write a string to the stream and close it.

Reading input from console


In this section, we will create some code examples that will deal with reading from the console.

186

The $stdin is a global variable that holds a stream for the standard input. It can be used to read input from the console.
#!/usr/bin/ruby inp = $stdin.read puts inp

In the above code, we use the read method to read input from the console.
inp = $stdin.read

The read method reads data from the standard input until it reaches the end of the file. EOF is produced by pressing Ctrl + D on Unix or Ctrl + Z on Windows.
$ ./reading.rb Ruby language Ruby language

When we launch a program without a parameter, the script reads data from the user. It reads until we press Ctrl + D or Ctrl + Z.
$ echo "ZetCode" | ./reading.rb ZetCode $ ./input.rb < stones Garnet Topaz Opal Amethyst Ruby Jasper Pyrite Malachite Quartz

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 gets method.
#!/usr/bin/ruby print "Enter your name: " name = gets puts "Hello #{name}"

We use the gets method to read a line from the user.


name = gets

The gets method reads a line from the standard input. The data is assigned to the name variable.
puts "Hello #{name}"

187

The data that we have read is printed to the console. We use interpolation to include the variable in the string.
$ ./readline.rb Enter your name: Jan Hello Jan

Sample output. In the following two scripts, we will discuss the chomp 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 Perl language.
#!/usr/bin/ruby print "Enter a string: " inp = gets puts "The string has #{inp.size} characters"

We read a string from a user and calculate the length of the input string.
$ ./nochomp.rb Enter a string: Ruby The string has 5 characters

The message says that the string has 5 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 chomp method.
#!/usr/bin/ruby print "Enter a string: " inp = gets.chomp puts "The string has #{inp.size} characters"

This time we use we cut the newline character with the chomp method.
$ ./chomp.rb Enter a string: Ruby The string has 4 characters

The Ruby string has indeed 4 characters.

Files
From the official Ruby documentation we learn that the IO class is the basis for all input and output in Ruby. The File class is the only subclass of the IO class. The two classes are closely related.
#!/usr/bin/ruby

188

f = File.open('output.txt', 'w') f.puts "The Ruby tutorial" f.close

In the first example, we open a file and write some data to it.
f = File.open('output.txt', 'w')

We open a file 'output.txt' in write mode. The open method returns an io stream.
f.puts "The Ruby tutorial"

We used the above opened stream to write some data. The puts method can be used to write data to a file as well.
f.close

At the end the stream is closed.


$ ./simplewrite.rb $ cat output.txt The Ruby tutorial

We execute the script and show the contents of the output.txt file. We will have a similar example which will show additional methods in action.
#!/usr/bin/ruby File.open('langs', 'w') do |f| f.puts "Ruby" f.write "Java\n" f << "Python\n" end

If there is a block after the open method then Ruby passes the opened stream to this block. At the end of the block, the file is automatically closed.
f.puts "Ruby" f.write "Java\n" f << "Python\n"

We use three different methods to write to a file.


$ ./simplewrite2.rb $ cat langs Ruby Java Python

We execute the script and check the contents of the langs file.

189

In the second example, we show a few methods of the File class.


#!/usr/bin/ruby puts File.exists? 'tempfile' f = File.new 'tempfile', 'w' puts File.mtime 'tempfile' puts f.size File.rename 'tempfile', 'tempfile2' f.close

The example creates a new file named 'tempfile' and calls some methods.
puts File.exists? 'tempfile'

The exists? method checks if a file with a given name already exists. The line returns false, because we have not yet created the file.
f = File.new 'tempfile', 'w'

The file is created.


puts File.mtime 'tempfile'

The mtime method gives us the last modification time of the file.
puts f.size

We determine the file size. The method returns 0, since we have not written to the file.
File.rename 'tempfile', 'tempfile2'

Finally, we rename the file using the rename method.


$ ./testfile.rb false 2011-11-05 16:19:36 +0100 0

This is a sample output. Next, we will be reading data from the files on the disk.
#!/usr/bin/ruby f = File.open("stones") while line = f.gets do puts line end f.close

190

This is a simple script that will open a file called stones and print it contents line by line to the terminal.
f = File.open("stones")

We open a 'stones' file. The default mode is a read mode. The 'stones' file contains nine names of valued stones, each on a separate line.
while line = f.gets do puts line end

The gets method reads a line from the I/O stream. The while block ends when we reach the end of file.
$ ./readlines2.rb Garnet Topaz Opal Amethyst Ruby Jasper Pyrite Malachite Quartz

This is the output of the example. The next example will read data from a file.
#!/usr/bin/ruby fname = 'alllines.rb' File.readlines(fname).each do |line| puts line end

This script shows another way of reading a file's contents. The code example will print its own code to the terminal.
File.readlines(fname).each do |line| puts line end

The readlines reads all lines from the specified file and returns them in the form of an array. We go through the array with the each method and print the lines to the terminal.
$ ./alllines.rb #!/usr/bin/ruby fname = 'alllines.rb' File.readlines(fname).each do |line| puts line

191

end

Output of the example.

Directories
In this section, we work with directories. We have a Dir class to work with directories in Ruby.
#!/usr/bin/ruby Dir.mkdir "tmp" puts Dir.exists? "tmp" puts Dir.pwd Dir.chdir "tmp" puts Dir.pwd Dir.chdir '..' puts Dir.pwd Dir.rmdir "tmp" puts Dir.exists? "tmp"

In the script we use four methods of the Dir class.


Dir.mkdir "tmp"

The mkdir method makes a new directory called 'tmp'.


puts Dir.exists? "tmp"

With the exists? method, we check if a directory with a given name exists in the filesystem.
puts Dir.pwd

The pwd method prints a current working directory. This is the directory from which we launched the script.
Dir.chdir '..'

The chdir method changes to another directory. The '..' directory is the parent directory of the current working directory.
Dir.rmdir "tmp" puts Dir.exists? "tmp"

Finally, we remove a directory with the rmdir method. This time the exists? method returns false.
$ ./dirs.rb true /home/vronskij/programming/ruby/io /home/vronskij/programming/ruby/io/tmp /home/vronskij/programming/ruby/io

192

false

This is the output of the example. In the second example, we retrieve all of a directory's entries, including its files and subdirectories.
#!/usr/bin/ruby fls = Dir.entries '.' puts fls.inspect

The entries method returns all entries of a given diretory.


fls = Dir.entries '.' puts fls.inspect

We get the array of files and directories of a current directory. The '.' character stands for the current working directory in this context. The inspect method gives us a more readable representation of the array.
$ ./allfiles.rb ["putc.rb", "simplewrite.rb", "readlines2.rb", "fileexists.rb~" ...

In the output we can see an array of files and directories. The third example works with a home directory. Every user in a computer has a unique 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/ruby puts Dir.home puts Dir.home 'root'

The script prints two home directories.


puts Dir.home

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. Someone, who has launched the script.
puts Dir.home 'root'

Here we print the home directory of a specific user: in our case, the superuser.
$ ./homedir.rb /home/vronskij /root

This is a sample output.

193

Executing external programs


Ruby has several ways to execute external programs. We will deal with some of them. In our examples we will use well known Linux commands. Readers with Windows or Mac can use commands specific for their systems.
#!/usr/bin/ruby data = system 'ls' puts data

We call a ls command which lists directory contents.


data = system 'ls'

The system command executes an external program in a subshell. The method belongs to the Kernel Ruby module.
$ ./system.rb allfiles.rb characters.rb fileexists.rb homedir.rb~ ...

This is a sample output. We show two other ways of running external programs in Ruby.
#!/usr/bin/ruby out = `pwd` puts out out = %x[uptime] puts out out = %x[ls | grep 'readline'] puts out

To run external programs we can use backticks `` or %x[] characters.


out = `pwd`

Here we execute the pwd command using backticks. The command returns the current working directory.
out = %x[uptime]

Here we get the output of the uptime command, which tells how long a system is running.
out = %x[ls | grep 'readline']

We can use also a combination of commands.


$ ./system2.rb /home/vronskij/programming/ruby/io 22:50:50 up 5:32, 1 user, load average: 0.46, 0.44, 0.45

194

readline.rb readline.rb~ readlines2.rb readlines2.rb~

This is a sample output. We can execute a command with the open method. The method belongs to the Kernel module. It creates an IO object connected to the given stream, file, or subprocess. If we want to connect to a subprocess, we start the path of the open with a pipe character (|).
#!/usr/bin/ruby f = open("|ls -l |head -3") out = f.read puts out f.close puts $?.success?

In the example, we print the outcome of the ls -l | head -3 commands. The combination of these two commands returns the first three lines of the ls -l command. We also check the status of the child subprocess.
f = open("|ls -l |head -3")

We connect to a subprocess, created by these two commands.


out = f.read puts out

We read and print data from the subprocess.


f.close

We close the file handler.


puts $?.success?

The $? is a special Ruby variable that is set to the status of the last executed child process. The success? method returns true if the child process ended OK.
$ ./system3.rb total 148 -rwxr-xr-x 1 vronskij vronskij -rwxr-xr-x 1 vronskij vronskij true

57 2011-10-30 23:33 allfiles.rb 58 2011-10-30 23:33 allfiles.rb~

This is a sample output.

195

Redirecting standard output


Ruby has predefined global variables for standard input, standard output and standard error output. The $stdout is the name of the variable for the standard output.
#!/usr/bin/ruby $stdout = File.open "output.log", "a" puts "Ruby" puts "Java" $stdout.close $stdout = STDOUT puts "Python"

In the above example, we redirect a standard output to the output.log file.


$stdout = File.open "output.log", "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 exist yet, it is created. Otherwise it is opened and the data is written at the end of the file.
puts "Ruby" puts "Java"

We print two strings. The strings will not be shown in the terminal as usual. Rather, they will be appended to the output.log file.
$stdout.close

The handler is closed.


$stdout = STDOUT puts "Python"

We use a predefined standard constant STDOUT to recreate the normal standard ouput. The "Python" string is printed to the console. In this part of the Ruby tutorial, we worked with input and output operations in Ruby.

196

SQLite Ruby tutorial


This is a Ruby programming tutorial for the SQLite database. It covers the basics of SQLite programming with Ruby. It uses the sqlite3 module. The examples were created and tested on Linux.

SQLite & Ruby


SQLite is an embedded relational database engine. It is a self-contained, serverless, zeroconfiguration and transactional SQL database engine. SQLite implements most of the SQL92 standard for SQL. The SQLite engine is not a standalone process. Instead, it is statically or dynamically linked into the application. An SQLite database is a single ordinary disk 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 framework.

Connecting to the SQLite database


This part of the SQLite Ruby tutorial will show you how to connect to a database and do a few simple things with the database.

Before we start
The SQLite comes with the sqlite3 command line utility. It can be used to issue SQL commands against a database. Now we are going to use the sqlite3 command line tool to create a new database.
$ sqlite3 test.db SQLite version 3.6.22 Enter ".help" for instructions Enter SQL statements terminated with a ";"

We provide a parameter to the sqlite3 tool. The test.db is a database name. It is a single file on our disk. If it is present, it is opened. If not, it is created.
sqlite> .tables sqlite> .exit $ ls test.db

The .tables command gives a list of tables in the test.db database. There are currently no tables. The .exit command terminates the interactive session of the sqlite3 command line tool. The ls Unix command shows the contents of the current working directory. We can see the test.db file. All data will be stored in this single file.

197

The sqlite-ruby interface is used to interact with SQLite database with the Ruby language.
$ sudo apt-get install libsqlite3-ruby

The above command installs the module on Debian based Linux systems. The first step is to create a Database object. The Database class encapsulates a single connection to an SQLite database. The database object is closed with the close method.
SQLite3::Database.new dbname SQLite3::Database.open dbname

The new method creates a new Database object that opens the given dbname file. If the file does not exist, it will be created if possible. By default, the new database will return result rows as arrays. The open method opens the database contained in the given file.
SQLite3::Database.new ":memory:"

It is possible to create an in-memory database if we provide a special string ":memory:" for the file name.

Sources
The sqlite-ruby.rubyforge.org website was consulted when creating this tutorial.

Version
In the first code example, we will get the version of the SQLite database.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.new ":memory:" puts db.get_first_value 'SELECT SQLITE_VERSION()' rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

In the above Ruby script we create a new in-memory database. We execute an SQL statement which returns the version of the SQLite database.
require 'sqlite3'

We use sqlite3 Ruby module to connect to the SQLite database.

198

db = SQLite3::Database.new ":memory:"

We create a new database object. The Database class encapsulates a single connection to an SQLite database. The database is created in memory. So it is not permanent.
puts db.get_first_value 'SELECT SQLITE_VERSION()'

We call the get_first_value method of the db object. It executes the SQL statement and obtains the first value of the first row of a result set.
rescue SQLite3::Exception => e puts "Exception occured" puts e

We check for errors. This is important, since working with databases is error prone.
ensure db.close if db end

In the end, we release the resources.


$ ./version.rb 3.7.7

The output might look like the above.

Inserting data
We will create a Cars table and insert several rows to it.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db" db.execute "CREATE TABLE IF NOT EXISTS Cars(Id INTEGER PRIMARY KEY, Name TEXT, Price INT)" db.execute "INSERT INTO Cars VALUES(1,'Audi',52642)" db.execute "INSERT INTO Cars VALUES(2,'Mercedes',57127)" db.execute "INSERT INTO Cars VALUES(3,'Skoda',9000)" db.execute "INSERT INTO Cars VALUES(4,'Volvo',29000)" db.execute "INSERT INTO Cars VALUES(5,'Bentley',350000)" db.execute "INSERT INTO Cars VALUES(6,'Citroen',21000)" db.execute "INSERT INTO Cars VALUES(7,'Hummer',41400)" db.execute "INSERT INTO Cars VALUES(8,'Volkswagen',21600)" rescue SQLite3::Exception => e puts "Exception occured" puts e ensure

199

end

db.close if db

The above script creates a Cars table and inserts 8 rows into the table.
db = SQLite3::Database.open "test.db"

We connect to the test.db database.


db.execute "CREATE TABLE IF NOT EXISTS Cars(Id INTEGER PRIMARY KEY, Name TEXT, Price INT)"

The execute method executes the given SQL statement. A new Cars table is created if it does not already exist.
db.execute "INSERT INTO Cars VALUES(1,'Audi',52642)" db.execute "INSERT INTO Cars VALUES(2,'Mercedes',57127)"

These two lines insert two cars into the table. Note that by default, we are in the autocommit mode, where all changes to the table are immediately effective.
sqlite> .mode column sqlite> .headers on

We verify the written data with the sqlite3 tool. First we modify the way the data is displayed in the console. We use the column mode and turn on the headers.
sqlite> SELECT * FROM Cars; Id Name Price ---------- ---------- ---------1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 8 Volkswagen 21600

This is the data that we have written to the Cars table.

The last inserted row id


Sometimes we need to determine the id of the last inserted row. We use the last_insert_row_id method to find it.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.new ":memory:" db.execute "CREATE TABLE Friends(Id INTEGER PRIMARY KEY, Name TEXT)"

200

db.execute db.execute db.execute db.execute db.execute

"INSERT "INSERT "INSERT "INSERT "INSERT

INTO INTO INTO INTO INTO

Friends(Name) Friends(Name) Friends(Name) Friends(Name) Friends(Name)

VALUES VALUES VALUES VALUES VALUES

('Tom')" ('Rebecca')" ('Jim')" ('Robert')" ('Julian')"

id = db.last_insert_row_id puts "The last id of the inserted row is #{id}" rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

We create a Friends table in memory. The Id is automatically incremented.


db.execute "CREATE TABLE Friends(Id INTEGER PRIMARY KEY, Name TEXT)"

In SQLite, INTEGER PRIMARY KEY column is auto incremented. There is also an AUTOINCREMENT keyword. When used in INTEGER PRIMARY KEY AUTOINCREMENT a slightly different algorithm for Id creation is used.
db.execute db.execute db.execute db.execute db.execute "INSERT "INSERT "INSERT "INSERT "INSERT INTO INTO INTO INTO INTO Friends(Name) Friends(Name) Friends(Name) Friends(Name) Friends(Name) VALUES VALUES VALUES VALUES VALUES ('Tom')" ('Rebecca')" ('Jim')" ('Robert')" ('Julian')"

These five SQL statements insert five rows into the Friends table.
id = db.last_insert_row_id

Using the last_insert_row_id method, we get the last inserted row id.
$ ./last_rowid.rb The last id of the inserted row is 5

We see the output of the script.

Fetching data
In the last example of this chapter we fetch some data. More about data fetching will be discussed in the Queries chapter.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db"

201

stm = db.prepare "SELECT * FROM Cars LIMIT 5" rs = stm.execute rs.each do |row| puts row.join "\s" end rescue SQLite3::Exception => e puts "Exception occured" puts e ensure stm.close if stm db.close if db end

In the example we fetch 5 rows from the Cars table.


stm = db.prepare "SELECT * FROM Cars LIMIT 5" rs = stm.execute

We prepare an SQL statement for execution with the prepare method. The method returns a statement object. Then the SQL statement is executed using the execute method. It returns a result set. The ResutlSet object is a simple cursor over the data that the query returns.
rs.each do |row| puts row.join "\s" end

With the each 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 2 3 4 5 ./fetch.rb Audi 52642 Mercedes 57127 Skoda 9000 Volvo 29000 Bentley 350000

This is the output of the fetch.rb script. In this chapter of the SQLite Ruby tutorial, we have shown how to establish a database connection to the SQLite database. We have explained scripts which do some basic work with a database.

Queries
We have already established a connection to the database. Now we are going modify and fetch the data from the database. Data is retrieved from the database with the SELECT statement. In SQLite Ruby module, first we prepare the SQL statement with the prepare method. The SQL string is sent to the database engine, which checks the statement validity, syntax and in some databases also the 202

user permissions to perform certain queries. If all is OK, a statement object is returned to the Ruby script. The next step is the call to the execute method. The method executes the query within the database. The data is retrieved. The Ruby SQLite module has several methods to fetch data from database tables. After the SQL statement was prepared and executed, we can go through the returned data.

Fetching data
In the first example we fetch one row from the Cars table.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.new "test.db" id = 1 stm = db.prepare "SELECT * FROM Cars WHERE Id=?" stm.bind_param 1, id rs = stm.execute row = rs.next puts row.join "\s" rescue SQLite3::Exception => e puts "Exception occured" puts e ensure stm.close if stm db.close if db end

In the example we do all the steps to get the first row from the Cars table.
stm = db.prepare "SELECT * FROM Cars WHERE Id=?"

The SELECT statement is prepared with the prepare method. A statement object is returned.
stm.bind_param 1, id

A parameter is bound to the placeholder in the statement.


rs = stm.execute

The statement is executed. A ResultSet object is returned.


row = rs.next

203

We obtain the next row from the result set. Since we want to fetch only one row, we call the next method once.
puts row.join "\s"

The row is a Ruby array. The three fields are joined with a space character to form a line using the join method.
$ ./fetch.rb 1 Audi 52642

This is the output of the example.

In the following example, we will fetch five rows. We put the next method in a while loop.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db" stm = db.prepare "SELECT * FROM Cars LIMIT 5" rs = stm.execute while (row = rs.next) do puts row.join "\s" end rescue SQLite3::Exception => e puts "Exception occured" puts e ensure stm.close if stm db.close if db end

In this script we connect to the database and fetch 5 rows of the Cars table.
stm = db.prepare "SELECT * FROM Cars LIMIT 5"

This is the SQL statement for fetching 5 rows.


while (row = rs.next) do puts row.join "\s" end

The next method is put inside the while loop. It returns the next row from the result set. If no more rows are left, the method returns nil and the while loop is terminated.

204

We can get data from the result set using the each method.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db" stm = db.prepare "SELECT * FROM Cars LIMIT 5" rs = stm.execute rs.each do |row| puts row.join "\s" end rescue SQLite3::Exception => e puts "Exception occured" puts e ensure stm.close if stm db.close if db end

Again we select five rows from the Cars table.


rs.each do |row| puts row.join "\s" end

We use the each method to iterate over the result set.

The next example shows the database object's execute method. It is a convenience method that saves a few keystrokes.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db" rows = db.execute "SELECT * FROM Cars LIMIT 5" for row in rows do puts row.join "\s" end rescue SQLite3::Exception => e puts "Exception occured" puts e

205

ensure db.close if db end

The example selects and prints five rows from the Cars table.
rows = db.execute "SELECT * FROM Cars LIMIT 5"

Here we do two jobs in one step. We prepare the statement and execute it. The method returns the data in a Ruby array.
for row in rows do puts row.join "\s" end

We print the data from the Ruby array.

So far we have seen data returned in the form of a ResultSet or an array. The next example 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/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db" db.results_as_hash = true ary = db.execute "SELECT * FROM Cars LIMIT 5" ary.each do |row| printf "%s %s %s\n", row['Id'], row['Name'], row['Price'] end rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

In the example we get fields by their column names.


db.results_as_hash = true

We set the results_as_hash property to true. All rows will be returned as Hash objects, with the column names as the keys.
ary.each do |row| printf "%s %s %s\n", row['Id'], row['Name'], row['Price'] end

206

We get the fields by their column names.


$ 1 2 3 4 5 ./fetch_hash.rb Audi 52642 Mercedes 57127 Skoda 9000 Volvo 29000 Bentley 350000

We see the output of the example.

Fetching a row or a value


Ruby SQLite module has two convenience methods for retrieving a row or a value. In the first example, we will get a single row from a table.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db" row = db.get_first_row "SELECT * FROM Cars WHERE Id=1" puts row.join "\s" rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

We get the data for the first row of the Cars table.
row = db.get_first_row "SELECT * FROM Cars WHERE Id=1"

The get_first_row method gets the first row and discards all other rows.
puts row.join "\s"

The row is printed to the console.


$ ./fetchrow.rb 1 Audi 52642

Here we see the output of the fetchrow.rb example.

In the last example, we select a single value.


#!/usr/bin/ruby

207

require 'sqlite3' begin db = SQLite3::Database.open "test.db" val = db.get_first_value "SELECT Price FROM Cars WHERE Name='Bentley'" puts val rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

We select a price for a specific car.


val = db.get_first_value "SELECT Price FROM Cars WHERE Name='Bentley'"

With the get_first_value method we select a specific field of a row. In our case it is the price of the Bentley car.
$ ./fetchvalue.rb 350000

This is the output. In this part of the SQLite Ruby tutorial, we have demonstrated how to fetch data from the database using various methods.

Binding parameters
SQL statements are often dynamically built. A user provides some input and this input is built into the statement. A 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 SQL statements is to use parameter binding. When we bind parameters, we create placeholders in the statement. The placeholder is a special mark in the SQL statement. It is often a question mark (?). Later a parameter is bound to the placeholder with a bind_param, execute, query etc. methods. Binding parameters guards the program against SQL injections. It automatically escapes some special characters and allows them to be handled correctly. Database performance is often improved when statements are prepared and their parameters bound prior to statement execution. In sqlite3 Ruby module the statements are always prepared. Even if we do not call the prepare method and call directly the execute method of the database object, the statement is prepared behind the scenes by the sqlite3 Ruby module.
#!/usr/bin/ruby

208

require 'sqlite3' begin db = SQLite3::Database.new "test.db" name = "Volkswagen" stm = db.prepare "SELECT * FROM Cars WHERE Name = ?" stm.bind_param 1, name rs = stm.execute row = rs.next puts row.join "\s" rescue SQLite3::Exception => e puts "Exception occured" puts e ensure stm.close if stm db.close if db end

The example selects a row from the Cars table for a specific car name.
name = "Volkswagen"

This is a value that could come from a user: for example, from a HTML form.
stm = db.prepare "SELECT * FROM Cars WHERE Name = ?"

The question mark (?) is a placeholder for a value. It is added later in the script.
stm.bind_param 1, name rs = stm.execute

With the bind_param method, the name variable is associated with the placeholder in the statement. The execute method will return the result set.
$ ./bindparam1.rb 8 Volkswagen 21600

This is the output of the example.

Next we present another way of binding parameters.


#!/usr/bin/ruby require 'sqlite3' begin

209

db = SQLite3::Database.new "test.db" id = 4 stm = db.prepare "SELECT * FROM Cars WHERE Id = :id" rs = stm.execute id row = rs.next puts row.join "\s" rescue SQLite3::Exception => e puts "Exception occured" puts e ensure stm.close if stm db.close if db end

We select a row from the Cars table for a specific Id.


stm = db.prepare "SELECT * FROM Cars WHERE Id = :id"

Previously we have seen a question mark as a placeholder. SQLite Ruby supports named placeholders too.
rs = stm.execute id

The parameter is bound in the execute method.

We provide yet another way for binding parameters.


#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.new "test.db" id = 3 row = db.get_first_row "SELECT * FROM Cars WHERE Id = ?", id puts row.join "\s" rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

This time, everythingpreparing the statement, binding the parameter and executing the statementis done using one method.

210

row = db.get_first_row "SELECT * FROM Cars WHERE Id = ?", id

The get_first_row is a convenience method, where three things are done in one step.

In our final example, we will bind several parameters in one statement.


#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.new ":memory:" stm = db.prepare "SELECT 2 + ? + 6 + ? + ?" stm.bind_params 3, 4, 6 rs = stm.execute row = rs.next puts row rescue SQLite3::Exception => e puts "Exception occured" puts e ensure stm.close if stm db.close if db end

In the example, we have more placeholders in the SQL statement.


stm = db.prepare "SELECT 2 + ? + 6 + ? + ?"

There are three placeholders in the SELECT statement.


stm.bind_params 3, 4, 6

We bind three values with the bind_params method.


$ ./bindparams.rb 21

This is the output of the bindparams.rb program. In this part of the SQLite Ruby tutorial we talked about binding parameters.

Working with images


In this chapter of the SQLite Ruby tutorial, we will work with image files. Note that some people oppose putting images into databases. Here we only show how to do it. We do not dwell into technical issues of whether to save images in databases or not. 211

sqlite> CREATE TABLE Images(Id INTEGER PRIMARY KEY, Data BLOB);

For this example, we create a new table called Images. For the images, we use the BLOB data type, which stands for Binary Large Object.

Inserting images
In the first example, we are going to insert an image to the SQLite database.
#!/usr/bin/ruby require 'sqlite3' begin fin = File.open "woman.jpg" , "rb" img = fin.read rescue SystemCallError => e puts e ensure fin.close if fin end begin db = SQLite3::Database.open 'test.db' blob = SQLite3::Blob.new img db.execute "INSERT INTO Images VALUES(1, ?)", blob rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

We read an image from the current working directory and write it into the Images table of the SQLite test.db database.
fin = File.open "woman.jpg" , "rb" img = fin.read

We open and read a jpg image. The read method returns the data as string.
blob = SQLite3::Blob.new img

We create an instance of the SQLite3::Blob class. It is intended for working with binary data.
db.execute "INSERT INTO Images VALUES(1, ?)", blob

The image is written to the database.

212

Reading images
In this section, we are going to perform the reverse operation. We will read an image from the database table.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open 'test.db' data = db.get_first_value "SELECT Data FROM Images LIMIT 1" f = File.new "woman2.jpg", "wb" f.write data rescue SQLite3::Exception, SystemCallError => e puts "Exception occured" puts e ensure f.close if f db.close if db end

We read image data from the Images table and write it to another file, which we call woman2.jpg.
data = db.get_first_value "SELECT Data FROM Images LIMIT 1"

This line selects the image data from the table.


f = File.new "woman2.jpg", "wb" f.write data

We open a new image file and write the retrieved data into that file. Then we close the file. This part of the SQLite Ruby tutorial was dedicated to reading and writing images.

Getting database metadata


Metadata is information about the data in a database. Metadata in SQLite contains information about the tables and columns in which we store data. The number of rows that an SQL statement affects is metadata. The number of rows and columns returned in a result set are metadata as well. Metadata in SQLite can be obtained using the PRAGMA command. SQLite objects may have attributes, which are metadata. Finally, we can also obtain specific metatada from querying the SQLite system sqlite_master table.
#!/usr/bin/ruby

213

require 'sqlite3' begin db = SQLite3::Database.open "test.db" pst = db.prepare "SELECT * FROM Cars LIMIT 6" puts pst.columns puts pst.types puts pst.column_count rescue SQLite3::Exception => e puts "Exception occured" puts e ensure pst.close if pst db.close if db end

In the above example, we get the column names, column types and the number of columns of a prepared statement.
puts pst.columns puts pst.types puts pst.column_count

These three methods return the column names, column types and the number of columns of a prepared statement.
$ ./cols_fields.rb Id Name Price INTEGER TEXT INT 3

The output shows three column names: Id, Name and Price. The types are INTEGER, TEXT and INT.

The following example shows how to retrieve the number of changes produced by a particular SQL command.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.new ":memory:"

214

db.execute db.execute db.execute db.execute db.execute db.execute db.execute

"CREATE "INSERT "INSERT "INSERT "INSERT "INSERT "DELETE

TABLE Friends(Id INTEGER PRIMARY KEY, Name TEXT)" INTO Friends(Name) VALUES ('Tom')" INTO Friends(Name) VALUES ('Rebecca')" INTO Friends(Name) VALUES ('Jim')" INTO Friends(Name) VALUES ('Robert')" INTO Friends(Name) VALUES ('Julian')" FROM Friends WHERE Id IN (3, 4, 5)"

n = db.changes puts "There has been #{n} changes" rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

We create a Friends table in memory. In the last SQL command, we delete three rows. We use the changes method to get the number of changes done by the last SQL operation.
db.execute "DELETE FROM Friends WHERE Id IN (3, 4, 5)"

In this SQL statement, we delete three rows.


n = db.changes puts "There has been #{n} changes"

We find out the number of changes done by the last SQL statement.
$ ./changes.rb There has been 3 changes

Example output.

In the next example, we will find out some data about the Cars table.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db" stm = db.prepare "PRAGMA table_info('Cars')" rs = stm.execute rs.each do |row| puts row.join "\s" end rescue SQLite3::Exception => e

215

puts "Exception occured" puts e ensure stm.close if stm db.close if db end

In this example, we issue the PRAGMA table_info(tableName) command to get some metadata info about our Cars table.
stm = db.prepare "PRAGMA table_info('Cars')" rs = stm.execute

The PRAGMA table_info(Cars) command returns one row for each column in the Cars table. Columns in the result set include the column order number, column name, data type, whether or not the column can be NULL, and the default value for the column.
rs.each do |row| puts row.join "\s" end

We iterate over the result set and print the data.


$ 0 1 2 ./table_info.rb Id INTEGER 0 1 Name TEXT 0 0 Price INT 0 0

Output of the example.

Next we will print 5 rows from the Cars table with their column names.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db" rows = db.execute2 "SELECT * FROM Cars LIMIT 5" rows.each do |row| puts "%3s %-8s %s" % [row[0], row[1], row[2]] end rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

216

We print five rows of the Cars table to the console. Now, we include the names of the columns too. The records are aligned with the column names.
rows = db.execute2 "SELECT * FROM Cars LIMIT 5"

The execute2 method executes the given SQL statement. The first row returned is the names of the columns.
rows.each do |row| puts "%3s %-8s %s" % [row[0], row[1], row[2]] end

The data is retrieved, formatted and printed to the terminal.


$ ./column_names.rb Id Name Price 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000

Output.

In our last example related to the metadata, we will list all tables in the test.db database.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db" rows = db.execute <<SQL SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;" rows.each do |row| puts row end rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

SQL

The code example prints all available tables in the current database to the terminal.
rows = db.execute <<SQL SELECT name FROM sqlite_master

217

WHERE type='table' ORDER BY name;" SQL

The table names are retrieved from the sqlite_master table.


$ ./list_tables.rb Cars Friends Images

These were the tables on our system. In this part of the SQLite Ruby tutorial, we have worked with database metadata.

Transactions
In this chapter, we will work with transactions. First, we provide some basic definitions. Then we present Ruby scripts that show, how to work with transactions in Ruby sqlite3 module. We will also talk about the autocommit mode, which is essential to understand when dealing with transactions.

Definitions
A transaction is an atomic unit of database operations against the data in one or more databases. The effects of all the SQL statements in a transaction can be either all committed to the database or all rolled back. In the autocommit mode the changes are immediately effective. To work with transactions we start a transaction with the transaction method. The transaction is ended with either the commit or rollback methods. The database connection is in the autocommit mode by default. Note that the default mode depends on the driver. In the SQLite Python driver, the autocommit is turned off by default. In SQLite, any command other than the SELECT will start an implicit transaction. Also, within a transaction a command like CREATE TABLE ..., VACUUM, PRAGMA will commit previous changes before executing. Manual transactions are started with the BEGIN TRANSACTION statement and finished with the COMMIT OR ROLLBACK statements. SQLite supports three non-standard transaction levels: DEFERRED, IMMEDIATE and EXCLUSIVE.

Examples
Now we will have some scripts that work with transactions and the autocommit mode.
#!/usr/bin/ruby require 'sqlite3' begin

218

db = SQLite3::Database.open "test.db" db.execute db.execute db.execute db.execute db.execute db.execute db.execute "DROP TABLE IF EXISTS Friends" "CREATE TABLE Friends(Id INTEGER PRIMARY KEY, Name TEXT)" "INSERT INTO Friends(Name) VALUES ('Tom')" "INSERT INTO Friends(Name) VALUES ('Rebecca')" "INSERT INTO Friends(Name) VALUES ('Jim')" "INSERT INTO Friends(Name) VALUES ('Robert')" "INSERT INTO Friends(Name) VALUES ('Julian')"

rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

We create a Friends table and fill it with data. We do not explicitly start a transaction, nor do we call commit or rollback methods. Yet the data is written to the table. This is because the default working mode is autocommit. In this mode each SQL statement is immediately effective.
db.execute "DROP TABLE IF EXISTS Friends" db.execute "CREATE TABLE Friends(Id INTEGER PRIMARY KEY, Name TEXT)"

We drop the Friends table if it already exists. Then we create the table with the CREATE TABLE statement.
db.execute "INSERT INTO Friends(Name) VALUES ('Tom')" db.execute "INSERT INTO Friends(Name) VALUES ('Rebecca')" ...

We insert data.
$ ./autocommit.rb $ sqlite3 test.db SQLite version 3.7.7 2011-06-23 19:49:22 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> SELECT * FROM Friends; 1|Tom 2|Rebecca 3|Jim 4|Robert 5|Julian

We execute the script and check the table with the sqlite3 command line tool. The Friends table is succesfully created.

In the second example we will start a transaction with the transaction method.
#!/usr/bin/ruby

219

require 'sqlite3' begin db = SQLite3::Database.open "test.db" db.transaction db.execute "DROP TABLE IF EXISTS Friends" db.execute "CREATE TABLE Friends(Id INTEGER PRIMARY KEY, Name TEXT)" db.execute "INSERT INTO Friends(Name) VALUES ('Tom')" db.execute "INSERT INTO Friends(Name) VALUES ('Rebecca')" db.execute "INSERT INTO Friends(Name) VALUES ('Jim')" db.execute "INSERT INTO Friends(Name) VALUES ('Robert')" db.execute "INSERT INTO Friends(Name) VALUES ('Julian')" db.execute "INSERT INTO Friends(Name) VALUES ('Michael')" db.commit rescue SQLite3::Exception => e puts "Exception occured" puts e db.rollback ensure db.close if db end

We recreate the Friends table. After the transaction method call, every statement is within a transaction until we call the commit method. We either save all changes or save nothing. This is the basic idea behind transactions.
db.transaction

The transaction method begins a new transaction. The method takes an optional mode parameter, where we can specify the transaction level. The default level is DEFERRED.
db.commit

The changes are written to the database. If we commented the line, the changes would not be saved.
db.rollback

In case of an error, we rollback the changes.


sqlite> SELECT * FROM Friends; 1|Tom 2|Rebecca 3|Jim 4|Robert 5|Julian 6|Michael

We verify with the sqlite3 command line tool that the changes were written.

220

When there is an error in the transaction, the transaction is rolled back an no changes are committed to the database.
#!/usr/bin/ruby require 'sqlite3' begin db = SQLite3::Database.open "test.db" db.transaction db.execute "UPDATE Friends SET Name='Thomas' WHERE Id=1" db.execute "UPDATE Friend SET Name='Bob' WHERE Id=4" db.commit rescue SQLite3::Exception => e puts "Exception occured" puts e db.rollback ensure db.close if db end

In the code example we want to change two names. There are two statements that form a transaction. There is an error in the second SQL statement. Therefore the transaction is rolled back.
db.execute "UPDATE Friend SET Name='Bob' WHERE Id=4"

The name of the table is incorrect. There is no Friend table in the database.
$ ./rollingback.rb Exception occured no such table: Friend

Running the example will display this error message. The transaction is rolled back.
sqlite> SELECT * FROM Friends; 1|Tom 2|Rebecca 3|Jim 4|Robert 5|Julian

The Friends table was not changed, even though the first UPDATE statement was correct.

We will again try to change two rows, this time in autocommit mode.
#!/usr/bin/ruby require 'sqlite3'

221

begin db = SQLite3::Database.new "test.db" db.execute "UPDATE Friends SET Name='Thomas' WHERE Id=1" db.execute "UPDATE Friend SET Name='Bob' WHERE Id=4" rescue SQLite3::Exception => e puts "Exception occured" puts e ensure db.close if db end

We try to update two names in the Friends table, changing Tom to Thomas and Robert to Bob.
db.execute "UPDATE Friends SET Name='Thomas' WHERE Id=1" db.execute "UPDATE Friend SET Name='Bob' WHERE Id=4"

The second of the UPDATE statements is incorrect.


$ ./autocommit2.rb Exception occured no such table: Friend

We receive the same error message as in the previous example.


sqlite> SELECT * FROM Friends; 1|Thomas 2|Rebecca 3|Jim 4|Robert 5|Julian

However this time, the first UPDATE statement was saved. The second one was not. In this part of the SQLite Ruby tutorial, we have worked with transactions.

MySQL Ruby tutorial


This is a Ruby programming tutorial for the MySQL database. It covers the basics of MySQL programming with Ruby. It uses the mysql2 module. The examples were created and tested on Ubuntu Linux.

MySQL & Ruby


MySQL is a leading open source database management system. It is a multi user, multithreaded database management system. MySQL is especially popular on the web. It is one of the parts of the very popular LAMP platform. Linux, Apache, MySQL, PHP. Currently MySQL is owned by Oracle. MySQL database is available on most important OS

222

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 framework.

mysql2 module
The mysql2 module is a Ruby interface to the MySQL server. It provides the same functions for Ruby programs that the MySQL C API provides for C programs.
$ sudo gem1.9 install mysql2

Here we install the Ruby module for the MySQL database.

Before we start
We are going to create a new database user and a new database. To do this, we use the mysql client program.
$ mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 30 Server version: 5.0.67-0ubuntu6 (Ubuntu) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | +--------------------+ 2 rows in set (0.00 sec)

We connect to the MySQL server using the root account. We show all available databases with the SHOW DATABASES statement.
mysql> CREATE DATABASE mydb; Query OK, 1 row affected (0.02 sec)

We create a new mydb database. We will use this database throughout the tutorial.
mysql> CREATE USER user12@localhost IDENTIFIED BY '34klq*'; Query OK, 0 rows affected (0.00 sec) mysql> USE mydb; Database changed mysql> GRANT ALL ON mydb.* to user12@localhost; Query OK, 0 rows affected (0.00 sec) mysql> quit; Bye

223

We create a new database user. We grant all privileges to this user for all tables of the mydb database.

MySQL server version


In the first example, we will get the version of the MySQL database.
#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*' puts con.get_server_info rs = con.query 'SELECT VERSION()' puts rs.fetch_row rescue Mysql::Error => e puts e.errno puts e.error ensure con.close if con end

In this script, we get the server version. We do it in two different ways.


require 'mysql'

We import the mysql module. The module has the classes and methods to work with the MySQL database.
con = Mysql.new 'localhost', 'user12', '34klq*'

We 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 con.get_server_info

The Mysql object, that we have created, has a get_server_info method. It returns the version of the MySQL server installed.
rs = con.query 'SELECT VERSION()' puts rs.fetch_row

Another way to get the version is to execute the SELECT VERSION() SQL statement. We fetch the data. Since we retrieve only one record, we call the fetch_row method.
rescue Mysql::Error => e puts e.errno puts e.error

We check for errors. This is important, since working with databases is error prone.

224

ensure con.close if con end

In the end, we release the resources.


$ ./version.rb 5.5.9 5.5.9

The output might look like the above.

Listing databases
The MySQL Ruby module has a list_dbs method, which returns available databases.
#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*' con.list_dbs.each do |db| puts db end rescue Mysql::Error => e puts e.errno puts e.error ensure con.close if con end

In this script, we print all available databases on our MySQL server.


con.list_dbs.each do |db| puts db end

The list_dbs method returns an array of available database names. Using the each method of the array, we print each item of the array to the console.
$ ./listdb.rb information_schema mydb test world

On my system, I had the above databases created.

Creating and populating a table


We create a table and populate it with some data.

225

#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' con.query("CREATE TABLE IF NOT EXISTS \ Writers(Id INT PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(25))") con.query("INSERT INTO Writers(Name) VALUES('Jack London')") con.query("INSERT INTO Writers(Name) VALUES('Honore de Balzac')") con.query("INSERT INTO Writers(Name) VALUES('Lion Feuchtwanger')") con.query("INSERT INTO Writers(Name) VALUES('Emile Zola')") con.query("INSERT INTO Writers(Name) VALUES('Truman Capote')") rescue Mysql::Error => e puts e.errno puts e.error ensure con.close if con end

We create a Writers table and add five authors to it.


con.query("CREATE TABLE IF NOT EXISTS \ Writers(Id INT PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(25))")

To execute an SQL statement, we use the query method. This SQL statement creates a new database table called Writers. It has two columns. Id and Name.
con.query("INSERT INTO Writers(Name) VALUES('Jack London')") con.query("INSERT INTO Writers(Name) VALUES('Honore de Balzac')") ...

We use the INSERT statement to insert authors to the table. Here we add two rows.
mysql> SELECT * FROM Writers; +----+-------------------+ | Id | Name | +----+-------------------+ | 1 | Jack London | | 2 | Honore de Balzac | | 3 | Lion Feuchtwanger | | 4 | Emile Zola | | 5 | Truman Capote | +----+-------------------+ 5 rows in set (0.00 sec)

After executing the script, we use the mysql client tool to select all data from the Writers table.

Retrieving data
Now, that we have inserted some data into the database, we can retrieve it back.

226

#!/usr/bin/ruby require "mysql" begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' rs = con.query("SELECT * FROM Writers") n_rows = rs.num_rows puts "There are #{n_rows} rows in the result set" n_rows.times do puts rs.fetch_row.join("\s") end rescue Mysql::Error => e puts e.errno puts e.error ensure con.close if con end

In this example, we retrieve all data from the Writers table.


con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb'

The last parameter of the constructor is the database name, to which we connect.
rs = con.query("SELECT * FROM Writers")

This SQL statement selects all data from the Writers table.
n_rows = rs.num_rows

We get the number of rows in the result set using the num_rows method of the result set object.
n_rows.times do puts rs.fetch_row.join("\s") end

Here we fetch each row with the fetch_row method. It returns a row as an array of fields. By default, the fields are separated by new line, when printed. With the join method, we print each row on one line. The fields are separated by one space.
$ ./retrieve1.rb There are 5 rows in the result set 1 Jack London 2 Honore de Balzac 3 Lion Feuchtwanger 4 Emile Zola 5 Truman Capote

227

Next we present another way to retrieve data from the table.


#!/usr/bin/ruby require "mysql" begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' rs = con.query("SELECT * FROM Writers") rs.each do |row| puts row.join("\s") end rescue Mysql::Error => e puts e.errno puts e.error ensure con.close if con end

We print all data from the Writers table. This time we use an each method of the result set to traverse the data.
rs.each do |row| puts row.join("\s") end

We iterate through the result set using the each method.


$ 1 2 3 4 5 ./retrieve2.rb Jack London Honore de Balzac Lion Feuchtwanger Emile Zola Truman Capote

This is the output of the example. We can traverse data in form of a Ruby hash.
#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' rs = con.query "SELECT * FROM Writers WHERE Id IN (1, 2, 3)" puts "We have #{rs.num_rows} row(s)" rs.each_hash do |row| puts row['Id'] + " " + row['Name'] end rescue Mysql::Error => e

228

puts e ensure con.close if con end

In the example, we use the each_hash iterator. Records from the result set can be retrieved by their column names.
rs.each_hash do |row| puts row['Id'] + " " + row['Name'] end

We go through the result set with the each_hash method. Each returned row is a Ruby hash; a collection of key-value pairs. The keys are the column names.
$ ./retrieve3.rb We have 3 row(s) 1 Jack London 2 Honore de Balzac 3 Lion Feuchtwanger

Ouput of the example.

Multiple statements
MySQL supports multiple statement execution. This must be enabled by a special option.
#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' con.set_server_option Mysql::OPTION_MULTI_STATEMENTS_ON rs = con.query "SELECT Name FROM Writers WHERE Id=1; SELECT Name FROM Writers WHERE Id=2; SELECT Name FROM Writers WHERE Id=3" puts rs.fetch_row while con.next_result rs = con.store_result puts rs.fetch_row end rescue Mysql::Error => e puts e.errno puts e.error ensure con.close if con end

In this example, we have three SELECT statements in one query. 229

con.set_server_option Mysql::OPTION_MULTI_STATEMENTS_ON

First we need to enable the multiple statements processing with the Mysql::OPTION_MULTI_STATEMENTS_ON.
rs = con.query "SELECT Name FROM Writers WHERE Id=1; SELECT Name FROM Writers WHERE Id=2; SELECT Name FROM Writers WHERE Id=3"

Here we define three SELECT statements. They are separated by a semicolon.


puts rs.fetch_row

The query method returns the first result set. We fetch a row from this result set.
while con.next_result rs = con.store_result puts rs.fetch_row end

We get additional result sets until there are no more statements left to process.
$ ./multiplest.rb Jack London Honore de Balzac Lion Feuchtwanger

Running the example.

Metadata
Metadata is information about the data in the database. Metadata in a MySQL system contains information about the tables and columns, in which we store data. Number of rows affected by an SQL statement is a metadata. Number of rows and columns returned in a result set belong to metadata as well.
#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' rs = con.query "SELECT * FROM Writers WHERE Id IN (1, 2, 3)" puts "We have #{con.field_count} fields" puts "We have #{rs.num_rows} row(s)" puts rs.fetch_row.join("\s") rescue Mysql::Error => e puts e ensure con.close if con end

In this script, we find out the number of rows and columns from an SQL query. 230

rs = con.query "SELECT * FROM Writers WHERE Id IN (1, 2, 3)"

This SQL statement returns three rows. Each row has two columns.
puts "We have #{con.field_count} fields" puts "We have #{rs.num_rows} row(s)"

These two lines return the number of columns and rows in the result set. Note that here a field is a synonym for a column. The returned data is metadata.
puts rs.fetch_row.join("\s")

Here we return one row from the result set. This is the original data stored in our database table. For INSERT, DELETE and UPDATE statements there is a method called rows_affected. This method returns the number of rows affected by these three statements.
#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' con.query "DELETE FROM Writers WHERE Id IN (1, 2, 3)" puts "The query has affected #{con.affected_rows} rows" rescue Mysql::Error => e puts e ensure con.close if con end

In our example, we delete first three rows from the Writers table.
con.query "DELETE FROM Writers WHERE Id IN (1, 2, 3)"

An SQL statement, which deletes first three rows of the Writers table.
puts "The query has affected #{con.affected_rows} rows"

Here we get the number of rows, that were affected by the above SQL statement. This number belongs to the metadata.
$ ./affected.rb The query has affected 3 rows mysql> SELECT * FROM Writers; +----+---------------+ | Id | Name | +----+---------------+ | 4 | Emile Zola | | 5 | Truman Capote | +----+---------------+

231

2 rows in set (0.00 sec)

We execute the affected.rb script and check for changes in the Writers table. Three rows have been deleted. In the next example, we are going to check for metadata about a field.
#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' rs = con.query "SELECT * FROM Writers WHERE Id=1" field = rs.fetch_field_direct 1 puts puts puts puts "Table "Field "Field "Field name: #{field.table}" name: #{field.name}" length: #{field.length}" type: #{field.type}"

rescue Mysql::Error => e puts e ensure con.close if con end

We get one record from the database. We get the field's table name, colum name, length and type.
rs = con.query "SELECT * FROM Writers WHERE Id=1"

This query returns one row. It has two columns.


field = rs.fetch_field_direct 1

Using the fetch_field_direct method, we get a specific record. More precisely, the record from the intersection of the first row, second column.
puts puts puts puts "Table "Field "Field "Field name: #{field.table}" name: #{field.name}" length: #{field.length}" type: #{field.type}"

We get the metadata using attribute readers of the field object.


$ ./metadata.rb Table name: Writers Field name: Name Field length: 25 Field type: 253

This is the output of the example.

232

In our last example relating to the metadata, we will print all rows from the table with their column names.
#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' rs = con.query "SELECT * FROM Writers" fields = rs.fetch_fields puts "%3s %s" % [fields[0].name, fields[1].name] rs.each_hash do |row| puts "%3s %s" % [row['Id'], row['Name']] end rescue Mysql::Error => e puts e ensure con.close if con end

We print the contents of the Writers table to the console. Now, we include the names of the columns too.
fields = rs.fetch_fields puts "%3s %s" % [fields[0].name, fields[1].name]

In the first step, we get the column names. They are printed using the standard Ruby string formatting abilities.
rs.each_hash do |row| puts "%3s %s" % [row['Id'], row['Name']] end

Now the data is fechted and printed to the console. We do some formatting too.
$ ./columnheaders.rb Id Name 1 Jack London 2 Honore de Balzac 3 Lion Feuchtwanger 4 Emile Zola 5 Truman Capote

Ouput of the script.

Prepared statements
Now we will concern ourselves with prepared statements. When we write prepared statements, we use placeholders instead of directly writing the values into the statements. Prepared statements increase security and performance.

233

#!/usr/bin/ruby require 'mysql' name = "Stefan Zweig" begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' pst = con.prepare "INSERT INTO Writers(Name) VALUES(?)" pst.execute name rescue Mysql::Error => e puts e ensure con.close if con pst.close if pst end

In the above example, we insert a new row into the Writers table. We use a prepared statement.
pst = con.prepare "INSERT INTO Writers(Name) VALUES(?)"

The prepare method is used to create a prepared statement. The ? character is a placeholder. Later we bind a value to this placeholder.
pst.execute name

We bind a value from the name variable to the placeholder and execute the prepared statement.
pst.close if pst

The prepared statement is closed.


mysql> SELECT * FROM Writers; +----+-------------------+ | Id | Name | +----+-------------------+ | 1 | Jack London | | 2 | Honore de Balzac | | 3 | Lion Feuchtwanger | | 4 | Emile Zola | | 5 | Truman Capote | | 6 | Stefan Zweig | +----+-------------------+ 6 rows in set (0.00 sec)

After the script was successfully run, we see a new author in the Writers table.

Writing images
Some people prefer to put their images into the database, some prefer to keep them on the file system for their applications. Technical difficulties arise when we work with millions of 234

images. Images are binary data. MySQL database has a special data type to store binary data called BLOB (Binary Large Object).
mysql> CREATE TABLE Images(Id INT PRIMARY KEY AUTO_INCREMENT, Data MEDIUMBLOB); Query OK, 0 rows affected (0.06 sec)

For this example, we create a new table called Images.


#!/usr/bin/ruby require 'mysql' begin fin = File.open("woman.jpg" , "rb") img = fin.read rescue SystemCallError => e puts e ensure fin.close if fin end begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' pst = con.prepare("INSERT INTO Images SET Data='%s'" % img.unpack('H*')) pst.execute rescue Mysql::Error => e puts e ensure con.close if con pst.close if pst end

In the above script, we read a jpg image and insert it into the Images table.
fin = File.open("woman.jpg" , "rb") img = fin.read

We open and read an image. The read method returns the data as string.
pst = con.prepare("INSERT INTO Images SET Data='%s'" % img.unpack('H*'))

This string data is placed into the prepared statement. Before doing so, it is decoded using the unpack method of the Ruby string object. Decoding is necessary, because the image object has many special characters which cannot be processed normally.

235

Reading images
In the previous example, we have inserted an image into the database table. Now we are going to read the image back from the table.
#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' rs = con.query "SELECT Data FROM Images LIMIT 1" f = File.new "woman2.jpg", "wb" f.write rs.fetch_row.pack 'H*' rescue Mysql::Error, SystemCallError => e puts e ensure con.close if con f.close if f end

We read one image from the Images table.


rs = con.query "SELECT Data FROM Images LIMIT 1"

We select one record from the table.


f = File.new "woman2.jpg", "wb"

We create a writable binary file.


f.write rs.fetch_row.pack 'H*'

We fetch the data from the previous SQL statement and write it to the file. The fetch_row method returns an array object. Before the data is written to the file, it is put back into the original format with the pack method of the array. For both operations, decoding and reversing, we use the same directive, 'H*'. It stands for hex string. Now we should have an image called woman2.jpg in our current directory. We can check if it is the same image, that we have inserted into the table.

Transaction support
A transaction is an atomic unit of database operations against the data in one or more databases. The effects of all the SQL statements in a transaction can be either all committed to the database or all rolled back. By default, MySQL 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. After disabling autocommit, changes to transaction-aware tables are not permanent immediately.

236

To store the changes, we must call the COMMIT statement or ROLLBACK to revert them. The Ruby MySQL has convenience methods for these SQL statements, commit and rollback. The MySQL database has different types of storage engines. The most common are the MyISAM and the InnoDB engines. There is a trade-off between data security and database speed. The MyISAM tables are faster to process and they do not support transactions. The commit and rollback methods are not implemented. They do nothing. On the other hand, the InnoDB tables are more safe against the data loss. They support transactions. They are slower to process.
mysql> SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES -> where TABLE_SCHEMA = 'mydb' AND TABLE_NAME='Writers'; +------------+--------+ | TABLE_NAME | ENGINE | +------------+--------+ | Writers | InnoDB | +------------+--------+ 1 row in set (0.00 sec)

The engine of the Writers table is InnoDB, which supports transactions.


#!/usr/bin/ruby require 'mysql' begin con = Mysql.new 'localhost', 'user12', '34klq*', 'mydb' con.autocommit false pst = con.prepare "UPDATE Writers SET Name = ? WHERE Id = ?" pst.execute "Leo Tolstoy", "1" pst.execute "Boris Pasternak", "2" pst.execute "Leonid Leonov" con.commit rescue Mysql::Error => e puts e con.rollback ensure pst.close if pst con.close if con end

In this script, we try to update three rows.


con.autocommit false

The autocommit mode is disabled.


pst = con.prepare "UPDATE Writers SET Name = ? WHERE Id = ?" pst.execute "Leo Tolstoy", "1" pst.execute "Boris Pasternak", "2" pst.execute "Leonid Leonov"

237

We execute three UPDATE statements. The last one is incorrect. The second parameter is missing.
con.commit

If all is OK, changes are committed to the table.


rescue Mysql::Error => e puts e con.rollback

In case of an error, changes are rolled back.


$ ./update.rb execute: param_count(2) != number of argument(1) mysql> SELECT * FROM Writers; +----+-------------------+ | Id | Name | +----+-------------------+ | 1 | Jack London | | 2 | Honore de Balzac | | 3 | Lion Feuchtwanger | | 4 | Emile Zola | | 5 | Truman Capote | | 6 | Stefan Zweig | +----+-------------------+ 6 rows in set (0.00 sec)

Running the script gives an error. However, the transaction was rolled back and the first two rows were not changed. This was MySQL Ruby tutorial.

238

Anda mungkin juga menyukai