Jumpstart Lab > Course Resources > Ruby Jumpstart > Ruby in 100 Minutes

Ruby in 100 Minutes

Ruby is a great language for beginners because it was written to make the programmer’s job easy — and not care if the computer’s job is hard. In this brief introduction we’ll look at the key language features you need to get started.

  1. Instructions and Interpreters
  2. Variables
  3. Methods
  4. Strings
  5. Numbers
  6. Symbols
  7. Collections
    • Arrays
    • Hashes
  8. Conditionals
    • Conditional Decisions
    • Conditional Looping
  9. Nil & Nothingness

1. Instructions & Interpreters

There are two ways to run Ruby code. You can write one or more instructions in a file then run that file through the Ruby interpreter. This is how we’ll run most of our work. When you’re writing a “real” program, this is the way to do it.

The second option is to use the Interactive RuBy shell — IRB. When I’m programming I always have IRB open. IRB has all the same features as the regular Ruby interpreter, but it allows you to easily evaluate one or a handful of instructions and instantly see their results. I use IRB, mostly, for checking myself. In a regular program I might write a hundred lines of instructions. But if there’s one thing I’m not sure about I’ll flip over to IRB to test it out. Start IRB by opening a Terminal (Mac) or Command Prompt (Win) and typing irb.

When we write our projects in RubyMine you’ll be running them through the Ruby interpreter. While you’re working through this introduction, though, you should use IRB.

2. Variables

Everything needs a name so we can refer to it. A variable, like in math, is just a name for a piece of data. In Ruby variables are very flexible and can be changed at any time. Variables are assigned using a single equals sign (=) where the right side of the equals sign is evaluated first, then the value is assigned to the variable named on the left side of the equals. Go into IRB, enter in these example instructions, and observe the output that Ruby gives you back:

a = 5
b = 10 + 5
c = 15 + a + b
b = c - a
d = "Hello, "
e = "World!"
f = d + e
g = d*a + e
b = "hi!" * b

3. Objects, Attributes, and Methods

In Ruby, everything is an object. Objects know information, called attributes, and they can do actions, called methods.

For an example of an object, think about you as a human being. You have attributes like height, weight, and eye color. You have methods like “walk”, “run”, “wash dishes”, and “daydream.” Different kinds of objects have different attributes and methods. In the next sections we’ll look at a few specific kinds of objects common in Ruby.

In Ruby we define an object using the class keyword, here’s an example defining the object type PersonalChef:

class PersonalChef

end

Inside the class we usually define one or more methods using the def keyword like this:

class MyNewClassName
  def make_toast

  end
end

Inside the def and end lines we’d put the instructions for how the chef should make the toast.

A class is an abstract idea, it defines what all objects of that type can know and do. Think of the chair you’re sitting in. It’s not an abstract chair, it is an actual chair. We’d call this actual chair an instance – it is a realization of the idea chair. It has measurable values like height, color, weight and abilities like hold_up_a_person. The class chair, on the other hand, has an abstract weight, color, and size — we can’t determine them ahead of time.

Once we define a class, we create an instance of that class like this:

frank = PersonalChef.new

We’re calling the new method on the class PersonalChef and storing it into the variable named frank. Once we have that instance, we can set or get its attributes and call its methods. Methods are called by using this syntax: object.method_name. So if you have a person named frank you would tell him to make toast by calling frank.make_toast.

Method Parameters

Sometimes methods take one or more parameters that tell them how to do what they’re supposed to do. For instance, I might call frank.make_toast('burned') for him to burn my toast. Or maybe he has another method where I call frank.make_breakfast("toast","eggs") for him to make both toast and eggs. Parameters can be numbers, strings, or any kind of object. When a method takes a parameter it’ll look like this:

class MyNewClassName
  def make_toast(color)

  end
end

Where the method is expecting us to pass in a color telling it how to do the method make_toast.

Method Chaining

Often we’ll want to call multiple methods on an object one after the other — this is called method chaining . Still thinking about frank, imagine that he has a method named make_toast that takes a parameter of darkness and a method named eggs that takes a parameter of quantity. We can call multiple methods by using the format object_name.method1.method2.method3. So for this example, we might say:

frank.make_toast("burned").make_eggs(6)

To read that in Engish, we’re telling frank to make_toast with the parameter burned, then after that is completed telling him to make_eggs with the parameter 6.

4. Strings

