Getting Started - Facets of Ruby - Programming Ruby 1.9 & 2.0: The Pragmatic Programmers’ Guide (2013)

Programming Ruby 1.9 & 2.0: The Pragmatic Programmers’ Guide (2013)

Part 1. Facets of Ruby

Chapter 1. Getting Started

Before we start talking about the Ruby language, it would be useful if we helped you get Ruby running on your computer. That way, you can try sample code and experiment on your own as you read along. In fact, that’s probably essential if you want to learn Ruby—get into the habit of writing code as you’re reading. We will also show you some different ways to run Ruby.

1.1 The Command Prompt

(Feel free to skip to the next section if you’re already comfortable at your system’s command prompt.)

Although there’s growing support for Ruby in IDEs, you’ll probably still end up spending some time at your system’s command prompt, also known as a shell prompt or just plain prompt . If you’re a Linux user, you’re probably already familiar with the prompt. If you don’t already have a desktop icon for it, hunt around for an application called Terminal or xterm. (On Ubuntu, you can navigate to it using Applications → Accessories → Terminal.) On Windows, you’ll want to run cmd.exe, accessible by typing cmd into the dialog box that appears when you select Start → Run. On OS X, run Applications → Utilities → Terminal.app.

In all three cases, a fairly empty window will pop up. It will contain a banner and a prompt. Try typing echo hello at the prompt and hitting Enter (or Return, depending on your keyboard). You should see hello echoed back, and another prompt should appear.

Directories, Folders, and Navigation

It is beyond the scope of this book to teach the commands available at the prompt, but we do need to cover the basics of finding your way around.

If you’re used to a GUI tool such as Explorer on Windows or Finder on OS X for navigating to your files, then you’ll be familiar with the idea of folders —locations on your hard drive that can hold files and other folders.

When you’re at the command prompt, you have access to these same folders. But, somewhat confusingly, at the prompt these folders are called directories (because they contain lists of other directories and files). These directories are organized into a strict hierarchy. On Unix-based systems (including OS X), there’s one top-level directory, called / (a forward slash). On Windows, there is a top-level directory for each drive on your system, so you’ll find the top level for your C: drive at C:\ (that’s the drive letter C, a colon, and a backslash).

The path to a file or directory is the set of directories that you have to traverse to get to it from the top-level directory, followed by the name of the file or directory itself. Each component in this name is separated by a forward slash (on Unix) or a backslash (on Windows). So, if you organized your projects in a directory called projects under the top-level directory and if the projects directory had a subdirectory for your time_planner project, the full path to the README file would be /projects/time_planner/readme.txt on Unix and C:\projects\time_planner\readme.txt on Windows.

Spaces in Directory Names and Filenames

Most operating systems now allow you to create folders with spaces in their names. This is great when you’re working at the GUI level. However, from the command prompt, spaces can be a headache, because the shell that interprets what you type will treat the spaces in file and folder names as being parameter separators and not as part of the name. You can get around this, but it generally isn’t worth the hassle. If you are creating new folders and files, it’s easiest to avoid spaces in their names.

To navigate to a directory, use the cd command. (Because the Unix prompt varies from system to system, we’ll just use a single dollar sign to represent it here.)

$ cd /projects/time_planner (on Unix)

C:\> cd \projects\time_planner (on Windows)

On Unix boxes, you probably don’t want to be creating top-level directories. Instead, Unix gives each user their own home directory . So, if your username is dave, your home directory might be located in /usr/dave, /home/dave, or /Users/dave. At the shell prompt, the special character ~ (a single tilde) stands for the path to your home directory. You can always change directories to your home directory using cd ~, which can also be abbreviated to just cd.

To find out the directory you’re currently in, you can type pwd (on Unix) or cd on Windows. So, for Unix users, you could type this:

$ cd /projects/time_planner

$ pwd

/projects/time_planner

$ cd

$ pwd

/Users/dave

On Windows, there’s no real concept of a user’s home directory:

C:\> cd \projects\time_planner

C:\projects\time_planner> cd \projects

C:\projects>

You can create a new directory under the current directory using the mkdir command:

$ cd /projects

$ mkdir expense_tracker

$ cd expense_tracker

$ pwd

/projects/expense_tracker

Notice that to change to the new directory, we could just give its name relative to the current directory—we don’t have to enter the full path.

We suggest you create a directory called pickaxe to hold the code you write while reading this book:

$ mkdir ~/pickaxe (on Unix)

C:\> mkdir \pickaxe (on Windows)

