This simple tutorial helps beginners learn Ruby's basic syntax.
If you haven't installed Ruby yet, see the environment setup page for instructions
The History of Ruby
Many people think Ruby is a young language, but it was actually released in 1994 by a developer named Matz. Matz is a geek obsessed with programming languages and a big fan of Perl. He created Ruby hoping it would be as flexible and powerful as Perl, but with richer syntax and more readable code.
Ruby quickly gained a following. But before 2000, all Ruby documentation was in Japanese, so if you wanted to learn Ruby, you had to learn Japanese first. Dave Thomas, a pioneer of agile programming, fell in love with Ruby and decided to write documentation for it. He wrote an influential book called The Pickaxe , named for the picture on its cover. This book opened a window for the English-speaking world to learn about Ruby.
More people in the English-speaking world started to know Ruby, but growth was very slow. Only when system administrators started writing maintenance and "glue" scripts in Ruby (previously written in Perl) did Ruby start to catch on. From 2000 to 2005, the US
Ruby community had a few hundred members.
In 2004-2005, a Chicago company called 37signals hired a young programmer to build a web application. They cared only about the client-side design and functionality and gave the young programmer enormous freedom in the implementation. At the time, the main web technologies were Perl CGI, PHP, JSP, ASP, and so on, each with its own pain points. So David, whom we now call DHH, blazed a new trail.
He built the application in Ruby. Apart from the core libraries and a few helper libraries, he did almost everything himself. He and 37signals both worked on this application, which is now called Basecamp.
After Basecamp was finished, DHH extracted a web framework from the application. Unlike the top-down frameworks of Java and .NET, Rails was extracted entirely from a real-world case. It follows the principle of convention over configuration, making common problems easier to solve.
Rails was a huge success, and it drove enormous growth in the Ruby community. Today you can buy a dozen books about Ruby on Amazon, there are hundreds of Ruby conferences around the world, and thousands of people have become professional Ruby/Rails developers.
If you want to learn Rails, learn Ruby first. Let's go…
1. A Quick Overview and the Interpreter
Ruby is an interpreted language, which means it doesn't run directly on the processor. It runs through a virtual machine. The advantage is that you write it once and it runs on all kinds of operating systems and hardware platforms.
A Ruby program can't run on its own; you need to load the virtual machine first. There are two ways to run Ruby code in the VM: IRB and the command line.
Running Ruby from the Command Line
Writing Ruby code in a file is the most common and reliable approach. Files can be backed up, shared, added to source control, and so on.
A Simple Ruby Example
Let's create a file named my_program.rb like this
|
|
Then we run the program like this
|
|
When you run ruby my_program.rb, you're actually loading the virtual machine and running the my_program.rb file.
Running Programs from IRB
Ruby was one of the first languages to popularize an interactive shell: read-eval-print loop. Think of it like a calculator: when you enter a complete instruction, IRB executes it, evaluates the result, and prints it for you.
IRB is best used as a scratchpad for experiments. Many developers keep an IRB window open while programming, using it to recall how a method works or to debug code.
Let's use IRB for our experiments too. Open a terminal and type irb.
2. Variables
Programming is about creating abstractions. To create abstractions, we need to give things names, and variables are how we name data.
In some programming languages, a variable can hold only a specific type of data. Ruby doesn't require this; it has a very flexible type system, and any variable can hold any type of data.
Creating and Assigning Variables
In some programming languages, you have to declare a variable before assigning it. Ruby variables are created automatically when you assign them, with no declaration needed. Here's an example
|
|
The statement a = 5 creates the variable a and stores 5 in it.
Read from the Right
In everyday reading, we read left to right, so it feels natural to read code that way too. But when assigning with =, Ruby actually evaluates the right side first. For example:
|
|
10 + 5 is evaluated first, then the result is assigned to the variable b.
Flexible Variable Assignment
Ruby variables can hold any type of data and can even change the type they hold. For example:
|
|
First c is assigned 20, then the string "hello" is assigned to c, and c's value becomes "hello."
Variable Naming Rules
The virtual machine has format requirements for most Ruby variable names. Generally, they
- Start with a lowercase letter (an underscore also works, but it's uncommon)
- Have no spaces
- Can't contain special characters such as $, @, &, etc.
Beyond that, Ruby programmers share some common naming conventions:
- All words lowercase and joined by underscores
- Named after what the variable holds, not its type
- Not too short
Good variable names look like count, students_in_class, or first_lesson.
Don't write names like these:
- studentsInClass - uses camelCase instead of underscores; it should be students_in_class
- 1st_lesson - variables can't start with a number; it should be first_lesson
- students_array - the format is fine, but the name describes the data type, so it's not idiomatic; it should be students
- sts - too short; just use students
Exercise
Using the interactive IRB shell, try out which names are good, which are illegal, and which are legal but not Ruby style.
- time_machine
- student_count_integer
- 3_secitons
- top_ppl
3. Strings
In real life, a string is a cord you can use to tie things up. Strings in programming have nothing to do with that.
Strings store collections of numbers and letters. They can be a single letter "a," a word "hi," or a sentence like "hello world!"
Writing Strings
A Ruby string starts with a quote, contains zero or more letters, numbers, and symbols, and ends with a quote. The shortest string is the empty string "". It's not unusual for a string to hold a paragraph or even several pages of text.
Substrings
Sometimes we need to take part of a string; that's called a substring. For example
|
|
Positive and Negative Positions
The characters in a string usually have positive positions starting at 0. In "Hi," position 0 is "H" and "i" is position 1
We take substrings using start and end positions. For example, greeting[0..4] means the characters from position 0 to position 4, five characters in total.
The Ruby interpreter handles negative numbers by counting from the end of the string: in "Hi," "i" is position -1 and "H" is position -2.
So if a character has both a positive and a negative position, which should you use? Positive positions are easy to understand, but if you want the last few characters of a string (like "What's the last character of this string?"), use negative positions.
Common String Methods
Let's try a few common string methods in IRB
- length
The length method tells you how many characters a string has, including spaces:12342.1.2 :012 > greeting = "hello world"=> "hello world"2.1.2 :013 > greeting.length=> 11
Try calculating the length of your name
- split
You often need to split a string into parts. For example, you have a sentence stored in a string and want to split it into words:
|
|
The .split method returns an array. It splits the string on spaces.
- .split with an argument
Sometimes you want to split not on spaces but on a specific character. The .split method can take an argument to do this, for example1234562.1.2 :018 > numbers = "one,two,three,four,five"=> "one,two,three,four,five"2.1.2 :019 > numbers.split=> ["one,two,three,four,five"]2.1.2 :020 > numbers.split(",")=> ["one", "two", "three", "four", "five"]
The first call to split returned an array with the whole string because there were no spaces. In the second call, I specified ,
as the separator and got an array of five separate words.
.sub and .gsub
These two methods replace parts of a string, similar to find and replace in Word. .sub is short for substitute and replaces a single match. .gsub means global substitute and replaces all matches.
|
|
Combining Strings and Variables
We often need to combine variables with strings. For example, start with this string"Good morning, Frank!"
When we type this string into IRB, it just returns the string. In a program, we'd want it to greet each user by their own name, not just "Frank."
So we need to combine the string with a variable. There are two ways to do this
String Concatenation
The simplest way is string concatenation: just join them with +.
|
|
In the first line, we create a variable to hold the name. In the second line, we print "Good morning," the name variable, and the "!" string.
String Interpolation
The second way is string interpolation, inserting data into a string.
String interpolation works in double-quoted strings. Inside the string, we use #{} for interpolation. We can put variables and code to be evaluated inside, which gets converted to a string and output. The previous example can be rewritten with interpolation like this:
|
|
If you compare the output, you'll see the result is the same. The interpolation style takes fewer characters and fewer opening and closing quotes, so forget about the plus sign.
Running Code Inside Interpolation
You can put Ruby code and operators inside the interpolation braces, like this.
|
|
modifier * 3 + mood is evaluated first, then the result is inserted into the string and output.
4. Symbols
Symbols are harder to explain; they're somewhere between strings and numbers. Symbols are easy to recognize: they start with a colon followed by letters, like :flag or :best_friend.
If You're New to Programming
If you're new to programming, think of a symbol as a stripped-down string without many methods or string interpolation. Compare the methods a string supports with those of a symbol
|
|
If You're an Experienced Programmer
If you're an experienced programmer, think of a symbol as a "named integer." The actual value a symbol refers to doesn't matter; what matters is that any reference to it anywhere in the VM returns the same value. Symbols are defined in a global symbol table, and their values never change.
5. Numbers
There are two basic kinds of numbers: integers and floats (numbers with a decimal point).
Integers are relatively easy for both you and the computer to handle. You can use the usual operators, including +, -, /, *. Integers have many methods to help with math; you can see them with 5.methods.
Repeating Instructions
A common repetition pattern in other languages is the for loop, usually used to repeat an instruction many times. For example, in JavaScript you might write:
|
|
For loops are common, but this kind of code isn't very readable. Because integers in Ruby are objects, they have methods. One of them is times, which repeats an instruction a number of times. Rewriting the loop above in Ruby looks something like this.
|
|
In this example, what we pass to the times method is called a block. We'll discuss it in the next section. Run this example in IRB and see what happens.
6. Blocks
Blocks are a very powerful concept in Ruby and are used all the time. Think of them as a set of instructions that can be passed around and used in many places.
Starting and Ending Blocks
You just saw the .times method used on an integer
|
|
A block starts with do and ends with end. do/end always works.
Blocks in Braces
When a block contains just one simple instruction, we often use {} instead to mark its start and end
5.times{puts "Hello,world"}
Passing Blocks to Methods
What are blocks actually good for? They can be passed as arguments to method calls. For example, when we just called 5.times, Ruby didn't know what we wanted to run 5 times. Passing a block is like saying, "This is what I want you to run each time."
Many methods accept blocks. The .gsub method we saw in the strings section accepts a block, for example.
|
|
Notice that Found an E! appears three times, because there are 3 e's in the string.
Why the result is "sntnv" is left for you to figure out.
Block Parameters
We often need the statements inside a block to refer to the value currently being used. When writing a block, block parameters are marked with pipe characters
|
|
The value of a block parameter depends on the method we call. In this example, we call the times method on a number. Try the statement above and look at the output, then try this one:
|
|
When calling the .gsub method on a String, try this code (with braces):
You'll see that the .gsub method replaces the original characters with the result of the block.
7. Arrays
When we write programs, we often need to handle collections of data. In this section, we'll look at the most common collection: the array.
A Visual Model
An array is a numerically indexed list. Imagine drawing three small boxes on a sheet of paper:
|
|
You can number each one by its position from left to right
|
|
Then put a string in each box:
|
|
This array has three elements. Ruby arrays can grow or shrink, and elements are usually added at the end.
|
|
Think about why the last position in an array is always one less than the number of elements.
If you ask for the element at position 2, you get "Dinner." Ask for the last element and you get "Dessert."
Arrays in Code
Here's the same model in Ruby code.
|
|
Look at what happened above...
- Array elements are separated by commas and wrapped in square brackets
- Use two less-than signs
<<to add an element to an array - Get an element by putting its position inside
[] - There are also handy methods for getting data, such as
.last
Common Array Methods
Arrays can do lots of cool things. Here are a few examples:
The .sort Method Explained
The .sort method returns a new, sorted array. If the elements are strings, they're sorted alphabetically. If they're numbers, they're sorted in ascending order. Try it out
|
|
You can reorder elements with sort, loop through each element with each, join them into a string with join, find an element's position with index, and check whether an element is in the array with include?.
Use an array whenever you need an ordered list.
Try Some Others
eachcollectfirstandlastshuffle
For more details, see the documentation: Array
8. Hashes
A hash is also a collection of data, but unlike an array, its data has no order, and each item has a name. It's a lot like a fridge. When we look for something in the fridge, we don't really care which shelf it's on. Order doesn't matter. Instead, we sort things by name: 3 apples, 1 orange, 12 carrots. That's when we use a hash.
Key-Value Pairs
A hash is an unordered collection where data is stored as key-value pairs. Hash syntax is a bit more complex and takes some getting used to.
|
|
Think of the key as an address and the value as the data stored at that address. In the produce hash, we have the keys "apples" and "oranges", and their values are 12 and 3. When creating a hash, keys and values are joined with the => characters, which we call a rocket. So a hash starts with a curly brace {, contains zero or more entries made of a key, =>, and a value, separated by commas, and ends with a curly brace "}".
Try the following operations
|
|
In the first line, we add a new value to the hash. Because the "grapes" key wasn't in the original hash, it gets added with the value 221. Keys in a hash must be unique, so when we use the same syntax on produce["oranges"], the oranges key already exists and its value is replaced with 6. The keys and value methods return each half of the key-value pairs.
Simplified Hash Syntax
In real code, we often use symbols as hash keys. When all the keys are symbols, the hash syntax can be simpler.
|
|
Look closely and you'll notice the keys end with a colon instead of starting with one. Even so, they're still symbols. Ruby 1.9 and later support this simpler syntax. Run ruby -v in the console to see which Ruby version you're using.
9. Conditionals
A conditional expression evaluates to ture or false. The most common conditional operators are ==, >, >=, <, <=.
Some object methods also return true or false, so they work as conditional expressions too. For example, every object has a .nil? method, which returns true when the object is nil. Arrays have a method called .include?, which returns true when the array contains the element. By Ruby convention, methods that return true or false end with a ?.
Conditional Branches/Statements
Why do we use conditional statements? We often need to control what happens based on conditions, especially with the if/elsif/else structure. Let's write an example:
|
|
Let's see what the water_status method returns for 5, 7, 8, and 9.
|
|
Understanding the Flow
When minutes is 5, Ruby first checks whether it's less than 7. It is, so it prints The water is not boiling yet..
When minutes is 7, 7 isn't less than 7, so it moves on. It equals 7, so it prints It's just barely boiling.
When minutes is 8, Ruby checks whether 8 is less than 7. It isn't. It checks whether 8 equals 7. It doesn't. Moving on, it checks whether 8 equals 8. It does, so it prints It's boiling!.
When minutes is 9, the same logic applies and the last statement runs: Hot! Hot! Hot!.
Possible Forms of an if Statement
An if statement can have...
- Exactly one if statement, which runs only when its condition is true
- Zero or more elsif statements, which run only when their condition is true
- Zero or one else statement, which runs only when none of the if or elsif conditions are true.
Only one branch of an if/elsif/else structure can run. If the if condition is true, Ruby skips the elsif branches entirely. Only one block runs at a time. That's it.
Equality vs. Assignment
The most common mistake when writing conditionals is mixing up = and ==.
=is assignment. It puts the value on the right into the name on the left. It's a statement, not a question==is a question. It asks whether the thing on the left equals the thing on the right. It's a question, not a statement
You can also combine conditionals with logical operators. The most common are logical AND and logical OR, written as && and ||.
10. Nil & Nothingness
What is nothingness? Does it only exist in outer space? When we think of nothing, isn't it just an abstraction of something? OK, that's getting too philosophical...
In Ruby, nil means a value doesn't exist.
If you have 3 eggs and eat all 3, you might think you have nothing. But in terms of eggs, you have 0. Zero is a number, not nothingness.
If you have the string "hello" and delete the "h", "e", "l", and "o" characters, you might think you have nothing left. But you actually have "", an empty string. That isn't nothingness either.
nil is Ruby's idea of nothingness. It shows up when you ask for something that doesn't exist. If we create an array with only 5 elements and insist on asking for the sixth, Ruby gives us nil. That doesn't mean the sixth slot is blank. Unlike a number, it simply doesn't exist: nil.
Most errors you'll run into when writing Ruby involve nil. You think you're working with something and try to use it, but you can't operate on something that doesn't exist, so Ruby raises an error.
11. Objects, Attributes, and Methods
Ruby Is an Object-Oriented Language
Ruby is an object-oriented language. Everything we work with in the virtual machine is an object. Every piece of data is an object. The information an object holds is called its attributes. The actions an object can perform are called its methods.
For an example of an object, think of yourself as a person. Your attributes include height, weight, and eye color. Your methods include walking, running, washing dishes, and dreaming. Different objects have different attributes and methods. In the next section, we'll look at common Ruby objects.
Classes and Instances
Object-oriented languages define classes. A class describes a category or type of thing. It defines the attributes and methods that all objects of that type share.
Defining a Class
Let's model a school. We create a Student class to represent all students. The Student class has the attributes first_name, last_name, and primary_phone_number. We can also define an introduction method so students can introduce themselves.
|
|
You may not know the attr_accessor method yet. It defines attributes for instances of a class.
Creating Instances
The class itself doesn't represent a student. It's just an abstract description of students. To represent a real student, we create an instance from the class.
Imagine you're a student. You aren't an abstract concept; you're a real person. That real person is a student instance, a concrete realization of the abstract concept. All the attributes hold real data: first_name, last_name, primary_phone_number.
Running Ruby from a File
We rarely define classes in IRB. It's just our scratchpad for quickly testing ideas. Let's see how to run a Ruby file.
- Exit the IRB session
- Create a folder from the command line to use as your working directory
- Use a text editor to create a file named student.rb
- Save it in your editor
- Run it from the command line
ruby student.rb The file is empty, so you won't see any output.
Creating a Student Class
In your text editor, write a class with this structure
|
|
Methods inside a class are usually defined with the def keyword:
|
|
Notice the puts line is a method that returns the student's first name. Let's add the attributes we used earlier.
|
|
Running the File
Go back to the terminal and run the program. Still no output...
Why? We defined a Student class, gave it a method, and added some attributes. But we never actually created an instance or called any methods.
Creating an Instance
After defining the class, we need to create an instance: frank = Student.new
We called the Student class's new method and stored the result in a variable named frank. Once we have an instance, we can set or read its attributes and call its methods.
Creating an Instance in the File
At the bottom of student.rb, after the last end, add the following lines.
|
|
Save, go back to the terminal, and run student.rb again. This time it should print Hi, I'm Frank!
Method Arguments
Sometimes methods take one or more arguments that tell them how to do what they do. For example, I want frank.introduction('katrina') to have Frank introduce himself to Katrina. Arguments can be numbers, strings, or any object. Change your method so it takes an argument:
|
|
Now run the file again, and you'll see Hi Katrina, I'm Frank.
Return Values
In Ruby, every method call returns a value. By default, a Ruby method returns the value of the last expression it runs.
Adding favorite_number
Add a favorite_number method to our class.
|
|
Run it from your terminal and you'll see Frank's favorite number is 7. The last line calls the favorite_number method. That method's last line is 7, so 7 becomes its return value and is handed back to whoever called it. Here, 7 is returned and interpolated into the string.
You're Off to a Good Start
That's the end of this quick introduction. Now you can dive deeper into the delights of Ruby.
Translated from Ruby in 100 Minutes