In Ruby a string is defined as a quote (") followed by zero or more letters, numbers, or symbols and followed by another quote ("). Some simple strings would be "hello" or "This sentence is a string!". Strings can be anything from "", the empty string, to really long sets of text. This whole tutorial, for instance, is stored in a string. Strings have a few important methods that we’ll use.

Experiment with the following samples in IRB:

tester = "Good Morning Everyone!"
tester.length
tester.delete("o")
tester.gsub("Everyone!","Friends!")
t2 = "sample,data,from,a,CSV"
t2.split(",")

Often with strings we want to pull out just a part of the whole — this is called a substring. Try out these examples in irb assuming you already have tester from the last examples:

tester[0..3]
tester[5..11]
tester[13..-1]

The numbers inside the [] brackets specify which of the characters you want pulled out. They’re numbered starting with zero. So the first example pulls out the letters from zero, the beginning of the string, up to position three. The second example pulls from 5 up to 11. The last one goes from 12 up to…-1? If you specify a negative value, that is like counting back from the end. Using -1 means the end of the string, so 12..-1 means “from 12 to the end of the string.”

If you just need a single character, there’s a “gotcha” — it’d be tempting to write tester[2] to get the character at position two. In the latest versions of Ruby (1.9+) that’s exactly how it works. But in 1.8.6 and some versions of 1.8.7, that code will give you back an integer representing the ASCII code for that letter — pretty useless! The hack, which works on any version of Ruby, is to take a substring that is only one character long like this: tester[2..2]

Combining Strings and Variables

It is extremely common that we want to combine the value of a variable with other strings. For instance, lets start with this simple example string:

"Happy Saturday!"

When we put that into IRB it just spits back the same string. If we were writing a proper program we might want it to greet the user when they start the program by saying "Happy" then the day of the week. So we can’t just put a string like "Happy Saturday!" or it’d be saying Saturday even on Tuesday.

What we need to do is combine a variable with the string. There are two ways to do that. The first and easiest approach is called string concatenation which is basically just adding strings together like this:

today = "Saturday"
puts "Happy " + today + "!"

In the first line we setup a variable to hold the day of the week, then in the second line we printed the string Happy combined with the value of the variable today and the string !. You might be thinking “What was the point of that since we still just wrote Saturday in the first line?” Ok, well, if you were writing a real program you’d use Ruby’s built-in date functions like this:

today = Date.today.strftime("%A")
puts "Happy " + today + "!"

If you get an error complaining about Date being unitialized, type require 'Date', enter, then try it again.

String concatenation works great, but there is a gotcha that frequently pops up. Try this:

today = Date.today.strftime("%A")
day_of_year = Date.today.yday
puts "Happy " + today + "! It is the " + day_of_year + " day of the year."

You should get an error complaining that Ruby “can’t convert Fixnum into String”. What does that mean? When Ruby is assembling the parts of that string it sees a string "Happy ", then a string in the variable today, then a string with the ! and a few words, then a the variable day_of_year, then the string "day of the year.".

The problem is that ruby knows how to add one string to another, but it’s not sure how to add a string to a number. day_of_year contains a number, and when it tries to combine the strings with that number Ruby isn’t sure what to do. Thankfully numbers have a conversion method which converts them into a string so they can be combined with strings. That method is .to_s for “to string”. Retry your example with this slight change:

today = Date.today.strftime("%A")
day_of_year = Date.today.yday
puts "Happy " + today + "! It is the " + day_of_year.to_s + " day of the year."

Great, no errors and our output looks correct. Having to remember that .to_s whenever you use a number is kind of a pain, though. There is another combination method that forces the “to string” conversion for you called string interpolation.

String interpolation is the process of sticking data into the middle of strings. We use the symbols #{} to mark where in a string the value of a variable should be inserted. Inside those brackets we can put any variables or Ruby code which will be evaluated, converted to a string, and output in that spot. Our previous example could be rewritten like this:

puts "Happy #{today}! It is the #{day_of_year} day of the year."

If you compare the output you’ll see that this second method gives the exact same results. The code itself is a little more compact and, personally, I find it much easier to read.

You can also put code or calculations inside the brackets when interpolating like this example:

modifier = "very "
mood = "excited"
puts "I am #{modifier * 3}#{mood} for today's class!"