Get into the habit of changing into that directory before you start work:

$ cd ~/pickaxe (on Unix)

C:\> cd \pickaxe (on Windows)

1.2 Installing Ruby

Ruby comes preinstalled on many Linux distributions, and Mac OS X includes Ruby (although the version of Ruby that comes with OS X is normally several releases behind the current Ruby version). Try typing ruby -v at a command prompt—you may be pleasantly surprised.

If you don’t already have Ruby on your system or if you’d like to upgrade to a newer version (remembering that this book describes Ruby 1.9 and Ruby 2.0), you can install it pretty simply. What you do next depends on your operating system.

Installing on Windows

There are two options for installing Ruby on Windows. The first is a simple installer package—download it, and you’ll have Ruby up and running in minutes. The second is slightly more complex but gives you the flexibility of easily managing multiple Ruby environments on the same computer at the same time. Whichever option you choose, you’ll first need to download and install a working Ruby.

Install Ruby with RubyInstaller

The simple solution (and probably the right one to use if you’re not planning on running multiple versions of Ruby at the same time) is Luis Lavena’s RubyInstaller.org.

Simply navigate to http://rubyinstaller.org , click the big DOWNLOAD button, and select the Ruby version you want. Save the file to your downloads folder, and then run it once it has downloaded. Click through the Windows nanny warnings, and you’ll come to a conventional installer. Accept the defaults, and when the installer finishes, you’ll have an entry for Ruby in your All Programs menu of the Start menu:

Select Start Command Prompt with Ruby to open a copy of the Windows command shell with the environment set up to run Ruby.

pik: Install Multiple Ruby Environments

The pik system by Gordon Thiesfeld allows you to manage multiple Ruby interpreters on the same machine, switching between them easily. Obviously, this isn’t something everyone needs, so you may want to skip to Source Code from This Book.

Before you start, make sure you have a working Ruby on your machine, using the instructions from the previous section to download and use RubyInstaller if necessary.

Then, install pik. Visit http://github.com/vertiginous/pik/downloads . Look near the top for the list of msi files, and choose the latest. Double-click the filename to download and install it.

After a few seconds, the Pik Setup dialog box will appear. Accept the defaults, and pik will be installed.

At this time, you’ll probably need to either log out and log back in or (possibly) restart Windows to get pik successfully integrated into your environment.

Now bring up a Ruby command prompt (Start Command Prompt with Ruby), and type the following at the prompt:

C:\Users\dave> pik add

** Adding: 193: ruby 1.9.3p0 (2011-10-30) [i386-mingw32]

You’ve now registered that Ruby interpreter with pik. At any other command prompt, you can use the pik command to list the Ruby interpreters pik knows about and to tell pik to make a particular interpreter current:

C:\>pik list

193: ruby 1.9.3p0 (2011-10-30) [i386-mingw32]

C:\>pik use 193

C:\>ruby -v

ruby 1.9.3p0 (2011-10-30) [i386-mingw32]

Having gotten one Ruby registered with pik, let’s install another. We’ll play with JRuby, an implementation of Ruby written in Java. Before doing this, you’ll need to download the Java runtime (Google is your friend). Once Java is installed, tell pik to install the JRuby interpreter:

C:\> pik install jruby

** Downloading: http://jruby.org......downloads/1.5.2/jruby-bin-1.5.2.zip

to: C:\Users\dave\.pik\downloads\jruby-bin-1.5.2.zip

** Extracting: C:\Users\dave\.pik\downloads\jruby-bin-1.5.2.zip

to: C:\Users\dave\.pik\rubies\JRuby-152

done

** Adding: 152: jruby 1.5.2 (ruby 1.8.7 patchlevel 249) (2010-08-20 1c5e29d)

(Java HotSpot(TM) Client VM 1.6.0_21) [x86-java]

Located at: C:\Users\dave\.pik\rubies\JRuby-152\bin

You now have two Ruby interpreters managed by pik. You can switch between them at the command line:

C:\>pik list

