This article was written in 2011 and remains one of our most popular posts. If you’re keen to learn more about Ruby and the Rails framework, you may want to head straight to the source — RubySource, that is — and you may find this recent article on Ruby and Sass of great interest.
While it certainly makes no attempt to constitute a complete guide to the Ruby language, this tutorial will introduce you to some of the basics of Ruby. We’ll power through a crash-course in object oriented programming, covering the more common features of the language along the way, and leaving the more obscure aspects of Ruby for a dedicated reference guide. I’ll also point out some of the advantages that Ruby has over other languages when it comes to developing applications for the Web. After reading this, you’ll be ready to dive into our dedicated Ruby site, www.rubysource.com
Some Rails developers suggest that it’s possible to learn and use Rails without learning the Ruby basics first, but as far as I’m concerned, it’s extremely beneficial to know even a little Ruby before diving into the guts of Rails. In fact, if you take the time to learn the Ruby basics first, you’ll automatically become a better Rails programmer.
That’s what this tutorial is all about. In fact, this information is excerpted from my new book, Build Your Own Ruby On Rails Web Applications, which is now available through sitepoint.com. The two chapters presented here get straight into the finer points of Ruby and Rails. If you need installation and other setup instructions, download the sample PDF, which contains chapters 1 to 4.
Ruby is a Scripting Language
In general, programming languages fall into one of two categories: they’re either compiled languages or scripting languages. Let’s explore what each of those terms means, and understand the differences between them.
The language in which you write an application is not actually something that your computer understands. Your code needs to be translated into bits and bytes that can be executed by your computer. This process of translation is called compilation, and any language that requires compilation is referred to as a compiled language. Examples of compiled languages include C, C#, and Java.
For a compiled language, the actual compilation is the final step in the development process. You invoke a compiler — the software program that translates your final hand-written, human-readable code into machine-readable code — and the compiler creates an executable file. This final product is then able to execute independently of the original source code.
Thus, if you make changes to your code, and you want those changes to be incorporated into the application, you must stop the running application, recompile it, then start the application again.
On the other hand, a scripting language such as Ruby, PHP, or Python, relies upon an application’s source code all of the time. Scripting languages don’t have a compiler or a compilation phase per se; instead, they use an interpreter — a program that runs on the web server — to translate hand-written code into machine-executable code on the fly. The link between the running application and your hand-crafted code is never severed, because that scripting code is translated every time it is invoked — in other words, for every web page that your application renders.
As you might have gathered from the name, the use of an interpreter rather than a compiler is the major difference between a scripting language and a compiled language.
The Great Performance Debate
If you’ve come from a compiled-language background, you might be concerned by all this talk of translating code on the fly — how does it affect the application’s performance?
These concerns are valid — translating code on the web server every time it’s needed is certainly more expensive, performance-wise, than executing pre-compiled code, as it requires more effort on the part of your machine’s processor. The good news is that there are ways to speed up scripted languages, including techniques such as code caching and persistent interpreters. However, both topics are beyond the scope of this book.
There’s also an upside to scripted languages in terms of performance — namely, your performance while developing an application.
Imagine that you’ve just compiled a shiny new Java application, and launched it for the first time … and then you notice a typo on the welcome screen. To fix it, you have to stop your application, go back to the source code, fix the typo, wait for the code to recompile, and restart your application to confirm that it is fixed. And if you find another typo, you’ll need to repeat that process again. Lather, rinse, repeat.
In a scripting language, you can fix the typo and just reload the page in your browser — no restart, no recompile, no nothing. It’s as simple as that.
Ruby is an Object Oriented Language
Ruby, from its very beginnings, was built as a programming language that adheres to the principles of object oriented programming (OOP). Before getting into Ruby specifics, I’d like to introduce you to some fundamental concepts of OOP. Now I know that theory can seem a bit dry to those who are itching to start coding, but we’ll cover a lot of ground in this short section, so don’t skip it. This discussion will hold you in good stead — trust me.
OOP is a programming paradigm that first surfaced in the 1960s, but didn’t gain traction until the 1980s with C++. The core idea behind it is that programs should be composed of individual entities, or objects, each of which has the ability to communicate with other objects around it. Additionally, each object may have the facility to store data internally, as depicted in Figure 3.1.
Figure 3.1. Communication between objects
Objects in an OOP application are often modeled on real-world objects, so even non-programmers can usually recognize the basic role that an object plays.
And, just like the real world, OOP defines objects with similar characteristics as belonging to the same class. A class is a construct for defining properties for objects that are alike, and equipping them with functionality. For example, a class named Car might define the attributes color and mileage for its objects, and assign them functionality — actions such as “open the trunk,” “start the engine,” and “change gears.” These different actions are known as methods, although you’ll often see Rails enthusiasts refer to the methods of a controller as “actions” — you can safely consider the two terms to be interchangeable.
Understanding the relationship between a class and its objects is integral to understanding how OOP works. For instance, one object can invoke functionality on another object, and can do so without affecting other objects of the same class. So, if one car object was instructed to open its trunk (think of KITT, the talking car from the classic 80s television show “Knight Rider,” if it helps with the metaphor), then its trunk would open, but the trunk of other cars would remain closed. Similarly, if our high-tech talking car were instructed to change color to red, then it would do so, but other cars would not. (“Knight Rider” was a popular series in the 1980s that featured modern-day cowboy Michael Knight (played by David Hasselhoff) and his opinionated, talking, black Pontiac Firebird named KITT. Having seen the show is not critical to understanding object oriented programming?just knowing that the car could talk will suffice!)
When we create a new object in OOP, we base it on an existing class. The process of creating new objects from a class is called instantiation. Figure 3.2 illustrates the concept.
Figure 3.2. Classes and objects
As I mentioned, objects can communicate with each other and invoke functionality (methods) on other objects. Invoking an object’s methods can be thought of as asking the object a question, and getting an answer in return.
Consider the example of our famous talking car again. Let’s say we ask the talking car object to report its current mileage. This question is not ambiguous — the answer that the object gives is called a return value, and is shown in Figure 3.3.
Figure 3.3. Asking a simple question
In some cases, the question and answer analogy doesn’t quite fit. In these situations, we might rephrase the analogy to consider the question to be an instruction, and the answer a status report indicating whether or not the instruction was executed successfully. This might look something like the diagram in Figure 3.4.
Figure 3.4. Sending instructions
Sometimes we need a bit more flexibility with our instructions. For example, if we wanted to tell our car to change gear, we need to tell it not only to change gear, but also which gear to change to. The process of asking these kinds of questions is referred to as passing an argument to the method.
An argument is an input value that’s provided to a method. An argument can be used in two ways:
- to influence how a method operates
- to influence which object a method operates on
An example is shown in Figure 3.5, where the method is “change gear,” and the number of the gear to which the car must change (two) is the argument.
Figure 3.5. Passing arguments
A more general view of all of these different types of communication between objects is this: invoking an object’s methods is accomplished by sending messages to it. As one might expect, the object sending the message is called the sender, and the object receiving the message is called the receiver.
Armed with this basic knowledge about object oriented programming, let’s look at some Ruby specifics.
Reading and Writing Ruby Code
Learning the syntax of a new language has the potential to induce the occasional yawn. So, to make things more interesting, I’ll present it to you in a practical way that lets you play along at home: we’ll use the interactive Ruby shell.
The Interactive Ruby Shell (irb)
You can fire up the interactive Ruby shell by entering irb into a terminal window.
Not the Standard DOS Box!
Windows users, don’t forget to use the Open Ruby Console option from the Instant Rails control panel, to make sure the environment you’re using contains the right settings.
irb allows you to issue Ruby commands interactively, one line at a time. This is great for playing with the language, and it’s also great for debugging, as we’ll see in Chapter 11, Debugging, Testing, and Benchmarking.
A couple of points about the irb output you’ll see in this chapter:
- Lines beginning with the Ruby shell prompt (irb>) are typed in by you (and me).
- Lines beginning with => show the return value of the command that has been entered.
We’ll start with a really brief example:
irb> 1 => 1
In this example, I’ve simply thrown the number 1 at the Ruby shell, and got back what appears to be the very same number.
Looks can be deceiving, though — it’s actually not the very same number. What we were handed back is in fact a fully-featured Ruby object.
Remember our discussion about object oriented programming in the previous section? Well, in Ruby, absolutely everything is treated as an object with which we can interact — each object belongs to a certain class, therefore each object is able to store data and functionality in the form of methods.
To find the class to which our number belongs, we call the number’s
irb> 1.class => Fixnum
We touched on senders and receivers earlier. In this example, we’ve sent the class message to the
1 object, so the
1 object is the receiver (there’s no sender, as we’re sending the message from the interactive command line rather than from another object). The value that’s returned by the method we’ve invoked is
Fixnum, which is the Ruby class that represents integer values.
Since everything in Ruby (including a class) is an object, we can actually send the very same message to the
Fixnum class. The result is different, as we’d expect:
irb> Fixnum.class => Class
This time, the return value is
Class, which is somewhat reassuring — we did invoke it on a class name, after all.
Note that the method
class is all lowercase, yet the return value
Class begins with a capital letter. A method in Ruby is always written in lowercase, whereas the first letter of a class is always capitalized.
Patrick has been developing web applications for ten years. Founder and lead developer of the freshmeat.net software portal, he and his Rails consultancy and application development company, limited overload were responsible for a major relaunch of Germany's biggest infotainment community. Patrick lives in Wiesbaden, Germany. His weblog can be found at poocs.net.