Basically interpolating means “evaluate the code inside this #{} wrapper and put it into this string”. You can see the first interpolation has a multiplication inside there so it’ll repeat the string modifier three times but the second will just plug in the value of the variable mood.

5. Numbers

There are two basic kinds of numbers: integers (whole numbers) and floats (have a decimal point). For our workshop we’ll only be dealing with integers. You can use normal math operations with integers including +, -, /, and *. Integers have a bunch of methods to help you do math-related things, but the only one we might use controls a loop.

The times method can be used to repeat one or more instructions a certain number of times. Try out this example:

5.times do
  puts "Hello, world!"
end

In this example we’re using the times method with a do/end block. When we call the times method we need to tell it what to do that number of times. Ruby looks for the starting keyword do and the ending keyword end. Each instruction between the do and end will be executed this number of times. Try this example with multiple instructions:

5.times do
  puts "Good morning!"
  puts "...is it lunch time yet?"
end

6. Symbols

Symbols are difficult to explain. A symbol starts with a colon then one or more letters. Here are some example symbols: :one, :tester, :first

We won’t use them very often in this class, but if you see an object that looks like :this, you’ll know it’s a symbol. Think of it as a stripped down string that has barely any methods and no string interpolation. They’re only used to represent data inside the program. We’d never print a symbol out to a user, it is just a type of marker used within our code.

7. Collections

Often we need to organize a group of objects and put them into a collection. There are two main types of collections: arrays and hashes.

Arrays

An array is a number-index list. Picture a city block of houses. Together they form an array and their addresses are the indices. Each house on the block will have a unique address. Some addresses might be empty, but the addresses are all in a specific order. The index is the address of a specific element inside the array. In Ruby the index always begins with 0. An array is defined in Ruby as an opening [, then zero or more elements, then a closing ]. Try out this code:

favorite_colors = ["red","blue","green","black","brown"]
puts favorite_colors[3]
puts favorite_colors.first
puts favorite_colors.last

Keep going with these, but not that the first line below should give you some unusual output. Try and understand what Ruby is telling you:

puts favorite_colors[5]
favorite_colors << "orange"
puts favorite_colors[5]
puts favorite_colors

In order to get a specific element in the array you use the syntax arrayname[index]. So looking at the favorite_colors array…

There are lots of cool things to do with an array. You can rearrange the order of the elements using the sort method. You can iterate through each element using the each method. You can mash them together into one string using the join method. You can find the address of a specific element by using the index method. You can ask an array if an element is present with the include? method. Try out this example that brings a bunch of things together:

sorted_colors = favorite_colors.sort
sorted_colors.each do |color|
  puts "#{color} is #{color.length} letters long"
end
puts sorted_colors.join(" & ")

target = "green"
position = favorite_colors.index(target)
puts "The color #{target} is in position #{position}"

We use arrays whenever we need a quick list and want the elements in a specific order.

Hashes

A hash is a collection of data where each element of data is addressed by a name. As an analogy, think about a classroom of children. Under ideal circumstances, each student has a name and can be found by using that name. We might look in a science classroom for a child named Joey and that would result in finding an actual student. We could write this like science["Joey"] which could be read as “look in the collection named science and find the thing named Joey.”

A hash is an unordered collection, it’s just a bunch of data collected together where each one has a unique name. Hashes have a more complicated syntax that takes some getting used to:

ages = {"joey" => 12, "jill" => 14, "jack" => 11, "jane" => 12}
puts "Joey is #{ages['joey']} years old"

Here we create a hash named ages. Hashes are made up what are called “key-value pairs.” The key is used as the address and the value is the object at that address. In the ages hash we have keys including "joey" and "jill" and values including 12 and 14. When creating a hash the key and value are linked by the => symbol which is called a rocket. So hashes start with a curly bracket {, have zero or more entries made up of a key, a rocket, and a value separated by commas, then end with a closing curly bracket }.

ages["jimmy"] = 14
ages["joey"] = 9
puts ages.keys
puts ages.values

In the second chunk of the example, we add a new value to the hash. Since the "jimmy" key wasn’t in the original hash, it’s added with the value of 14. If the key "jimmy" already existed then the value would be replaced by 14. Every key in a hash must be unique! In the second line we reference the key "joey" which already exists, so the value gets replaced with the 9. Then, just to show you the state of the hash, we print out the list of keys and the list of values.

students = ages.keys.sort
students.each do |student|
  puts "#{student} is #{ages[student]} years old."
end