152: jruby 1.5.2 (ruby 1.8.7 patchlevel 249) (2010-08-20 1c5e29d) (Java H...

193: ruby 1.9.3p0 (2011-10-30) [i386-mingw32]

C:\>pik use 152

C:\>jruby -v

jruby 1.5.2 (ruby 1.8.7 patchlevel 249) (2010-08-20 1c5e29d)

(Java HotSpot(TM) Client VM 1.6.0_21) [x86-java]

C:\>pik use 193

C:\>ruby -v

ruby 1.9.3p0 (2011-10-30) [i386-mingw32]

If you plan on installing gems that have native code components (that is, they interface to existing Windows libraries using C code), you’ll need a C development environment on your machine, and you’ll need to download and install the Pik development kit.

Now that you’re all set up, skip forward to Source Code from This Book.

Installing on Linux and Mac OS X

One of the interesting things about the various Unix-like systems out there is that their maintainers all have their own ideas about how to package tools such as Ruby. It is very nice that they have gone to this trouble, but it also means that if you go with the flow, you’ll need to learn their way of doing things. It also often means that you’ll be stuck with what you’re given. So, we’re going to take a different approach. We’re going to use a system called the Ruby Version Manager (RVM), written by Wayne E. Seguin. RVM is a tool that lets you have multiple independent Ruby installations on the same machine. You can switch between them using a single command. This is wonderful, because you can experiment with new versions of Ruby while still keeping the old ones on your system. We use RVM to keep a Ruby environment for the examples in this book that’s isolated from our daily work.[5]

Installing RVM

Although you can install RVM using RubyGems (assuming you already have a working Ruby on your system), the preferred approach is to install it directly.

Most Unix-like systems will already have all the dependencies installed.[6] The possible fly in the ointment is Ubuntu, where the curl utility is not installed by default. Add it before you start with this:

$ sudo apt-get update

$ sudo apt-get install curl

You install RVM by executing a script that you download from its repository in github.

$ curl -L https://get.rvm.io | bash -s stable

If this makes you nervous, you can always download the script first, inspect it, and then run it.

$ curl -L get.rvm.io >rvm-installer

$ less rvm-installer

$ bash rvm-installer

Behind the scenes, either option fetches a script from the RVM git repository and executes it on your local box. The end result is that RVM is installed in a directory named .rvm beneath your home directory. At the end of the process, RVM spits out a page or so of information. You should read it.

You may need to knit RVM into your environment. To find out, have a look at the end of ~/.bashrc. If it doesn’t mention RVM, add the following:

source $HOME/.rvm/scripts/rvm

Once that’s done, start a new terminal window (because RVM gets loaded only when your .bashrc file executes). Type rvm help, and you should get a summary of RVM usage.[7]

Before we use RVM to install Ruby, we have to let it install a few things that it will need. To do that, we need to let RVM install various system libraries and utilities that are used when building Ruby. First, we have to give it permission to manage packages:

dave@ubuntu:~$ rvm autolibs packages

If you run into problems, Wayne has a great set of hints on the RVM installation page.[8]

Installing Ruby 2.0 Under RVM

This is where we start to see the payoff. Let’s install Ruby 2.0. (Note that in the following commands we do not type sudo. One of the joys of RVM is that it does everything inside your home directory—you don’t have to be privileged to install or use new Ruby versions.)

$ rvm install 2.0.0

RVM first installs the system packages it needs (if any). At this stage, you may be prompted to enter a password that gives you superuser privileges.[9]

RVM then downloads the appropriate source code and builds Ruby 2.0. It also installs a few tools (including irb, RDoc, ri, and RubyGems). Be patient—the process may take five minutes or so. Once it finishes, you’ll have Ruby 2.0 installed. To use it, type the following:

dave@ubuntu:~$ rvm use 2.0.0

info: Using ruby 2.0.0

dave@ubuntu:~$ ruby -v

ruby 2.0.0p0 (2013-02-24 revision 39474) [i686-linux]

This is probably more work than you were expecting. If all you wanted to do was install a prepacked Ruby, we’d agree. But what you’ve really done here is given yourself an incredible amount of flexibility. Maybe in the future a project comes along that requires that you use Ruby 1.8.7. That’s not a problem—just use rvm install 1.8.7 to install it, and use rvm use 1.8.7 to switch to it.

The rvm use command applies only to the current terminal session. If you want to make it apply to all your sessions, issue this command:

$ rvm use --default 2.0.0

The RubyGems that you install while you’re using an RVM-installed Ruby will be added to that version of Ruby and not installed globally. Do not prepend the gem install command with a sudo—bad things will happen.

Why Stop with Ruby 2.0?

As well as installing stable versions of the Matz Ruby interpreter, RVM will also manage interpreters from different sources (JRuby, Rubinius, Ruby Enterprise Edition, and so on—rvm list known gives the full list). It will also install versions of Ruby directly from the developers’ repository—versions that are not official releases.

The Ruby developers use Subversion (often abbreviated as SVN) as their revision control system, so you’ll need a Subversion client installed on your machine. Once done, you can use RVM to install the very latest Ruby using rvm install ruby-head or the latest version of the 2.0 branch using rvm install 2.0-head.

Source Code from This Book

If a code listing is preceded by a filename in a shaded bar, the source is available for download.[10] Sometimes, the listings of code in the book correspond to a complete source file. Other times, the book shows just part of the source in a file—the program file may contain additional scaffolding to make the code run.

If you’re reading this as an ebook, you can download the code for an example by clicking the heading.

1.3 Running Ruby

Now that Ruby is installed, you’d probably like to run some programs. Unlike compiled languages, you have two ways to run Ruby—you can type in code interactively, or you can create program files and run them. Typing in code interactively is a great way to experiment with the language, but for code that’s more complex or that you will want to run more than once, you’ll need to create program files and run them. But, before we go any further, let’s test to see whether Ruby is installed. Bring up a fresh command prompt, and type this:[11]

$ ruby -v

ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin12.2.0]

