Chapter 5: Ruby

In This Chapter

bullet Understanding the structure of a Ruby program

bullet Creating comments and declaring variables

bullet Using operators and data structures

bullet Branching and looping statements

bullet Creating functions and objects

The Ruby programming language was created by Yukihiro “Matz” Matsumoto, a Japanese programmer who named the language after a gemstone in reference to the Perl (pearl) programming language. Although most languages focus on wringing out extra performance from computer hardware, Ruby focuses on a clean language syntax that’s easy for programmers to understand and use. Instead of trying to increase machine efficiency, Ruby tries to increase programmer efficiency. The overriding principle of Ruby is to create a language of least surprise, meaning that after you’re familiar with Ruby, you aren’t suddenly surprised that its features can be used in an entirely different way, which often occurs with languages such as C++.

Ruby is an interpreted, object-oriented language for creating interactive Web pages. Although Ruby is similar to Perl and Python, Ruby abandons the C-syntax of Perl and more closely resembles the syntax of programming languages like Smalltalk or Ada. Instead of enclosing blocks of commands in curly brackets like C or Perl, Ruby encloses blocks of commands with keywords like Ada or more modern versions of BASIC.

A programming framework, dubbed Ruby on Rails, makes it easy to manipulate databases through Web pages and has attracted the attention of many former Java programmers. Like Ruby itself, Ruby on Rails is free, which has further fueled its growth. Although still a relatively young language (created in 1995), Ruby has attracted a worldwide following and will likely play a major role in future applications developed for the Web.

Mac OS X and many Linux distributions include an interpreter for the Ruby language. To get a copy of the free Ruby interpreter for other operating systems, visit the official Ruby Web site (www.ruby-lang.org).

The Structure of a Ruby Program

A Ruby program can consist of one or more commands:

print(‘What is your name? ‘ )

myname = gets()