The last chunk of the example calls the keys method on the hash ages. keys gives back an array holding all the key values inside the hash. We then called sort on that array to put them in alphabetical order before storing the array into the variable students. We then iterated through the array students using the method each, gave each element of the list the name student, then printed out one line with that student name and the student’s age from ages.

While that last part probably seemed complicated, it’s just to illustrate that although hashes are by nature unordered, you can still manipulate and output the data in ordered, meaningful ways.

8. Conditionals

Conditional statements evaluate to true or false only. The most common conditional operators are == (equal), > (greater than), >= (greater than or equal to), < (less than), and <= (less than or equal to).

Some objects also have methods which return a true or false, so they’re used in conditional statements. For example every object has the method .nil? which is true only when the object is nil. Arrays have a method named .include? which returns true if the array includes the specified element.

Conditional Branching / Instructions

Why do we have conditional statements? Most often it’s to control conditional instructions, especially if/elsif/else structures. Try out this example:

total = 5

if total < 7
  puts "Total is less than seven"
elsif total == 7
  puts "Total is exactly equal to seven"
else
  puts "Total is greater than seven"
end

Try this example using 5, 7, and 9 for the value of total.

When the total is 5, here is how the execution goes: “Is it true that 5 is less than 7? Yes, it is, so print out the line Total is less than seven”.

When the total is 7, it goes like this: “Is it true that 7 is less than 7? No. Next, is it true that 7 is equal to 7? Yes, it is, so print out the line Total is exactly equal to seven”.

Lastly, when total is 9, it goes: "Is it true that 9 is less than 7? No. Next, is it true that 9 is equal to 7? No. Ok, then print the line Total is greater than seven.

An if block has…

Only one section of the if/elsif/else structure can have it’s instructions run. If the if is true, for instance, Ruby will never look at the elsif. Once one block executes, that’s it.

Conditional Looping

Another time we use conditional statements is when we want to repeat a set of instructions. Try out this simple example:

counter = 0
while counter < 10
  puts "The counter is only #{counter}"
  counter = counter + 1
end

See how that works? The counter starts out as zero. The while instruction evaluates the conditional statement counter < 10 and finds that yes, zero is less than ten. Since the condition is true, execute the instructions inside the loop. First print out "The counter is only 0" then take the value of counter, add one to it, and store it back into counter. Then the loop goes back to the while statement. Is one less than ten? Yes, so print the line and add one again. Is two less than 10? Yes…and so on.

I most often use while, but you can achieve the same results using until as well. Try this…

counter = 0
until counter == 10
  puts "The counter is only #{counter}"
  counter = counter + 1
end

The #1 mistake people encounter when writing conditional statements is the difference between = and ==.

You can also combine conditional statements using logical operators. The most common are known as “logical and” and “logical or”. In Ruby you can write a logical and with either the work and or with double ampersands like this: &&. You can write a logical or with the word or or with double pipes like this: ||. For each operation, the symbolic representation (&& and ||) is more common.

9. Nil & Nothingness

What is nothingness? Is there nothingness only in outer space? Really, when we think of “nothing” isn’t it just the absence of something? Ok, that’s too much philosophy…

nil is Ruby’s way of referring to “nothingness.”

If you have three eggs, eat three eggs, then you might think you have “nothing”, but in terms of eggs you have “0”. Zero is something, it’s a number, and it’s not nothing.

If you’re working with words and have a string like “hello” then delete the “h”, “e”, "l"s, and “o” you might think you’d end up with nothing, but you really have "" which is an empty string. It’s still something.

nil is Ruby’s idea of nothingness. It’s usually encountered when you ask for something that doesn’t exist. When looking at arrays, for instance, we created a list with five elements then asked Ruby to give us the sixth element of that list. There is no sixth element, so Ruby gave us nil. It isn’t that there’s a blank in that sixth spot (""), it’s not a number 0, it’s nothingness — nil.

A large percentage of the errors you encounter while writing Ruby code will involve nil. You thought something was there, you tried to do something to it, and you can’t do something to nothing so Ruby creates an error. Try out these instructions to illustrate nil:

tester = "hello"

if tester.nil?
  puts "Tester is nil! Noooooooooo!"
else
  puts "Tester is not nil, the earth is saved."
end

puts tester*5
puts tester.length

Now do it again, but change the first line so tester = nil. Read the error messages carefully — you’ll be seeing them soon!