If you believe that you should have Ruby installed and yet you get an error saying something like “ruby: command not found,” then it is likely that the Ruby program is not in your path—the list of places that the shell searches for programs to run. If you used the Windows One-Click Installer, make sure you rebooted before trying this command. If you’re on Linux or OS X and you’re using RVM, make sure you type rvm use 2.0 before trying to use Ruby.

Interactive Ruby

One way to run Ruby interactively is simply to type ruby at the shell prompt. Here we typed in the single puts expression and an end-of-file character (which is Ctrl+D on our system). This process works, but it’s painful if you make a typo, and you can’t really see what’s going on as you type.

$ ruby

puts "Hello, world!"

^D

Hello, world!

For most folks, irb —Interactive Ruby—is the tool of choice for executing Ruby interactively. irb is a Ruby shell, complete with command-line history, line-editing capabilities, and job control. (In fact, it has its own chapter: Chapter 18, Interactive Ruby Shell.) You run irb from the command line. Once it starts, just type in Ruby code. It will show you the value of each expression as it evaluates it. Exit an irb session by typing exit or by using the Ctrl+D.

$ irb

2.0.0 :001 > def sum(n1, n2)

2.0.0 :002?> n1 + n2

2.0.0 :003?> end

=> nil

2.0.0 :004 > sum(3,4)

=> 7

2.0.0 :005 > sum("cat", "dog")

=> "catdog"

2.0.0 :006 > exit

We recommend that you get familiar with irb so you can try our examples interactively.

Ruby Programs

The normal way to write Ruby programs is to put them in one or more files. You’ll use a text editor (Emacs, vim, Sublime, and so on) or an IDE (such as NetBeans) to create and maintain these files. You’ll then run the files either from within the editor or IDE or from the command line. I personally use both techniques, typically running from within the editor for single-file programs and from the command line for more complex ones.

Let’s start by creating a simple Ruby program and running it. Open a command window, and navigate to the pickaxe directory you created earlier:

$ cd ~/pickaxe (unix)

C:\> cd \pickaxe (windows)

Then, using your editor of choice, create the file myprog.rb, containing the following text.

gettingstarted/myprog.rb

puts "Hello, Ruby Programmer"

puts "It is now #{Time.now}"

(Note that the second string contains the text Time.now between curly braces, not parentheses.)

You can run a Ruby program from a file as you would any other shell script, Perl program, or Python program. Simply run the Ruby interpreter, giving it the script name as an argument:

$ ruby myprog.rb

Hello, Ruby Programmer

It is now 2013-05-27 12:30:36 -0500

On Unix systems, you can use the “shebang” notation as the first line of the program file:[12]

#!/usr/bin/ruby

puts "Hello, Ruby Programmer"

puts "It is now #{Time.now}"

If you make this source file executable (using, for instance, chmod +x myprog.rb), Unix lets you run the file as a program:

$ ./myprog.rb

Hello, Ruby Programmer

It is now 2013-05-27 12:30:36 -0500

You can do something similar under Microsoft Windows using file associations, and you can run Ruby GUI applications by double-clicking their names in Windows Explorer.

1.4 Ruby Documentation: RDoc and ri

As the volume of the Ruby libraries has grown, it has become impossible to document them all in one book; the standard library that comes with Ruby now contains more than 9,000 methods. Fortunately, an alternative to paper documentation exists for these methods (and classes and modules). Many are now documented internally using a system called RDoc .

If a source file is documented using RDoc, its documentation can be extracted and converted into HTML and ri formats.

