You are previewing Learning Ruby.

Learning Ruby

Cover of Learning Ruby by Michael Fitzgerald Published by O'Reilly Media, Inc.
  1. Learning Ruby
    1. SPECIAL OFFER: Upgrade this ebook with O’Reilly
    2. A Note Regarding Supplemental Files
    3. Preface
      1. Who Should Read This Book?
      2. How This Book Works
      3. About the Examples
      4. How This Book Is Organized
      5. Conventions Used in This Book
      6. Comments and Questions
      7. Safari® Enabled
      8. Acknowledgments
    4. 1. Ruby Basics
      1. Hello, Matz
      2. Interactive Ruby
      3. Resources
      4. Installing Ruby
      5. Permission Denied
      6. Associating File Types on Windows
      7. Review Questions
    5. 2. A Quick Tour of Ruby
      1. Ruby Is Object-Oriented
      2. Ruby's Reserved Words
      3. Comments
      4. Variables
      5. Strings
      6. Numbers and Operators
      7. Conditional Statements
      8. Arrays and Hashes
      9. Methods
      10. Blocks
      11. Symbols
      12. Exception Handling
      13. Ruby Documentation
      14. Review Questions
    6. 3. Conditional Love
      1. The if Statement
      2. The case Statement
      3. The while Loop
      4. The loop Method
      5. The for loop
      6. Execution Before or After a Program
      7. Review Questions
    7. 4. Strings
      1. Creating Strings
      2. Concatenating Strings
      3. Accessing Strings
      4. Comparing Strings
      5. Manipulating Strings
      6. Case Conversion
      7. Managing Whitespace, etc.
      8. Incrementing Strings
      9. Converting Strings
      10. Regular Expressions
      11. 1.9 and Beyond
      12. Review Questions
    8. 5. Math
      1. Class Hierarchy and Included Modules
      2. Converting Numbers
      3. Basic Math Operations
      4. Ranges
      5. Inquiring About Numbers
      6. More Math Methods
      7. Math Functions
      8. Rational Numbers
      9. Prime Numbers
      10. Review Questions
    9. 6. Arrays
      1. Creating Arrays
      2. Accessing Elements
      3. Concatenation
      4. Set Operations
      5. Unique Elements
      6. Blow Your Stack
      7. Comparing Arrays
      8. Changing Elements
      9. Deleting Elements
      10. Arrays and Blocks
      11. Sorting Things and About Face
      12. Multidimensional Arrays
      13. 1.9 and Beyond
      14. Other Array Methods
      15. Review Questions
    10. 7. Hashes
      1. Creating Hashes
      2. Accessing Hashes
      3. Iterating over Hashes
      4. Changing Hashes
      5. Converting Hashes to Other Classes
      6. 1.9 and Beyond
      7. Other Hash Methods
      8. Review Questions
    11. 8. Working with Files
      1. Directories
      2. Creating a New File
      3. Opening an Existing File
      4. Deleting and Renaming Files
      5. File Inquiries
      6. Changing File Modes and Owner
      7. The IO Class
      8. Review Questions
    12. 9. Classes
      1. Defining the Class
      2. Instance Variables
      3. Accessors
      4. Class Variables
      5. Class Methods
      6. Inheritance
      7. Modules
      8. public, private, or protected
      9. Review Questions
    13. 10. More Fun with Ruby
      1. Formatting Output with sprintf
      2. Processing XML
      3. Date and Time
      4. Reflection
      5. Using Tk
      6. Metaprogramming
      7. RubyGems
      8. Exception Handling
      9. Creating Documentation with RDoc
      10. Embedded Ruby
      11. Review Questions
    14. 11. A Short Guide to Ruby on Rails
      1. Where Did Rails Come From
      2. Why Rails?
      3. What Have Other Folks Done with Rails?
      4. Hosting Rails
      5. Installing Rails
      6. Learning Rails
      7. A Brief Tutorial
      8. Review Questions
    15. A. Ruby Reference
      1. Ruby Interpreter
      2. Ruby's Reserved Words
      3. Operators
      4. Escape Characters
      5. Predefined Variables
      6. Global Constants
      7. Regular Expressions
      8. String Unpack Directives
      9. Array Pack Directives
      10. Sprintf Flags and Field Types
      11. File Tests
      12. Time Formatting Directives
      13. RDoc Options
      14. Rake
    16. B. Answers to Review Questions
      1. Chapter 1 Review Questions
      2. Chapter 2 Review Questions
      3. Chapter 3 Review Questions
      4. Chapter 4 Review Questions
      5. Chapter 5 Review Questions
      6. Chapter 6 Review Questions
      7. Chapter 7 Review Questions
      8. Chapter 8 Review Questions
      9. Chapter 9 Review Questions
      10. Chapter 10 Review Questions
      11. Chapter 11 Review Questions
    17. Glossary
    18. Index
    19. About the Author
    20. Colophon
    21. SPECIAL OFFER: Upgrade this ebook with O’Reilly