puts( “Welcome to Ruby, #{myname}” )

Unlike other programming languages, Ruby programs don’t need to define a main program, don’t enclose blocks of commands with curly brackets, and don’t end statements with a semicolon. Type a command, and Ruby obeys without its syntax interfering with your thinking.

The preceding Ruby program simply asks the user to type in a name. Whatever name the user types gets stored in the myname variable. Then the last line prints the string “Welcome to Ruby,” followed by the contents of the myname variable.

Creating Comments

To write a comment in Ruby, use the # symbol. Anything that appears to the right of the # symbol is considered a comment, which the computer ignores.

# This is a comment

print(‘What is your name? ‘ )

myname = gets() # This is also a comment

puts( “Welcome to Ruby, #{myname}” )

If you want to write a comment over multiple lines, define the start and end of a comment block with =begin and =end, such as

=begin This is a block of comments

       that make it easy to comment

       out multiple lines. However,

       Ruby’s block commenting is kind

       of ugly so it’s rarely used.

=end

print(‘What is your name? ‘ )

myname = gets()

puts( “Welcome to Ruby, #{myname}” )

Defining comments with the =begin and =end lines is often cumbersome, so it’s more common for programmers to use multiple # symbols in front of each line instead like this:

# This program was written by John Doe

# on January 24, 2009. It took him a

# long time to write so maybe he deserves

# a big fat raise or at least some extra

# sick days so he can look for a better job.

print(‘What is your name? ‘ )

myname = gets()

puts( “Welcome to Ruby, #{myname}” )

Declaring Variables

Ruby uses symbols to identify different types of variables:

bullet Local: Begins with a lowercase letter, such as myage

bullet Instance: Begins with an @ symbol, such as @house

bullet Class: Begins with two @ symbols, such as @@mathclass

bullet Global: Begins with a $ symbol, such as $mymoney

In Ruby, constants are identified with an initial uppercase letter like Pi or Taxrate. To avoid confusing constants with local variables, it’s best to use all uppercase letters to name constants like PI or TAXRATE.

Both class and instance variables are used inside classes that define objects.

To store data into a variable, define the variable name and set it equal to a value:

variableName = value

The name of your variables can be anything, but Ruby is a case-sensitive language so myAge is considered a completely different variable than myage.

Using Operators

The three types of operators used in Ruby are mathematical, relational, and logical operators. Mathematical operators calculate numeric results such as adding, multiplying, or dividing numbers, as shown in Table 5-1.

Table 5-1 Mathematical Operators
Mathematical Operator Purpose Example
+ Addition 5 + 3.4
- Subtraction 203.9 – 9.12
* Multiplication 39 * 146.7
/ Division 45 / 8.41
% Modula division 35 % 9 = 8
(returns the remainder)
** Exponentiation 2**3 = 8

If you divide two integers with the / operator, the answer will be rounded to the nearest integer. If you want to return a decimal value, at least one of the numbers must be written as a decimal value such as 2.0 / 3 or 2 / 3.0. If you just type 2 / 3, the answer will be 0.

Relational operators compare two values and return a True or a False value. The seven comparison operators available are shown in Table 5-2.

Table 5-2 Relational Operators
Relational Operator Purpose
== Equal
=== Identical
!= Not equal
< Less than
<= Less than or equal to
> Greater than
>= Greater than or equal to

Ruby uses three equal signs (===) to compare to values and determine if they’re of the same data type. For example, Ruby treats 1.0 and 1 as identical because both are numbers, but 1.0 and “1.0” wouldn’t be considered equal because one is a number and the other is a different data type (a string).

Logical operators compare two Boolean values (True or False) and return a single True or False value, as shown in Table 5-3.

Table 5-3 Logical Operators
Logical Operator Truth Table
&& (AND) True && True = True
True && False = False
False && True = False
False && False = False
|| (OR) True || True = True
True || False = True
False || True = True
False || False = False
^ (XOR) True ^ True = False
True ^ False = True
False ^ True = True
False ^ False = False
! (NOT) !True = False
!False = True

Most programming languages use the equal sign to assign values to variables, such as

i = 59

However, Ruby also includes combination assignment and mathematical operators, as shown in Table 5-4.

Table 5-4 Assignment Operators
Assignment Operator Purpose Example
+= Addition assignment i += 7 (equivalent to i = i + 7)
-= Subtraction assignment i -= 4 (equivalent to i = i - 4)
*= Multiplication assignment i *= y (equivalent to i = i * y)
/= Division assignment i /= 3.5 (equivalent to i = i / 35)
%= Modulo assignment i %= 2.8 (equivalent to i = i % 2.8)

Because Ruby lacks an increment and decrement operator like C++, you must increment variables with the assignment operator. So although C++ lets you use an increment operator like this:

++i;

The equivalent increment operator in Ruby might look like this:

i += 1

Branching Statements

The simplest branching statement is an IF statement that runs only one or more commands if a Boolean condition is True, such as

if condition

  Command

end

If you write the entire IF statement on a single line, you must make sure you include the then keyword, such as

if condition then Command end

Ruby also includes a negated form of the IF statement called the UNLESS statement that looks like this:

unless condition

  Command

end

The UNLESS statement runs only if the condition is False.

a = 5

unless a < 1

  puts “This will print out.”

end

Because the condition a < 1 is False, the preceding UNLESS statement runs the command sandwiched between the UNLESS keyword and the END keyword.

Both the IF and UNLESS statements can make the computer choose between two mutually exclusive sets of commands by including an ELSE keyword, such as

if condition

  Command1

else

  Command2

end

Although the IF-ELSE statement can only give the computer a choice of two groups of commands to run, the IF-ELSIF statement can offer the computer multiple groups of commands to run, such as

if condition1

  Command

elseif condition2

  Command

elseif condition3

  Command

end

As an alternative to the IF-ELSIF statement, you can also use the CASE statement to offer two or more choices, such as

case variable

when value1

  Command

when value2

  Command

else

  Command;

end

Rather than check if a variable equals a specific value, the CASE statement can also check if a variable falls within a range of values by using the .. characters, such as

case variable

when value1..value4

  Command

when value5

  Command

else

  Command;

end

Looping Statements

A looping statement repeats one or more commands for a fixed number of times or until a certain Boolean condition becomes True. To create a loop that repeats for a fixed number of times, use the FOR loop, which looks like this:

for variable in startvalue..endvalue

  Command

end

If you wanted the FOR loop to run four times, you could set the Start value to 1 and the End value to 4, such as

for i = 1..4

  Command

end

If you don’t know how many times you need to repeat commands, use a WHILE loop, which looks like this

while condition

  Command

end

If the condition is True, the loop runs at least once. If this condition is False, then the loop doesn’t run.

Ruby also offers a negated form of the WHILE loop called an UNTIL loop, which looks like this:

until condition

  Command

end

The UNTIL loop keeps running until a condition becomes True.

Somewhere inside a WHILE or an UNTIL loop, you must have a command that can change the condition from True to False; otherwise the loop will never end and your program will appear to hang or freeze.

Creating Functions

To break up programming problems, you can create subprograms that solve a specific task. Such subprograms are functions or methods. The format of a typical function looks like this:

def functionname (Parameter list)

  Commands

  return value

end

The two parts of a Ruby function are

bullet Parameter list: Defines any data that the function needs to work. If the function doesn’t need to accept any values, omit the parentheses altogether.

bullet Return: Defines a value to return.

If a function doesn’t return a value or accept any parameters, it might look like this:

def myfunction

  Command

end

Using Data Structures

Ruby offers two built-in data structures: collections and hashes (also known as an associative array).

bullet A collection can hold any number of items of different data types, such as strings and numbers. In a collection, each item is identified by an index number, starting with 0.

bullet A hash is like a collection, but stores a unique key value with every item. To retrieve a value from a hash, you need to know its key.

To create a collection, define a collection name and list the items to store in the collection inside square brackets like this:

collectionname = [data1, data2, data3]

So if you wanted to store the string “Ruby is cool” and the number 84.3 in the first and second elements of a collection, you could do the following:

mystuff = [“Ruby is cool”, 84.3]

To retrieve data from a collection, specify the collection name and index number. So if you wanted to retrieve the first item in a collection, you could do this:

puts mystuff [0]

One problem with collections is that to retrieve specific data, you need to know its exact location in the collection. For greater flexibility, Ruby offers hashes so you can assign a unique value (a key) to each item. To create a hash and store data along with a key, do this:

hashname = {key => value, key => value}

Ruby defines a collection with square brackets but defines a hash with curly brackets.

If you wanted to assign the number 3.14 to the “pi” key, you could do this:

myhash = {“pi” => 3.14}

If you need to store multiple keys and values in a hash, you might prefer this alternate way of storing keys and data in a hash:

hashname = Hash.new

hashname[key] = value

hashname[key] = value

When defining a hash with multiple lines, use square brackets.

To retrieve data from a hash, identify the hash name and a key value, such as

puts hashname[“key”]

So if you wanted to retrieve data stored under the key “pi”, you could do the following:

hashname = Hash.new

hashname[“pi”] = 3.14

puts hashname[“pi”]

The first line creates a hash data structure. The second line stores the value 3.14 into the hash using the key “pi”. The third line prints out the value identified by the “pi” key in the hash data structure.

Creating Objects

Ruby supports object-oriented programming. To create an object, you must define a class, which specifies the properties and methods, such as

class Classname

  def propertyname

    @propertyname

  end

  def propertyname=(propertyname)

    @propertyname = propertyname

  end

  def methodname(parameter list)

    commands

  end

end

To create an object, you must use the following syntax:

objectname = Classname.new

To assign a value to an object’s property, you need to specify the object name and the property you want to use, such as

objectname.propertyname = value

To tell an object to run a method, you need to specify the object name followed by the method name, such as

objectname.methodname(parameters)

Ruby allows single inheritance, where an object can inherit from one class (in contrast to multiple inheritance, which allows an object to inherit from two or more classes). To inherit from a class, use the < symbol followed by the class name you want to inherit from, such as

class Classname

  def propertyname

    @propertyname

  end

  def propertyname=(propertyname)

    @propertyname = propertyname

  end

  def methodname(parameter list)

    commands

  end

end

class Classname2 < Classname1

  # property and method definitions go here

end