Several websites contain a complete set of the RDoc documentation for Ruby.[13] Browse on over, and you should be able to find at least some form of documentation for any Ruby library. The sites are adding new documentation all the time.

The ri tool is a local, command-line viewer for this same documentation. Most Ruby distributions now also install the resources used by the ri program.[14]

To find the documentation for a class, type ri ClassName. For example, the following is the summary information for the GC class. (To get a list of classes with ri documentation, type ri with no arguments.)

$ ri GC

-----------------------------------------------------------------------------------

The GC module provides an interface to Ruby's garbage collection mechanism. Some of

the underlying methods are also available via the ObjectSpace module.

You may obtain information about the operation of the GC through GC::Profiler.

-----------------------------------------------------------------------------------

Class methods:

count, disable, enable, malloc_allocated_size, malloc_allocations,

start, stat, stress, stress=

Instance methods:

garbage_collect

For information on a particular method, give its name as a parameter:

$ ri GC::enable

---------------------------------------------------------------- GC::enable

GC.enable => true or false

---------------------------------------------------------------------------

Enables garbage collection, returning true if garbage collection was disabled.

GC.disable #=> false

GC.enable #=> true

GC.enable #=> false

If the method you give ri occurs in more than one class or module, ri will list the alternatives.

$ ri assoc

Implementation from Array

------------------------------------------------------------------------------

ary.assoc(obj) -> new_ary or nil

------------------------------------------------------------------------------

Searches through an array whose elements are also arrays comparing obj

with the first element of each contained array using obj.==.

Returns the first contained array that matches (that is, the first associated

array), or nil if no match is found.

See also Array#rassoc

s1 = [ "colors", "red", "blue", "green" ]

s2 = [ "letters", "a", "b", "c" ]

s3 = "foo"

a = [ s1, s2, s3 ]

a.assoc("letters") #=> [ "letters", "a", "b", "c" ]

a.assoc("foo") #=> nil

(from ruby site)

Implementation from ENV

------------------------------------------------------------------------------

ENV.assoc(name) -> Array or nil

------------------------------------------------------------------------------

Returns an Array of the name and value of the environment variable with

name or nil if the name cannot be found.

(from ruby site)

Implementation from Hash

------------------------------------------------------------------------------

hash.assoc(obj) -> an_array or nil

------------------------------------------------------------------------------

Searches through the hash comparing obj with the key using ==.

Returns the key-value pair (two elements array) or nil if no match is

found. See Array#assoc.

h = {"colors" => ["red", "blue", "green"],

"letters" => ["a", "b", "c" ]}

h.assoc("letters") #=> ["letters", ["a", "b", "c"]]

h.assoc("foo") #=> nil

For general help on using ri, type ri --help. In particular, you might want to experiment with the --format option, which tells ri how to render decorated text (such as section headings). If your terminal program supports ANSI escape sequences, using --format=ansi will generate a nice, colorful display. Once you find a set of options you like, you can set them into the RI environment variable. Using our shell (zsh), this would be done using the following:

$ export RI="--format ansi --width 70"

If a class or module isn’t yet documented in RDoc format, ask the friendly folks over at suggestions@ruby-doc.org to consider adding it.

All this command-line hacking may seem a tad off-putting if you’re not a regular visitor to the shell prompt. But, in reality, it isn’t that difficult, and the power you get from being able to string together commands this way is often surprising. Stick with it, and you’ll be well on your way to mastering both Ruby and your computer.

Footnotes

[5]

RVM isn’t the only way of managing multiple Ruby installations. You might want to look at rbenv ( https://github.com/sstephenson/rbenv/ ) or chruby ( https://github.com/postmodern/chruby ).

[6]

http://rvm.io/rvm/prerequisites/

[7]

The website, http://rvm.io/ , has even more information.

[8]

http://rvm.io/rvm/install/

[9]

This is the only time you’ll need these privileges. Once your system has all the tools it needs, RVM can do the rest of its work as a regular user.

[10]

http://pragprog.com/titles/ruby4/code

[11]

Remember, you may need to use ruby1.9 as the command name if you installed using a package management system.

[12]

If your system supports it, you can avoid hard-coding the path to Ruby in the “shebang” line by using #!/usr/bin/env ruby, which will search your path for ruby and then execute it.

[13]

Including http://www.ruby-doc.org and http://rubydoc.info

[14]

If you installed Ruby using rvm, there’s one additional step to get ri documentation available. At a prompt, enter rvm docs generate.