O'Reilly logo

Chapter 1. Ruby Basics

Perhaps like you, I've learned to program in a number of languages over the years—BASIC, FORTRAN, C, C++, C#, Java, and JavaScript among others—but so far Ruby is my favorite. It has been the most fun to learn and use. Why? Because of its syntax. If you have a background in a variety of other languages, Ruby is easy to figure out. And it's flexible: Ruby lets you do things in a variety of ways, not just one way, so you can decide how to do things your way.

Ruby is an interpreted rather than a compiled language. You can call it a scripting language, an object-oriented language, a refreshing language. It's not a perfect language. It doesn't have to be. It's still my favorite. It has that certain je ne sais quoi. If it didn't, why would I spend hundreds of hours writing a book about it? Certainly not for money and fame.

To me, one of the best aspects of Ruby is its composability. Composability is the degree to which you can express logic by combining and recombining parts of a language (see James Clark's "The Design of RELAX NG" at http://www.thaiopensource.com/relaxng/design.html#section:5). Ruby's got that, big time.

Also, Ruby isn't under committee or corporate control. It's open source. It was written by Matz, with some help from his friends. (It was written in C, by the way, and can take C extensions.)

"Matz" is short for Yukihiro Matsumoto (from Japan). He started working on Ruby in 1993, and first released it to the world in 1995, the same year Java came out. It took a while for Ruby to emerge in the West, but once it did, around the year 2000, it started to take off. With the help of people like Dave Thomas, Andy Hunt, Hal Fulton, and others, Ruby got a foothold. Now it has a fan base.

And Ruby has a killer app. It's called Ruby on Rails (http://www.rubyonrails.org). Heard of it? It's a web application framework for producing web sites with databases quickly and easily. A lot of people really like Rails. Not everyone, but a lot of people. And those people are discovering that one of the main reasons they like Rails is because it was written in Ruby.

Hello, Matz

I know many readers are expecting a "Hello, World" example right about now. In spite of a moral and ethical obligation to provide a "Hello, World" example, I have decided to change the first example to "Hello, Matz." Given all that Matz has done for the programming world, don't you think he deserves some acknowledgment?

Before you go any further, find out if you already have Ruby installed on your computer. If you are on Mac OS X or a Linux distribution of some sort, it might already be there, though it's probably an older version; Tiger (Mac OS X 10.4 or later) ships with version 1.8.2, for example.

To discover if Ruby is lurking inside your box, just go to a shell prompt on a Unix/Linux system (this won't work on a standard Windows system) and type:

$ which ruby

See if you get a reply like this one (good news if you do):

/usr/local/bin/ruby

Or just type a command to check the version of Ruby (this works on Unix/Linux and Windows):

$ ruby -v

or:

$ ruby --version

If Ruby is installed, you should get an answer that looks like this:

ruby 1.8.6 (2007-03-13 patchlevel 0) [powerpc-darwin8.9.0]

Tip

If Ruby is not installed on your box, and you're a little nervous about figuring out how to install it on your own, go to the section "Installing Ruby," later in this chapter. Follow the instructions there to install Ruby on your platform. Then come right back!

A Very Short Ruby Program

Now that you have Ruby up and running, type the following line in a plain-text editor such as TextPad or vim:

puts "Hello, Matz!"

This line of code is a programming statement, an instruction that you want the program to carry out. The instruction will print the string Hello, Matz! on your screen, followed by a newline character.

You can end a statement with a semicolon (;) if you want, just like in C or Java, but you sure don't have to: a newline will do fine. (Most Ruby programmers don't use ; except when writing multiple statements on one line.)

Save the little program in a file as plain text and name it matz.rb. (The .rb file extension is the conventional extension for Ruby programs.)

Tip

It's a good idea to save the file in a directory or folder where you plan to do your Ruby work so that all your Ruby files will be readily accessible in one location.

You run the program by running the Ruby interpreter. To do this, type the following at a shell or command prompt:

$ ruby matz.rb

The output from the program is displayed by default on the screen:

Hello, Matz!

Placing a # at the beginning of a line tells the interpreter to ignore that line:

# a nice greeting for Matz
puts "Hello, Matz!"

Add the # and some text following it to your program matz.rb. This is called a comment. Whatever follows the # is hidden from the Ruby interpreter. You'll learn more about comments in Chapter 2.

Shebang!

If you run a Ruby program on Windows, you generally have to use the ruby command before the Ruby filename (unless you associate the file extension .rb with a file type; to learn how to do this, see "Associating File Types on Windows," later in this chapter). You can avoid typing ruby each time on Unix/Linux systems by adding something called a shebang line (#!) at the top of your Ruby file. Add a shebang line to the top of matz.rb:

#!/usr/local/bin/ruby
# a nice greeting for Matz
puts "Hello, Matz!"

The shebang lets the system know where to find the Ruby interpreter, that is, in /usr/local/bin, which is a conventional place to install Ruby executables (see "Installing Ruby on Mac OS X Tiger," later in this chapter). A more general alternative is #!/usr/bin/env ruby. Choose what works for you. I use the latter.

Tip

As mentioned earlier, Tiger comes installed with an older version of Ruby, version 1.8.2, which is stored in /usr/bin. We won't bother using that version.

Go to a prompt on your Mac or Unix/Linux system and enter the filename by itself:

$ matz.rb

You'll get the same answer as before:

Hello, Matz!

Tip

If you get a permission denied message when running matz.rb, and you aren't sure what to do about it, I'd like to offer you a hand. Go to the section "Permission Denied" near the end of this chapter to find out what to do.

I'll now show you more ways you can output the text Hello, Matz!, which will give you a glimpse of the power of Ruby. At this point, I won't get very deep into detail about what's going on. Just follow along, typing in and testing as much code as you want. To test the code, follow these steps.

  1. Delete the previous code in matz.rb.

  2. Enter the new code.

  3. Run the program with the Ruby interpreter from the prompt to see the output.

You'll be deleting the old code in matz.rb and inserting new code, unless another Ruby file with a different name is presented in the text. You can either recreate these other files with the given names, or you can download all the files that come with this book from http://www.oreilly.com/catalog/9780596529864. After downloading the ZIP archive, extract the files into the directory or folder of your choice. That's where you'll do your work. Navigate to the directory in a shell or command window using the cd command.

Issue a System Command

You can run an operating system command with system:

system "echo 'Hello, Matz!'"

Try this with and without single quotes ('), where shown.

You can also submit each part of a command separately, as an argument to system:

system "echo", "Hello,", "Matz!"

The exec command is similar to system, but it replaces the current process and, after the command is finished, exits—not always what you want to do.

Appending a String

Append one string to another with the + method:

puts "Hello, " + "Matz!"

You can also append a string with the << method:

puts "Hello, " << "Matz!"

Multiply

What if you want to print out a line of text three times? How about:

puts "Hello, Matz! " * 3

This would give you:

Hello, Matz! Hello, Matz! Hello, Matz!

Or you could use the times method:

5.times { print "Hello, Matz! " }

It will show your enthusiasm:

Hello, Matz! Hello, Matz! Hello, Matz! Hello, Matz! Hello, Matz!

You could just print one word three times, then add or append more text with +:

puts "Hello, " * 3 + "Matz!"

Then you'd get:

Hello, Hello, Hello, Matz!

Inserting a Shell Command

Let's insert some output from a shell command:

puts "Hey Matz, I'm running " + `ruby --version`

When you run this, the output from the shell command inside the grave accents or backticks (`ruby --version`) is inserted into the output:

Hey Matz, I'm running ruby 1.8.6 (2006-08-25) [powerpc-darwin8.8.0]

Using a Variable

You can give a value a name by assigning it to a variable:

hi = "Hello, Matz!"
puts hi # => Hello, Matz!

hi is an example of a local variable. You can tell because its name starts with a lowercase letter. You'll learn more about local and other kinds of variables in Chapter 2 in the section "Variables."

Tip

In code examples, => will always follow a comment character (#). Whatever follows => is the output you can expect from the line or block of code, or from the whole program.

Put two or more variables together with the + method:

hi = "Hello, "
person = "Matz!"
puts hi + person # => Hello, Matz!

Expression Substitution

Another way of inserting the value of a variable in a string is with expression substitution—very handy feature of Ruby:

person = "Matz!"
puts "Hello, #{person}" # => Hello, Matz!

The #{...} is replaced with the result of the expression inside it. For example, #{2+2} would yield the result 4.

Using expression substitution, you can grab an argument off the command line and add it to the output.

#!/usr/bin/env ruby

puts "Hello, #{ARGV[0]}!"

Ruby stores command-line arguments in a predefined Ruby variable called ARGV. ARGV[0] refers to the first item on the command line, the 0th element in ARGV. Run the matz.rb program you just edited with an argument to see the results:

$ matz.rb Matz
Hello, Matz!

Formatting a String

You can change the output on the fly with the %s format flag and %:

hi = "Hello, %s"

puts hi % "Matz!" # => "Hello, Matz!"

puts hi % "people!" # => "Hello, people!"

puts hi % "universe!" # => "Hello, universe!"

You can also use % like this:

"%s, %s!" % [ "Hello", "Matz" ]

% is a method from the String class that formats a string. It is like using sprintf:

sprintf( "Hello, %s", "Matz!" ) # => "Hello, Matz!"

Use printf to print the output to your display (the default standard output device).

printf( "Hello, %s", "Matz!" ) # => Hello, Matz!

You will learn about formatting strings with sprintf in Chapter 10 in the section "Formatting Output with sprintf."

The eval Method and -e Option

The eval method evaluates a string enclosed in quotes as a Ruby statement or expression and returns the result. It's handy for testing.

eval "puts 'Hello, Matz!'" # => Hello, Matz!

Similarly, there is a way you can print Hello, Matz! without using a separate file at all—with the -e (execute/evaluate) option:

ruby -e "puts 'Hello, Matz!'"

Notice that you use single quotes inside of double quotes when using the -e option. You can also use multiple -e options:

ruby -e "print 'Hello, '" -e "puts 'Matz!'"

Using both of these will give you the same output as before (or what looks like the same output):

Hello, Matz!

I used print in the first -e option because it doesn't add an end-of-line or newline character at the end of the line like puts does. If I used puts with both -e options, the result would be:

Hello,
Matz!

You can use multiple statements, separated by semicolons, inside a single -e if you want:

ruby -e "three = 3; puts 'Matz! ' * three"

This will give you:

Matz! Matz! Matz!

Getting Input from the Keyboard

You can use the gets method to read from standard input (text from your keyboard, by default).

#!/usr/bin/env ruby

print "Who do you want to say hello to? "
hello = gets
puts "Hello, " + hello

The program prints the message Who do you want to say hello to? The gets method reads what you type and assigns it to the hello variable. puts prints Hello, plus whatever is held in hello, to the standard output (your computer display, by default). Run the program, then type your answer to the question.

$ matz.rb
Who do you want to say hello to? Matz!
Hello, Matz!

Methods

You've had a chance to use a few methods like system and eval; now you'll define your own method with def/end:

def hello
  puts "Hello, Matz!"
end

hello # => Hello, Matz!

The method called hello contains a single statement that prints Hello, Matz!. To see it in action, call the method by invoking its name, hello.

The block

Redefine hello so that it contains only a yield statement, then call the new version of hello with a block (the code in braces).

def hello
  yield
end

hello { puts "Hello, Matz!" } # => Hello, Matz!

The yield statement executes the block of code in braces (that is, { puts "Hello, Matz!" }) associated with the method call to hello. You'll learn more about blocks in the section "Blocks" in Chapter 2.

The each Method

Let's go a step further. Let's print all the elements in an array using the each method followed by a block:

[ "Hello, ", "Matz!"].each { |e| print e }

An array is an ordered list of elements. The method each uses a block—again, the code enclosed in braces—to iterate over, or repeatedly process, all the elements in the array. The |e| represents the elements fed from the array; the print e statement prints each element in the array. You'll learn much more about arrays in Chapter 6.

The proc

You can convert a block into an object. This object is called a proc (procedure). The nice thing about procs is that they preserve their execution environment and pack it along with them. The lambda method is one way to create a proc object. I'll use it here to create a now familiar greeting.

prc = lambda { |name| puts "Hello, " + name }

The proc is stored in prc as the result of a call to lambda, which stores the block as an object. You can now call the proc with an argument; call executes the proc with an argument, yielding a string.

prc.call "Matz!" # => Hello, Matz!

You'll learn more about procs in the section "Procs" in Chapter 2.

XML

For XML processing, REXML is built into Ruby. Use it to greet the revered founder of our feast, as shown in Example 1-1 and Example 1-2.

Example 1-1. matz.xml

<hello>Matz!</hello>

Example 1-2. matz_xml.rb

#!/usr/bin/env ruby

require "rexml/document"

file = File.new( "matz.xml" )
doc = REXML::Document.new file
puts doc.to_s

When you run it, the program grabs the XML file matz.xml and displays it.

The Class

Use the class Hello to greet Matz, as shown in Example 1-3.

Example 1-3. hello.rb

class Hello

  def initialize( name )
    @name = name
  end

  def hello_matz
    puts "Hello, " + @name + "!"
  end

end

hi = Hello.new( "Matz" )
hi.hello_matz # => Hello, Matz!

You'll learn a bit about classes in Chapter 2. Chapter 9 is dedicated to bringing you fully up to speed on Ruby classes.

The Tk Toolkit

Create a graphical version of "Hello, Matz!" with the Tk toolkit (see http://www.tcl.tk/), as shown in Example 1-4.

Example 1-4. matz_tk.rb

#!/usr/bin/env ruby

require 'tk'
hello = TkRoot.new
TkLabel.new( hello ) do
    text "\n  Hello, Matz!  \n"
    pack
end
Tk.mainloop

The require method loads the Tk library. The next line creates a new TkRoot object called hello. TkLabel.new adds a label to that object with the text Hello, Matz!. Tk.mainloop makes the graphical event happen, displaying the graphic shown in Figure 1-1. You can run the program by typing the following at a shell prompt:

matz_tk.rb &

The & puts the process in the background on a Unix/Linux system. You'll learn more about the Tk library and other graphical user interfaces in the section "Using Tk" in Chapter 10.

Tk version of Hello, Matz! on Mac OS X

Figure 1-1. Tk version of Hello, Matz! on Mac OS X

Editing and Running Ruby in TextMate

If you own a Mac, you will get more joy out of life if you get yourself a copy of TextMate. (Download a free trial or pay for a copy at http://www.macromates.com.)

TextMate has language bundles that make editing in a given language—such as HTML, C, Java, Python, Ruby, and Rails—a snap. Other IDEs have similar features, for sure, and I don't spend any energy knocking them, in public or private. The difference to me is that TextMate is elegant; it doesn't overwhelm you with complex features. It's there to help without getting in your way.

Figure 1-2 shows a version of matz.rb open for editing in TextMate. To run this program in TextMate, I simply type Command-R, and the results appear in a separate window (RubyMate), shown in Figure 1-3.

Editing a Ruby program in TextMate

Figure 1-2. Editing a Ruby program in TextMate

Results of running a Ruby program in TextMate

Figure 1-3. Results of running a Ruby program in TextMate

Here are a few of the Ruby shortcuts in TextMate:

  • Insert Ruby templates to make file creation quicker.

  • Insert Ruby keywords, such as begin or if, followed by a tab, and TextMate completes the typing for you.

  • Execute a single line as Ruby with Control-Shift-E. This inserts the result right into the file. You can do this in other files, too (HTML files, for example).

  • Validate syntax, without running the program, with Control-Shift-V.

  • Place the cursor on a Ruby keyword or method name, then enter Control-H to get documentation on that term.

The best content for your career. Discover unlimited learning on demand for around $1/day.