Ruby For Beginners

Ruby Monday Study Group curriculum for beginners

This book has been written after we have run 4 beginners groups at our Ruby Monstas groups in Berlin, and it outlines the current state of our beginner groups curriculum.

After completing this curriculum you’ll be able to read, understand, and write basic Ruby code yourself:

You can use this knowledge to create small tools that might help you in your day-to-day work (such as converting numbers, or extracting data from files) that normally would cost a lot of manual work. You’ll be able to jump into other tutorials, and have a much easier time understanding what they’re talking about. And you can start working on our next curriculum which will walk you through the basics of building an actual web application.

If you’d like to print this book, or export it as a PDF try using this page, which is a single-page version of the entire book.

You can find the source code of this book here.

Preface

Read this book at your own pace, and do exercises at your own pace.

We recommend reading at least a page a day (ideally more), and taking some more time, at least once a week, in addition to the weekly meeting on Mondays. It often helps to meet with others, have some coffee and cake, and hang out while reading some more of this book, or doing a few exercises together.

We suggest that you read the book from beginning to end, and do exercises as you go. If you come across chapters that you feel are too theoretical you can skip them for the time being and come back to them later, if needed.

If you’d prefer to jump right in, you can also skip over the introductory chapters. Jump to the chapter “Your tools”, and read the introductory chapters later. If you already feel familiar with your editor and terminal, and know how to use ruby to execute a Ruby file, then you can skip over the chapter “Your tools”, too.

Take notes about whatever questions come up during the week, things that you don’t understand, and everything else worth mentioning (for example, epiphanies you have, or things you found interesting). Bring your notes to the study group so we can talk about them in the group.

Please help us improve this book for others: Whenever you find something unclear or missing then please tell us. You can do this during the study group, email the mailing list, or ideally file an issue here. (This also helps you get familiar with GitHub, which we will use a lot later on.)

By using the name “Ada” in examples in this book we give credit to Ada Lovelace, the world’s first computer programmer :)

Resources

We also recommend looking at, reading, and working through other resources, as much as you can. Every beginners book expresses things a little bit differently, in a different order, and from a different angle.

Overview

Recommended reading

Online courses

Puzzles

Role model stories

Resources for coaches

Programming is creation

Things coming to life

Programming is creation. Whenever you run a program a little universe is created. Things come to life and interact with each other, according to the rules that you, as their creator, define.

Imagine you build an application like Twitter. Then, as a developer, in the programming language of your choice, you would say things like “Let there be users! And let there be tweets!”, and once your application starts these things will come into existence. Next you would go ahead and define “Users can create tweets, and they can follow each other”. And from now on, every time new users are created in the little universe that is your application, these users will have the ability to tweet and follow each other.

Learning to program

Brainwashing yourself

Learning to program means, fundamentally, two things: Learning a new language, and learning to solve problems by way of using this language. This means writing code and describing your solution to the problem.

When this text, the one that you are reading right now, was written, the author used the language English trying to come up with an adequate solution to the problem “How can someone best start learning to program?” Reading this text you also use the language English. If you think about what you are doing right now, you will notice that you do not think about English as a language at all. Right? Instead you use the language in order to figure out what this author might be talking about, and what that might mean to you.

Try to remember when you last walked up the stairs. Walking up the stairs is a pretty complex series of movements, and it took you quite a while to properly learn it as a child. The exact order and coordination of movements, bending your knees, ankles, while keeping your overall balance, is so complex that we probably wouldn’t even be able to describe it properly. However, we have somehow managed to learn this ability and we can now use it.

The point I am trying to make here is: When you last walked up the stairs you were thinking about all sorts of things. Maybe you were on the phone with someone, searching for your keys in your pockets, and thinking about looking for a nice introduction to programming online … maybe you did all of this at the same time. Whatever it was, you did not think about how exactly to bend your knees and ankles while trying to maintain your balance and get up to the next step.

Programming is very much the same. As programmers, while we program, we do not think about the programming language, and how to use it. Instead we simply use it, and meanwhile think about very different things, such as the problem we are trying to solve, how we can make things easier for fellow programmers, how to best suit the needs of our users, or customers, and so on.

When you start learning to program you will first learn about the basic concepts of the programming language. And you sometimes may feel slightly overwhelmed, and wonder how programmers might be able to remember all this stuff. The trick is: they don’t, consciously. Instead they have assimilated these concepts so much that they are able to simply use them, without consciously remembering or thinking about them. Just like you use English, or your ability to walk up the stairs.

That’s why learning a programming language, just like learning any other language, or skill, is a lot about repetition: You basically brainwash yourself into being able to form meaningful “sentences” (code) without having to think about the concepts that you are using.

Over time, while you repeat basic concepts of Ruby over and over again (by way of doing exercises and writing code) you will notice that things become very natural, and this probably will happen much quicker than you think.

At first, you will not understand anything. It’ll be weird, just like with learning any human language. You will struggle with words, and not know what symbols are what, and it’ll all be very confusing. Then one day BANG your brain will snap and you will suddenly “get it.” If you keep doing the exercises and keep trying to understand them, you will get it. from the great book Learn Ruby The Hard Way by Zed Shaw.

Learning modes

People are different

Different people learn things in different ways.

Some like to listen to lectures, or read books that thoroughly explain concepts before they then start exercising, and experiment with what they just learned. Others like to get their hands dirty, and play with code until it does what they want.

Some want to fully understand what a certain line of code does, and why. Others don’t care that much about the details, and want their code to produce the right things instead. They might memorize what worked, and understand things more fully later.

Some understand concepts in logical ways, and go precisely by their definitions. Others understand things better by coming up with good analogies and metaphors. And yet others tend to simply memorize things and how they get used.

Therefore there is no one true path or one-size-fits-all approach to learning programming. Try different things, and pay attention to what works well for you, what is the most fun to you, and keeps you motivated.

If you find it hard to keep motivated working through a certain online tutorial, or if you have a hard time fully understanding what an exercise is about, then try to pick a different approach, or talk to your study group.

Consider meeting with others during the week, have some coffee and cake and hang out, read some more of this book, or do a few exercises together.

Also, consider joining local programming events, like meetups, hackdays, or a conference once in a while. That gives you a broader perspective, even if you might not be able to fully understand everything all the time. Meeting with others and hearing about their experiences can also be a good source for inspiration and motivation.

If you can’t put a lot of time into learning programming, then consider spending at least a few minutes on it every day. For example, every morning, before you leave the house, take 10 minutes to read a page in a programming book, review an exercise, or read some code. Or spend some time with it on the train on your way home from work later. This will keep your subconscious mind busy with programming concepts, and help you pick things up more easily later.

Don’t believe everything we say

While you are learning to program you’ll talk to seasoned developers, ask questions, and listen to their advice, tips, and experiences.

That’s great! We recommend you listen closely, try to understand, and ask more questions.

However…

Always try to put things into perspective. Whatever you hear, try to understand, compare with other opinions, and judge for yourself.

As in any other field, developers, as much as any other person, will always give answers based on their own perspective, based on their own experience, and based on what they think is a helpful answer to you. Now, being a great Ruby developer (“knowing your stuff”) and being a great Ruby coach (“giving the right advice”) are not the same thing.

Developers who have never coached, or are new at coaching, tend to, for example, overload you with information. They know all this stuff, and, as said before, they aren’t even fully aware of it. They just use the language, and all these features.

Now, when asked to explain things, and may suddenly remember: “Oh, right, and then there’s also this other language feature, and that one, and another one, and …!” They may be excited to explain all the things at once, without realizing that, at this particular point, you actually don’t need to know them all at once.

Also, they might present a conclusion, and omit the learning process. In programming, as much as in any other field, there’s rarely any silver bullet. There are always alternative solutions, with different advantages and downsides. Often it’s hard to fully understand them unless one tries a particular solution and sticks with it for a while.

On top of this, whatever is considered a “good” solution by the community at any point of time, is always the conclusion of a decades-long evolutionary learning process. Often it makes sense to start practicing with an older and simpler solution that worked well enough a couple of years ago, and experience some of the problems it caused, and only then try using the latest, more modern solution.

Developers often tend to be excited about their current preferences, and things they’ve learned just recently, and will happily explain at length why one solution works better for them than another. Often you can learn a lot from listening to these explanations. However, keep in mind that this doesn’t necessarily mean a tool that’s great for an experienced programmer is also a tool that’s great for learning to program.

On top of all this, there’s also the problem that the tools we use, over time, become more and more optimized for advanced users. New features are being added that make our day-to-day work easier, and over the years, up-to-date documentation and tutorials will focus on these features.

While that’s great for advanced users, it’s sometimes bad for beginners, as you now not only need to understand the basic concept, you also need to understand this additional, more abstract feature that sits on top of it.

A good coach will try and adjust to these things, but doing so also is a skill that needs to be learned. Try to give feedback, and help your coaches improve.

Of course, everything said above also applies to ourselves :)

Here are a few examples of decisions we made for our study groups. Don’t worry if you don’t understand what we’re talking about at this point. You’ll fully understand them once we get there during study group.

Formatting your code

Keeping things pretty

By “formatting code” we refer to the way code is indented, or not, where and how whitespace is being used in order to separate things visually, or not, etc.

For example, even though this code won’t mean a lot to you at this point (it will, in a few chapters), it is formatted well:

def widths(row)
  row.map do |cell|
    cell.width
  end
end

Even without understanding what these few lines of code do at all, from just looking at it one can recognize a certain structure: things are somehow nested, and stuff that sits on the same horizontal indentation relates to each other visually.

On the other hand the following code also is perfectly valid Ruby code, in the sense that Ruby will happily run it, and it does exactly the same. However, it is not formatted very well at all (in fact it’s quite a mess, isn’t it?):

  def widths (     row
)
 row.map do | cell| cell.width
end
     end

This does the same, technically: Ruby will run it. But it does not look and read the same, simply because of the way it is formatted.

Pattern recognition

When you talk to developers about your code you will probably notice very quickly that we are all obsessed about how exactly we’d like code to be formatted.

There’s a good reason for that, and you should try hard to learn how to use your editor in order to format your code properly, so over time, you can become obsessed, too :)

The reason for this obsession is pattern recognition: The ability of our brain to help us recognize things subconsciously, from just glancing over them.

Imagine you are driving a car, and there’s a kid playing with a ball on the sidewalk. Even if you only see the kid from the corner of your eye your brain will immediately process this information and even assign a meaning to it. You’ll start paying attention, and maybe lower your speed immediately.

Often when you search for something online, and look at a couple of websites, your brain will help you recognize things that you are looking for without consciously thinking about the structure of the site.

In the same way, as a programmer, when you look at code, you will immediately recognize some of its structure, and thereby understand it, without reading it thoroughly. This allows you to to grasp the overall picture of what you’re looking at, and quickly find something that you’re looking for, in order to then read this particular part of the code more carefully.

As you can imagine, in order for this kind of pattern recognition to kick in, code needs to be formatted consistently and carefully.

Another aspect of this is that looking at “badly” formatted code causes discomfort to an extent that it is described as causing physical pain. While this might seem like an exaggeration, there’s something important to it.

Because of how pattern recognition works, as a programmer, whenever there’s a small issue with the formatting of some code, you will immediately notice it, and distract yourself from other thoughts. You’ll need to re-focus on what you were trying to accomplish, and whenever you come back to the code it will distract you again.

That’s why developers often feel the urge to fix even small formatting mistakes immediately. People might outright refuse to talk about your actual code, and any questions that you have, before you’ve added this one extra space here, and indented that other single line there.

(One certain aspect of this has been even baked right into the language Ruby. For example, by definition, class names must start with an uppercase letter. On top of this, the Ruby community has agreed on conventions for how to write other names. We’ll get to this once we talk about variables and classes more.)

Reading error messages

Your new best friends

As programmers we want to build things that work. When we do exercises we want to figure out the solution to the given problem. Seeing error messages therefore has a negative connotation to it: we haven’t managed to get it right! Right?

Well, yes. But also, no. Errors can also indicate progress. Often error messages indicate that we’ve done the right first step, and now have to figure out the right next step.

Whenever you find an error message printed on your terminal, don’t fret. Instead, appreciate it. Read it carefully. Ruby is trying to give you a hand and help. Normally an error message tells you exactly what went wrong in your code, and where. Once you’ve understood what has happened look at your code and try to understand why it happened, and how you might fix it.

Often, when you fix one thing, you’ll get a different error message. That’s progress. Rinse and repeat until your code does what you want.

For a beginner, Ruby error messages can sometimes be hard to read. There are certain conventions used, e.g. for indicating there’s an instance of a certain class involved. Backtraces might be hard to read and might look frightening. But all they do is tell you the exact path of execution Ruby took until it ended up raising an error.

If you do not understand an error message and you have the opportunity to ask someone else, then do so. You’ll get better and better at reading error messages over time. And you’ll become friends with them.

Using Google

Someone else has already had that question

Whenever you have a question, and you’re not sure where to start looking for an answer, simply go ahead and ask Google. Some other person most probably has had the same question before, and often times you will find a helpful blog post, tutorial, documentation, or answer on community sites like Stack Overflow.

Finding the right terms to type into Google might take some time. Experiment with this. If one question does not yield a helpful result on the first page, try to rephrase your question. You’ll get better and better at this over time.

Always include the keyword “ruby” though, so you don’t get answers for other programming languages.

E.g. if you are wondering if there is a method that gets you all the keys from a hash, then google for “ruby hash get keys”. If you are wondering if there’s a method to align strings so they all have a certain length, then google for “ruby string align”.

Google results that link to the Ruby documentation on ruby-doc.org are often good ones to look at, but these pages also often are very long. Look at the summary of the page on Google, and the highlighted terms, then go to the page and use your browser’s search feature to find them on the page.

Also, results on Stack Overflow are often very worthwhile to read. This is a programming community site where people with all kinds of experience levels post questions, which then will be answered by others. People can rank answers, and the best ranked answer appears at the top. Often it is worth skimming through most of the answers, as sometimes the question asked is just slightly different from yours, but someone might still suggest a solution that might be similar to the one you are looking for.

Your tools

When you start learning programming in Ruby you’ll need three tools: A text editor, a terminal, and a Ruby runtime.

As a programmer you’ll spend tons of time working with your text editor and terminal (or “in” them, as we say). It makes sense for you to learn how to use these tools, and how to customize them so they fit your taste.

There are also text editors that can be integrated into a terminal window. This means you don’t have to switch between applications. There are also online services that integrate all of this as a web application, with a nice interface in your browser.

Feel free to try all these things out, and play with them as much as you like. However, for our study groups, we have found that using the simplest tools possible, at least for a while, works best: It reduces the amount of things people need to learn in the beginning, and everyone learns the same few basic things that are required to run a Ruby program in this environment.

Text Editor

For our study groups we recommend using Sublime Text as a text editor, which you can download and run on Mac OSX, Ubuntu, or Windows. This is an editor that has been specifically designed for writing code, comes with a lot of great tools, and can be easily customized.

Other text editors that might be worth looking at are Atom, Textmate 2, and, if you like to use some of the powerful oldschool tools from the early times of Unix, VIM and Emacs. These are all great editors to use.

Whatever editor you use, you want it to insert 2 spaces when you hit the “tab” key, i.e. when you want to indent your code. Make sure your editor is configured to do this.

For Sublime Text you can do the following: In the menu item “Sublime Text” go to “Preferences” and select “Settings - User”. This opens up a configuration file that you can edit just like any other file. Make sure it looks like this:

{
  "tab_size": 2,
  "translate_tabs_to_spaces": true
}

Also, we recommend enabling auto-saving your files. This will automatically save your changes when you switch to another application (like your terminal), and protect you from the mistake of forgetting to save:

{
  "tab_size": 2,
  "translate_tabs_to_spaces": true,
  "save_on_focus_lost": true
}

Whenever you open a new file, make sure to save it with a filename that ends with .rb first. This will tell the editor that you want this to be a Ruby file. Your editor will start highlighting your code as Ruby code, and enable other Ruby specific editor features. Alternatively, select “Ruby” in the extensions menu at the bottom right.

Some keyboard shortcuts that are extremely useful to know are:

Terminal

Every operating system comes with some kind of terminal application built in, and they’ll be fine to use for us.

A terminal is an application that doesn’t do much more but provide a window to run another program, called a “shell”. A shell is a text-based program, so it does not have a window, and thus needs the terminal to be run on your graphical user interface.

A shell is an interactive program that waits for you to type a command and hit enter (or “return”). It will then run the command, display any output, and then, again, sit and wait for you to type the next command.

This is how working with computers was done in early times before there was the idea of a graphical user interface with clickable icons, windows, and a mouse as an input device. Instead, everything was done by typing commands.

While this might take a little while for you to get used to, you’ll discover why many programmers feel that working with the shell helps them be so much more productive and get simple things done so much quicker than using a mouse and a graphical interface.

The default settings for most terminal applications that come built in to operating systems are quite poor, unfortunately. For example the Terminal.app on Mac OSX opens a tiny little mini window with a very small font. You want to make the window much (much!) bigger, and find the settings to pick a bigger font size. As a programmer, the terminal (along with your editor) is your new home. You want to be as comfortable reading and writing in your terminal as in any other application.

In case you are using Microsoft Windows it is highly recommended to use any kind of unix based terminal. One option is Git-Bash (https://gitforwindows.org/). However, as Ruby and Microsoft Windows are not best friends, it is even better to install the Windows Subsystem for Linux which is available here for Windows 10: https://docs.microsoft.com/en-us/windows/wsl/install-win10. With this option you can install everything you need for your Ruby development under Ubuntu and use Bash as your main shell.

All commands in the following texts are unix commands and will not work in a Microsoft Windows terminal.

Once you have started the terminal program you will see your shell’s prompt, and can start typing commands. You’ll want to learn at least the command cd which allows you to navigate to a particular directory (where you have stored your code), and the command ls which lists the contents of a directory.

Also learn how to use the command line completion using tab: For example, type cd, space, and the first two or so letters of the directory you want to navigate to, then hit tab. The shell will complete the rest of the directory name for you. If nothing happens, then there are multiple directory names starting with the same few letters. In this case hit tab twice, quickly, and your shell will display a list of choices. Type the next letter and hit tab again.

Ruby runtime

The last tool you need is a Ruby runtime. This is a program that can execute Ruby code, and it is a program that can be run in your shell (much like cd and ls).

If you have some code in a file with the name hello.rb, and you have navigated to the directory where the file is saved, then you can type the following and hit enter, in order to execute the code:

ruby hello.rb

This will tell the ruby runtime to interpret the contents of the file hello.rb as Ruby code, and execute it.

One can also use this program to do other things. You probably won’t need these a lot, but we think it’s good to know. You can try these by typing these commands in your terminal.

E.g. you can print out the version of the program:

ruby --version

Or execute Ruby code without storing it to a file:

ruby -e 'puts 123'

Programming workflow

In order to do programming excercises on your computer, play around with things you learned, and write actual, useful programs you want to learn the following workflow:

In order to switch back and forth between apps quickly you can use the keyboard shortcut cmd-tab on Mac OSX, and alt-tab on Ubuntu and Windows.

In your shell you can use the cursor up key to go through your last used commands: you don’t have to type ruby hello.rb again. Just hit cursor up and then enter to run it again.

Interactive Ruby

One other tool that is worth mentioning, and that comes with your Ruby runtime, is irb. You can start it by typing irb in your shell and hitting enter.

Its name is short for “Interactive Ruby Shell”, and yes, it is another kind of shell: Just like the shell running in your terminal irb is also a program that interactively waits for you to type something, and hit enter. However, since this is a Ruby shell, it will expect that you type Ruby code instead of system commands.

IRB is pretty handy for quickly trying something out, and it is a great tool for exploring the language Ruby, and things that come built in.

For example:

$ irb
> puts "Hello world!"
Hello world!
=> nil
>

The first line starts the IRB program. Notice how the “prompt” indicator changes. The prompt will look a little different depending on your system and shell configuration, but often $ is used to indicate that this is a system shell prompt, while > is used by IRB to indicate that this is an interactive Ruby shell.

The second line is a piece of Ruby code. When you type this line and hit enter then Ruby will execute the code, and print out the text “Hello world!”.

It will then also print out the return value for this statement, which in this case is nil. This is something that you can simply ignore for the time being.

On the last line you see IRB again waiting for input with a prompt.

You can exit the IRB session, and get back to your system shell, by typing exit and hitting enter. Or you can also just hit ctrl-d, which does the same thing.

Our Roadmap

Ok, let’s get started.

Here’s a rough overview of the road that lies in front of us, and topics that we’ll cover.

This curriculumn is built on top of two main ideas:

Of course you don’t have to follow exactly this path. For example, if you’re curious, after we’ve introduced the most basic built-in types of things in Ruby, numbers and Strings (text), you might find there’s another chapter about more such types. Feel free to skip ahead, and read it. Just be aware that you might find this chapter assume a couple more things.

So, here’s our roadmap:

1. Object Oriented Programming

We’ll look at the main idea (concept, paradigm) behind programming in Ruby from a little bit of a philosophical perspective. We do this to set a little bit of a context for the terms object, class, and method which will be used quite frequently from then on.

2. Variables

In order to do things with objects, and form readable sentences (code) we need to be able to assign names to them.

This chapter explains variables in Ruby.

3. Built-In Data Types

Ruby comes with lots of batteries included. Things that are built-in, and ready for you to be used when you open an empty Ruby file, or IRB.

We’ll look the two most basic, and most widely used ones:

Numbers, and Strings (text). These will be good enough for us to introduce other concepts without spending too much time on talking about all the other things that Ruby has built-in (we’ll look at the most important ones later).

We’ll quickly mention 3 primitive things that are widely used in Ruby: true, false, and nil, so you’ve already heard of them when we come across them later.

Then we discuss Arrays and Hashes, which are data structures. I.e. these are things that you can use to store other things. They’re pretty powerful, and widely used.

Symbols are quite an odd beast, and you normally wouldn’t even need to know them in order to write your own, working code. However, they’re very widely used and many (many!) examples out there use them. So we introduce them briefly, too.

4. Objects, Classes, Methods

This chapter discusses how objects and classes relate to each other, how methods can be called on objects, and explores a number of different methods. It also has a quick look to see what’s up with that magic, so-called top-level object in Ruby.

5. Writing Methods

While variables give names to things, methods give names to behaviour. Methods are like the swiss-army knife of programming. We’ll have a look at the anatomy of a method, and learn how we can define our own ones.

6. Writing Classes

With this knowledge at hand we can now go ahead and define our first class (kind of thing) ourselves: We’ll define the class Person, create some “people” (objects), and let them interact. We’ll learn how to make our objects “know” things, and how to give them “behaviour”.

7. Blocks

Blocks are a super powerful feature in Ruby. We love them, and use them everywhere. Many built-in methods use them, too. So it’s good to introduce them now.

Blocks are like methods that don’t have a name, and they are passed when calling actual methods. We’ll discuss why this is cool, and how it works.

8. Conditionals, Truthiness, and Nothing

Sometimes you want to run some part of your code only if a certain condition applies (e.g. you only want to allow users to login if the supplied password is correct).

Conditionals allow you to do that. Ruby comes with some pretty cool features included, and we’ll quickly look at them.

9. Operators

There are lots of different operators built into Ruby, and at this point you’ve already used a number of them (such as the arithmetical operator +, and the assignment operator =).

We’ll look at a few more, and also reveal that operators, in fact, are … methods in disguise!

Bonus and advanced topics

This concludes the core of our “Ruby For Beginners” curriculum. With this knowledge you’ll have all the tools you need in order to play with things, read (most of) other people’s code, and write your own useful things.

There are a couple bonus chapters that you might want to skim through. Some of these are still waiting to find their place somewhere else in the book. Some will probably be marked as optional.

Also there are some extra chapters about advanced topics, some of which are relevant to the more advanced exercises, and for the next curriculum about building your own web applications.

Object-oriented programming

Classes and objects

Ruby is, like many other popular languages, an object-oriented programming language. Other object-oriented languages that you might have heard of are C++, Java, Python, PHP, and Javascript. At some point in the 1990s this paradigm started to become more and more popular and nowadays it is the most prevalent one.

One reason for this is that object-oriented programming very much fits the way we perceive and think about the world, at least in the occidental culture. Our way of thinking was, historically, very much influenced by Plato, and philosophers who followed him:

We somehow tend to think about the world as if there are abstract “ideas” (or concepts) and concrete “things”, which are entities of the ideas, or implementations of the concepts. So, “ideas” are like blueprints for “things”.

For example there’s the idea of a human being, and then there are actual human beings: you, and me. Our idea of a human being includes the ability to, for example, remember our own name, and tell it to others when asked. We know that we can ask people for their name, and they’ll know it.

Now, object-oriented programming languages allow you to describe things exactly this way: In object-oriented programming languages “ideas” are called classes. And actual “things” are called objects.

As a programmer you would define classes, like a class “User” and a class “Tweet”, and then create actual instances of these classes: an actual concrete user with a name, email address, a password and actual tweets. You would also define that users have the ability to remember their own name, and the ability to tell it to others when asked.

Classes are like ideas, objects are concrete things, manifestations of their ideas.

Every object-oriented programming language comes with some “ideas”, that is, classes, already baked in, and so does Ruby. For example Ruby has classes for numbers, strings (text), and other useful things. You therefore can, without any further effort, do number calculations, or text transformations.

In your first excercises you will do just that. Later on you will learn to define your own “ideas” as classes, and then use them by the way of creating actual instances or objects, from these classes, and then make them interact with each other and do interesting stuff.

By the way, here is a quote from a book titled The Early History Of Smalltalk from 1993. It has been written by Alan C. Kay, one of the designers of Smalltalk, which was created in the 1970s, and can be considered the first fully object oriented programming language. We think it’s pretty interesting to read.

“[Smalltalk’s] way of making objects is quite Platonic in that some of them act as […] Ideas from which manifestations can be created. That the Ideas are themselves manifestations (of the Idea-Idea) and that the Idea-Idea is a-kind-of Manifestation-Idea — which is a-kind-of itself, so that the system is completely self-describing — would have been appreciated by Plato as an extremely practical joke.” — Alan C. Kay

Anyhow, you can take away from all of this that those universes that we create when we write programs will be populated by objects (“things”), and their characteristics are defined by classes (“types of things”, or “ideas”).

This will start to make a lot more sense to you once you write your own classes.

There is, today, some debate about the paradigm of object-oriented programming, and whether we should move on to another one, called “functional programming”. You might hear about this if you talk to developers. Some functional languages are Haskell, Go, and Clojure, and they have recently started gaining some traction. Don’t let yourself be distracted by this too much, unless you really want to. Ruby is a very good language to start learning programming for lots of reasons.

Variables

Naming things

In order to refer to the “things” (objects) that our program deals with we want to assign names to them.

Every practical programming language has a feature to do this, called variables. This is basically the same concept that you might know from math, although in Ruby there are different kinds of variables (you will get to know another one in a couple chapters).

We’ll discuss this concept quickly because you already need to know it in the next chapter, and the respective exercises.

If some of this seems rather abstract to you, don’t fret. It will become very practical, and you won’t even think a lot about it any more, as soon as you actually work with variables while learning other things.

Alright. Let’s jump right in:

In Ruby you can assign a name to something (an object) by using the so called assignment operator =. Like so:

number = 1

This will assign the name number to the “thing” (object) that is the number 1. From now on we can refer to this object by using the name number. For example the following code would output the number 1:

A name on the left side of the assignment operator = is assigned to the object on the right side.

number = 1
puts number

One important thing to note here is that a variable is not a “thing” an object by itself. Instead it’s just a name for an actual object. In our example the number 1 is an object, while number is a name for it because we’ve assigned it.

A variable itself is not a “thing”. It’s just a name for a thing (an object).

You can think of it like a post-it note with the name number written on it, and stuck on the actual thing, which is an object (in this case, a number).

Imagine you were in the middle of learning some Spanish, and sticked post-its onto things in your apartment: the name nevara onto the refrigerator, cama onto your bed, and puerta del baño onto the bathroom door.

Now, whenever you use one of these terms, as in abrir la nevera (open the refrigerator) in order to learn the language and rehearse vocabulary, you’ll obviously refer to the object, and open its actual, physical door.

That’s pretty much how variable assignment works in Ruby. There’s a “thing”, the object on the right side of the assignment operator =, and the name on the left side is being assigned to it.

Whenever we use a variable name that has been defined before we refer to the actual object that it has been assigned to. E.g. on the second line of the code example above number refers to the actual object, the number 1 that it has been assigned to on the first line. Therefore puts number outputs the number.

You can pick whatever variable names you want, they’re just names, like post-it notes stuck onto actual objects.

Since names are just names, the following examples would do exactly the same:

a = 1
puts a

large_number = 1
puts large_number

apples = 1
puts apples

However, also note that it makes sense to try and pick names that reveal your intention. The chapter Using the right words at the end of this book will talk more about this. Feel free to jump ahead if you are curious. In short, the first example using a as a name would be frowned upon because it’s wasting the opportunity to use a meaningful name. The second and third examples are just trying to be stupid, and pick names that don’t match the “thing” (the object, number 1) at all.

There are a two more things about variable assignments that we’d like to point out before we move on.

Reusing variable names

It is also important to keep in mind that a name is unique, in the sense that the same name can only be assigned to one value (object) at a time.

In other words, if you assign different values to the same variable, then assignments that happen later will simply overwrite previous ones. Like so:

number = 4
number = number * 3
puts number + 2

This, again, would output 14.

Variable names can be re-used, and re-assigned.

The first line assigns the name number to the number 4. The second line re-assigns it to another object.

Getting back to our post-its metaphor … this would stick a post-it with the name number on one thing, and then later take it off of it, and stick it on something else.

Let’s look at it under the microscope:

Of course, you would probably never actually write this exact code in practice since you can simply do all this in just one line instead: puts 4 * 3 + 2.

However, sometimes you’ll find or write code that assigns an initial value to a variable, and then keeps working on it for a few more lines. This sometimes is useful to break up long lines, and make code more readable.

Using variable names can be useful to break up long lines and make code more expressive and readable.

Also, Ruby has different kinds of variables.

The kind of variable that we’ve introduced so far is called a local variable, and it’s the one used most often. You will learn about another type of variables later when we talk about classes and objects.

On formatting: Note that there are spaces around the assignment operator `=` as well as the arithmetical operators `+` and `*`.

Things on the right go first

One last thing that is worth mentioning about variables:

Just as in traffic (well, at least in most parts of the world), things on the right side go first :)

For a variable assignment, in order to assign the thing on the right side to the name on the left side, Ruby first needs to figure out the thing on the right. As you will see later the same is true for many other expressions in Ruby.

In our example above it will first create the object that is the number 1, and then assign it to the name number. The following example makes that more clear:

number = 2 + 3 * 4
puts number

When Ruby looks at the first line number = 2 + 3 * 4 it notices that this is using the assignment operator =. Therefor, before it can assign the name number to the “thing” (object) on the right … it first needs to know what that thing is.

So, before she does anything else, Ruby will first look at the expression 2 + 3 * 4, which will result in the number (object) 14. She will then assign the name number to this object (i.e. evaluate the assignment operator =).

You can imagine that in this moment, when Ruby starts evaluating the assignment = the code temporarily looks like this: number = 14 (because the calculation has returned the number 14).

Does this make sense?

Again, on the second line Ruby will then pass the thing with the name number (which is 14) to puts, which will output it to the screen.

Ruby evaluates the expression on the right first.

Built-In Data Types

As mentioned before, Ruby comes with lots of things already baked in, and provides you with tons of tools to use and hit the road running.

We’ll look at some of the most common data types in Ruby. Data types are types of “things” that are mainly used to represent data, such as numbers, text, and other values.

This is basically the “stuff” that you, as a Ruby programmers will work with, when we work with actual data, that is interesting to you, or your users in one way or the other.

We will discusss the following data types:

These “kinds of things” (objects) cover like 98% of all built-in data types that you’ll be using on a day to day basis, i.e. these are being used all over the place. There are more data types, but those are rather exotic, and used much less often.

Numbers and Strings (which is just a strange name for “texts”) are some of the most basic “things” that you deal with in Ruby on a regular basis. The are also just enough lego bricks for us to dive into more interesting topics, such as how objects, classes, and methods relate to each other, and how you can create your own ones.

Before we do so we will also briefly mention the “things” true, false, and nil, just because these are things that we’ll come across along the way anyway.

Symbols also are very commonly used, but quite an odd concept. You normally wouldn’t need to understand Symbols in order to write your own code. We’ll still cover them briefly, and use them once in a while, just in case you find them elsewhere.

Arrays and Hashes are “things” (objects) that are used to store other things, and they’re super useful, and widely used.

Numbers

Numbers are simply numbers.

You can create one by writing it: 123 is Ruby code and it represents the number one-hundred-twenty-three.

Negative numbers are created by prepending a minus -: This is the number minus-ninety-nine: -99.

And of course there are decimal numbers, too. Again, you create one by writing it: 12.34.

You can also use an underscore to separate thousands places: E.g. 1_234.56 is the number one-thousand-two-hundred-thirty-four-point-five-six. However, this is optional. This is the exact same number in Ruby: 1234.56.

A number is defined by a series of digits, using a dot as a decimal mark, and optinally an underscore as a thousands separator.

Note that different countries use different punctuation for decimal and thousands separators. Ruby is using the same notation used in the USA, which happens to be the exact opposite of what’s used in Germany.

Kinds of numbers

Under the hood, for reasons that are mostly technical, there are actually different kinds of numbers:

For example there are integer numbers (those without a fraction, i.e. a dot and decimal places), and depending on their size there are two kinds of them. For floating point numbers there are even more. Unless you are super curious, you can perfectly ignore all of that for now, and just think of numbers as numbers.

However, when you do calculations with numbers, keep in mind that integer numbers (“integers”) and decimal point numbers (floating point numbers, aka “floats”) are different.

If you do a calculation that uses integer number you’ll always get an integer back:

$ irb
> 1 + 2
=> 3

However, if any of the numbers involved is a float, then you’ll get a float back:

$ irb
> 1.0 + 2
=> 3.0
> 1 + 2.0
=> 3.0

Mathematical operations result in a floating point number except if all numbers used are integer numbers.

This is, for example, important when you do a division (/ means “divide by”):

$ irb
> 3 / 2
=> 1

As you can see any decimal places will be just cut off, since the result needs to be an integer number.

However, if you use floats:

$ irb
> 3.0 / 2
=> 1.5
> 3 / 2.0
=> 1.5

Use floating point (decimal) numbers when doing devisions.

Exercises: How about doing some of the exercises on numbers next?

Strings

A String, in programming languages, is text.

More precisely a String is an object that represents a specific text. E.g. your name, represented in Ruby, is one String. The title of this text is another String, and so is this paragraph, and this full text in its entirety.

In web applications Strings are everywhere. In fact they’re used by far more often than numbers. That probably is because most applications that we deal with on a daily basis are dealing with text messages (Email, Facebook, Twitter, …) or descriptions of things (Amazon, Ebay, …).

Did you ever use a web application that is a complicated calculator app, and mostly deals with numbers? There you go :)

In Ruby there are a couple of flexible ways to create Strings, but the most simple and by far most common way is to simply enclose some characters in quotes:

"This is one String!"
'And this is another one.'

Strings can be defined by enclosing any text with single or double quotes.

Both of these are good to use. Technically they are almost the same, except for one important feature called “String interpolation”, which we’ll explain later.

Things you can do with Strings

Here are a few things you can do with Strings.

You can glue them together by using +. We also call this concatenation.

$ irb
> "snow" + "ball"
=> "snowball"

> "hi" + "hi" + "hi"
=> "hihihi"

The last operation can also be done by using *, like so:

$ irb
> "hi" * 3
=> "hihihi"

I.e. multiplying a String by a number in Ruby means repeating the String as many times.

The following examples are worth noting, too:

$ irb
> "1" + "1" + "1"
=> "111"

> "1" * 3
=> "111"

This demonstrates that Ruby behaves the same for Strings that contain nothing but numbers.

Some other things that you can do with Strings that you can try yourself in irb:

> "hello".upcase
=> "HELLO"

> "hello".capitalize
=> "Hello"

> "hello".length
=> 5

> "hello".reverse
=> "olleh"

These last few examples are examples of “calling methods on objects that are Strings”. Methods are “behaviour” that objects are capable of. We’ll explain methods, and how they relate to objects more in just a few chapters.

Exercises: How about doing some of the exercises on Strings next?

History

The reason why pieces of text, in the context of programming languages, usually are not referred to as “text”, but instead with the slightly odd term “String” is a historical, and technical one:

In early programming languages Strings were implemented as lists of characters, and programmers had to deal with them as such: imagine pellets lined up on a String. One had to take care of nasty things like manually managing the length of the character list, and inserting a couple characters in the middle of such a list was quite a complicated operation.

When languages evolved over time they made things like this easier for developers, and added built-in abstractions for the concept of “Strings”. So the name sticked, and resembles the way programmers had thought about text before: as characters lined up on Strings.

Luckily, nowadays, in Ruby and any other modern language, you can just think about Strings as text.

True, False, and Nil

There are three more “things” that we’d like to mention quickly, just because you’ll see quite frequently: These are true, false, and nil.

The first two, true and false are just what you think they are:

The object true represents “truth”, while false represents the opposite of it.

In other words, in Ruby, true and false are also “things”, just like numbers, Strings, Arrays, and Hashes. You can assign them to variables, pass them around, and otherwise use them. They’re fairly simple things, but they’re also very useful.

The third object nil represents “nothing”. Yeah, that’s right. In Ruby there’s a “thing” that represents the absence of things. This might be a interesting topic to discuss on a philosophical level, but for now we’ll just see how it works in Ruby.

The object nil represents “nothing”.

You’ll see later that every operation (“method”) in Ruby always returns exactly one thing (i.e. one object), and that’s why there needs to be a “thing” that represents “nothing”.

This will start to feel pretty natural to you pretty soon.

Symbols

Symbols are like strings, except they are code.

Symbols are a rather strange concept to be honest, and we only introduce them because symbols are used so often and widely that you’ll very likely find them used in code elsewhere. For your first steps in learning programming we would not necessarily need them.

A symbol is written like this: :something

I.e. there is a word that is preceded by a colon. This means that normally symbols do not contain spaces. Instead, if we have symbols that consist of multiple words we would concatenate them with underscores, like so: :another_funny_symbol

A symbol is created by adding a colon in front of a word.

So when to use strings, and when to use symbols?

There’s actually no perfectly clear line or simple definition.

Symbols are unique identifiers that are considered code, not data.

If you find all of this confusing, don’t worry, many people do. You’ll understand symbols better once you get to use some of them in your code. For now you can think of them as a special, limited variation of Strings (text).

Symbols are a special, limited variation of Strings.

The technical difference

Skip the following unless you’re really curious about the underlying technical difference between Strings and Symbols.

Try this in IRB:

$ irb
> "a string".object_id
=> 70358630335100
> "a string".object_id
=> 70358640625960
> "a string".object_id
=> 70358644379620

As you can see, even though the 3 Strings created are exactly the same, every new String created has a different object_id: They’re actually different objects, even though they contain the same text.

With Symbols however:

$ irb
> :a_symbol.object_id
=> 1086748
> :a_symbol.object_id
=> 1086748
> :a_symbol.object_id
=> 1086748

We now get the same object_id for each of the Symbols, meaning they’re referring to the exact same object.

The object_id is a unique id that Ruby uses internally in order to keep track of all the objects that are flying around in the universe that makes up your program. E.g. Ruby needs to know which objects are still being useful, and which ones can be cleaned up and thrown away. The object_id is a way to identify each and any object by a unique id.

By true, false, and nil (as well as all numbers) also behave this way: Whenever you use these in your code you’ll get the same object. Try it in IRB and check their object_id.

Let’s move on though.

Arrays

Arrays are like bags that contain things

While numbers, Strings, true, false, and nil all represent simple, primitive things, Arrays are more interesting, and very useful.

Arrays are things that store (or “hold”) other things. You can think of an Array as a collection or list of things. Or better yet, as a bag that you can throw things in: The bag itself is a thing (an object), too.

An Array is an object that stores other objects.

An Array is created by separating values by commas, and enclosing this list with square brackets, like so:

[1, 2, 3]

This is a simple Array that holds three numbers.

An Array is created by listing objects, separated by commas, and enclosed by square brackets.

Arrays can contain all kinds of things:

["A string", 1, true, :symbol, 2]

This creates an Array with 5 elements, i.e. a bag that contains 5 things: a string, a number, true, a symbol, and another number.

Arrays can contain all kinds of objects.

Note that in Ruby Arrays always keep their order: Unlike a real bag, where, when you throw in a bunch of apples, they might come out in a different order, an Array always keeps its objects in the same defined order (unless you do something to change the order).

Also note that in Ruby you can store any kind of object in an Array. For example, you can also store Arrays in an Array: that’s a 2-dimensional Array, like a table that has many rows, and each row has many cells (“things”).

Arrays have a defined order, and can store all kinds of objects.

Retrieving an element from an Array

Arrays can be used in a lot of different, and useful ways, but the most basic one is to retrieve a certain element by the way of referring to its position: Please get me the element at position 1!

In Ruby, you can do this with square brackets like so:

words = ["one", "two", "three"]
puts words[1]

Do you recognize how we use a variable to assign a name to our Array here?

words[1] means: from the Array words get the element at position 1. puts will then print this value out to the screen. (By the wayputs stands for “(out-) put string”.)

So, as you can see square brackets [] mean different things when used in different contexts. The same is true for other punctuation, too.

In our case here the square brackets on the first line are used to create an Array object with the given elements. On the second line the square brackets are now appended to a variable name. This means we want look up an element from the Array that (at this moment) is called words (i.e. assigned to the variable words).

Punctuation (such as square brackets) has different meanings in different contexts.

Arrays are zero based

What do you think our example code will print out to the terminal? Funnily, it’s two, and not one. Huh?

The reason for this is: The first position in an Array is 0, not 1. So the position 1 refers to the second element, not the first one.

In programming books and the Ruby documentation you’ll often find the word “index” to be used instead of “position” in this context.

Arrays start with the index 0, not 1.

Appending an element to an Array

In order to add an element to the end of an existing Array you can use the operator <<, called “shovel operator”, like so:

words = ["one", "two", "three"]
words << "four"
puts words[3]

This prints out four: The string "four" has been “shoveled” into, that means, appended to the Array. And since it now sits at position 3 we can access it using words[3].

Setting an element to a position

You can also set an element to a specific index, like so:

words = ["one", "two", "three"]
words[3] = "four"
puts words[3]

This also prints out four.

You could also overwrite existing elements the same way. For example this would set the word "uno" to the position 0 (i.e. overwrite "one"):

words = ["one", "two", "three"]
words[0] = "uno"
puts words[0]

So, this would now output uno.

On formatting: Note that there are no spaces inside the square brackets, and there’s one space after each comma.

Missing elements

What if we try to retrieve an element that does not exist, for example the element at the fourth, or fifth position (index)?

Right, we get back nil, meaning “nothing”:

> words = ["one", "two", "three"]
> words[3]
=> nil
> words[4]
=> nil

You’ll learn later that every operation (“method”) in Ruby always returns exactly one thing (i.e. one object), and that’s why there needs to be a “thing” that represents “nothing”.

This will start to feel pretty natural to you pretty soon.

Nested Arrays

As said before, Arrays can contain all sorts of things. So, they can also contain more Arrays.

This is quite a common thing to use when you need to represent some data that has the characteristics of a table, like an spreadsheet.

The outer Array represents the table, and each inner Array represents one row. Each value then represents a cell. For example:

[
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
  [0]
]

This is a nested Array that represents the structure of number keys on a phone.

Things you can do with Arrays

Here are a few things you can do with Arrays.

Look at them, and play with them in irb. Don’t necessarily try to memorize all of them … you can always look things up in the documentation when you actually need these. It might be useful if you’ve seen some of them before though.

Funnily, you can “calculate” with Arrays. Remember set theory from your math classes? This is pretty similar.

You can add Arrays:

$ irb
> [1, 2] + [3, 4]
=> [1, 2, 3, 4]

Subtract them from each other:

$ irb
> [:one, :two, :three, :four] - [:three, :four]
=> [:one, :two]

Multiply with a number:

$ irb
> ["Ruby", "Monstas"] * 3
=> ["Ruby", "Monstas", "Ruby", "Monstas", "Ruby", "Monstas"]

And find the intersection:

$ irb
> [1, 2, 3] & [2, 3, 4]
=> [2, 3]

first and last are alternative ways to retrieve the first and last element:

$ irb
> [1, 2, 3].first
1
> [1, 2, 3].last
3

Some other things that you can do with Arrays that you can try yourself in irb:

> [1, 2, 3].length
=> 3

> [3, 1, 2].sort
=> [1, 2, 3]

> [1, nil, 2, 3, nil].compact
=> [1, 2, 3]

> [1, 2, 3].index(3)
=> 2

> [1, 2, 3, 4].rotate(2)
=> [3, 4, 1, 2]

> [[1, 2, 3], [4, 5, 6], [7, 8, 9]].transpose
=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

In these examples compact removes all nil values from the Array. transpose works with a nested Array and “flips” the table, i.e. turns columns into rows, and rows into columns.

Exercises: Now would be a good time to do some of the exercises on Arrays.

Hashes

Dictionaries: look up one thing by another

Hashes are another very useful, and widely used kind of thing that can be used to store other objects.

Unlike arrays which are mere lists, Hashes are like dictionaries:

You can use them to look up one thing by another thing. We say: we look up a value from a Hash using a key. Or one could say: Please get me the value that is associated with this key.

Imagine a real dictionary that translates from English to German. When you look up the English word “hello” then you’ll find the German “Hallo”. When you look up “one” then you’ll find “eins”, and so on. The authors of this dictionary have assigned a German word (a value) to an English word (the key).

Hashes work pretty much like this.

A Hash assigns values to keys, so that values can be looked up by their key.

We also refer to a value that is assigned to a key as key/value pairs. A Hash can have as many key/value pairs as you like.

Creating a Hash

In Ruby you can create a Hash by assigning a key to a value with =>, separate these key/value pairs with commas, and enclose the whole thing with curly braces.

This is how it looks:

{ "one" => "eins", "two" => "zwei", "three" => "drei" }

This defines a Hash that contains 3 key/value pairs, meaning that we can look up three values (the strings "eins", "zwei", and "drei") using three different keys (the strings "one", "two", and "three").

By the way, the Ruby community has come up with the name hash rocket for the bit of syntax => which separates a key from a value, … we think that is pretty cool to know :)

A Hash is created by listing key/value pairs, separated by hash rockets, and enclosed by curly braces.

Looking up a value

Now, how do you actually look up the value that is associated with the key "one"?

Just like with Arrays you use sqare brackets, but instead of passing a number indicating the position you now pass the key. Like so:

dictionary = { "one" => "eins", "two" => "zwei", "three" => "drei" }
puts dictionary["one"]

Do you reckognize how we, on the second line, use a variable name to refer to the Hash defined on the first line?

In this example, dictionary is a Hash defined on the first line. ["one"] looks up the value associated to the key "one", which is "eins". This value will be passed to puts which outputs it to the screen.

Setting a key to a value

Also, just like with Arrays, there’s a way to set key/value pairs on an existing Hash:

dictionary = { "one" => "eins", "two" => "zwei", "three" => "drei" }
dictionary["zero"] = "null"
puts dictionary["zero"]

This prints out null.

You could also overwrite existing key/values the same way. For example this would set the word "uno" to the key "one" (i.e. overwrite the existing pair with the value "eins"):

dictionary = { "one" => "eins", "two" => "zwei", "three" => "drei" }
dictionary["one"] = "uno"
puts dictionary["one"]

So, this would now output uno.

Any kind of objects

You can use any kind of object as keys, and you can store any kind of object as values.

For example, these are all valid Hashes, too:

{ 1 => "eins", 2 => "zwei", 3 => "drei" }
{ :one => "eins", :two => "zwei", :three => "drei" }
{ "weights" => ["pound", "kilogram"], "lengths" => ["meter", "mile"] }
{ :de => { :one => "eins", :two => "zwei", :three => "drei" } }

The first example uses numbers as keys, while the second one uses Symbols, which is quite a common thing to do in Ruby.

In the third example you can see that one can use Arrays as values in Hashes. So if you’d look up the key "weights" you’d now get an Array back.

Not quite sure where you’d use a Hash like the third line in real code, but the last line is actually pretty darn close to what Rails uses for translating strings to different languages:

It is also an example of a nested Hash. There’s another Hash associated (stored) as a value for the key :de (representing the language German). And this other Hash now has three key/value pairs. So a Rails programmer could look up how to translate “one” to German, and get “eins” back.

Hashes can use any kind of objects as keys and values.

On formatting: Note that there’s one space inside the curly braces on both sides, around the => Hash rocket, and after each comma. But there are, again, no spaces inside that square brackets [] that define the Arrays on the third line.

Missing values

What happens if we try to look up a key that does not exist?

Again, just as with Arrays, we’ll get back nil, meaning “nothing”:

$ irb
> dictionary = { "one" => "eins", "two" => "zwei", "three" => "drei" }
> dictionary["four"]
=> nil

Does this make sense?

Things you can do with Hashes

The main purpose of a Hash is being able to lookup a value by a key.

However, here are a few other things you can do with Hashes, too.

Again, look at them, and play with them in irb. Don’t necessarily put too much effort into memorizing all of them …

You can merge two Hashes:

$ irb
> { "one" => "eins" }.merge({ "two" => "zwei" })
=> { "one" => "eins", "two" => "zwei" }

fetch does just the same as the square bracket lookup [] discussed before, but it will raise an error if the key is not defined:

$ irb
> dictionary = { "one" => "eins" }
> dictionary.fetch("one")
=> "eins"
> dictionary.fetch("two")
KeyError: key not found: "two"

keys returns an Array with all the keys that a Hash knows:

$ irb
> dictionary = { "one" => "eins", "two" => "zwei" }
> dictionary.keys
=> ["one", "two"]

length and size both tell how many key/value pairs the Hash has:

$ irb
> dictionary = { "one" => "eins", "two" => "zwei" }
> dictionary.length
=> 2
> dictionary.size
=> 2

Exercises: Now would be a good time to do some of the exercises on Hashes.

Hash syntax confusion

You can skip the following and jump right to the chapter Variables, or you can keep reading if you’re curious.

We’ve found it’s important for us to explain the following somewhere in our book, because many online resources use another, alternative syntax for defining Hashes.

The term syntax, in programming, refers to ways to use punctuation in order to (amongst other things) create objects.

E.g. the fact that we can use square brackets [] and commas , in order to define Arrays, and curly braces {} and hash rockets => in order to define Hashes, is part of Ruby’s syntax.

Today, there are two different syntaxes for defining Hashes with curly braces, and they have the potential to confuse newcomers a lot.

There’s an old-style one, and a new, modern one.

We use the old syntax, and ignore the new one, for now.

Here’s why:

Up to a certain version of Ruby the syntax that uses hash rockets was the only syntax to create Hashes, and it works the same for all Hashes no matter what kinds of objects you use as keys.

Then, a few years back, a new syntax was introduced. Many Ruby programmers love to use it, because it takes a little less space, and it also looks a lot like JSON, which is a data format that is widely used in web applications.

The new Hash syntax looks like this:

{ one: "eins", two: "zwei", three: "drei" }

Using this syntax we tell Ruby that we want the keys to be symbols.

Hmmmm? We just learned that Symbols are defined by prepending a word with a colon like :one, right?

Well, yes, correct, but that’s just how it works: If you define a Hash using this syntax, then you’ll get a Hash that has Symbols as keys.

We found the new syntax pretty confusing for beginners: It is slightly less explicit and obvious, and you have to learn another piece of information. That’s why we simply ignore it in our study groups while we learn what Hashes are and how you can use them.

Once you feel comfortable using Hashes, you can make your own decision, and start using the modern syntax if you like it better.

In the meanwhile, whenever you see a Hash using the new syntax somewhere else, you now know what it means, and where to look it up. Simply remember that these two Hashes are exactly the same:

{ :one => "eins", :two => "zwei", :three => "drei" }
{ one: "eins", two: "zwei", three: "drei" }

Objects, Classes, Methods

We’ve talked about objects quite a bit now, merely using that term as a synomym for “things”. You’ve learned to do stuff with simple objects such as numbers and Strings, and the data structures Arrays and Hashes. You’ve also learned what a method is, how to define and use them, and how to pass things to them, and get others back.

We’re also prepared well enough to have a closer look at objects, classes (types of things) and methods, and how they relate to each other.

As a sidenote, you may have heard the following. Rubyist love saying it:

In Ruby everything is an object.

Actually, this is a little bit of a lie. Even though it’s being said so often, it isn’t completely true: not everything is an object. There are a few things that are not objects.

But almost everything is, and that’s good enough to know for now.

In Ruby almost everything is an object :)

(Just in case you want to out-smart people at your local Ruby user group though, remember to ask “Really? Is an if statement an object or a method? How about self?”)

Objects have classes

As mentioned before when you run a Ruby program a little universe (space, scope) is being created, and populated with concrete objects (things) as defined by your program. These things interact, and do useful stuff, using certain methods that you call.

Also, each concrete thing (object) is an instance of a general idea or type, and these ideas are called classes.

You can see that objects have classes when you open IRB in your terminal and ask an object for its class:

$ irb
> "this is a string".class
=> String

Objects are concrete instances (manifestations) of classes.

That means that the following sentence is true: In Ruby, "a string" is a String.

Hmmmm, yeah, we kinda knew that already, right. However, you can also ask the same question in Ruby:

$ irb
> "this is a string".is_a?(String)
=> true

So, the actual string knows that it is a String, which in Ruby means that it is an instance of the class String. You can do this for any object. E.g. 1.is_a?(Numeric), also returns true. This is pretty cool.

We also say that an object is an instance of its class. Let’s see what that means.

Classes create objects

Objects are instances of classes.

Classes are kind of blue prints for the concrete objects. Every time a concrete object (such as the String "one string", the String "another string", the String "yet another string", and so on …) is created:

We say that the class is instantiated: an object is created from it.

What does that mean?

Classes have a bunch of characteristics, but most importantly, every class defines a number of methods, which are specific to this type of thing (e.g. a String).

Now, every time a new object is created (“instantiated”) from this class this new object get (“inherits”) all of these methods.

Objects inherit methods from their classes.

That’s right. Objects have their own methods attached to them.

We’ll explain more about methods that belong to objects in the next chapter. And you’ll see how you can define methods to your own classes, so they’re then available on your objects when we start defining our first, own class.

But for now we can already point out that all concrete Strings that you use in your code will all have the same methods defined (attached to them) … because they’re all created (instantiated) from the the same class.

You can have a look at all the methods that the class String defines on Ruby’s documentation page for this class.

Let’s see how we can use these methods.

Objects have methods

Methods are an object’s behaviour

Objects have methods, allowing us to do interesting stuff with them. An object’s methods are things that the object can do.

Think about a person, like, a friend of yours. You can ask this person for their name (call a method), and they’ll tell you (return it to you). Their name is a piece of knowledge that this person has, and the ability to tell it to you (respond to your question) is a piece of behaviour (a method) they have.

We could also ask them to make, and bring a cup of tea for us. Or we could ask them to remember a phone number, or email password.

As Rubyists we actually say that we “talk to objects”, or “send messages” to them: We do so by using (calling) methods that they respond to.

So, what can an object do?

That depends on their class (type). Numbers can do things that are useful for numbers, obviously. You can do math, and ask them about their mathematical properties (e.g. “Are you an odd number?”). Strings (text) come with way more methods, and they’re often related to text transformations.

Methods add behaviour that is useful to have for a particular type of object.

We’ve already used some methods in the previous chapters: E.g. "hello".upcase calls the method upcase on the String "hello".

Also, class and is_a? are methods defined on all objects in Ruby, and therefore also defined on the String "a string": "a string".is_a?(String) answers with true.

Some methods, such as class, is_a?, are defined on all objects.

Let’s move on to see how we can use (call) these methods though.

Calling methods

In Ruby, methods that belong to (are defined on) objects can be used (called) by adding a dot, and then the method name, like so:

object.method

That’s like saying Hey object, please do [method].

Let’s try that out in IRB.

For example, the class String defines methods like upcase (Give me an uppercase version of yours), downcase (What’s the downcased version of yours), and length (Hey string, what’s your length?).

Here’s how we can call them:

$ irb
> name = "Ruby Monstas"
> name.upcase
=> "RUBY MONSTAS"
> name.downcase
=> "ruby monstas"
> name.length
=> 12

And so on.

In other words, you first address, or mention, the object that you want to talk to, and then, with the dot ., “send a message” to the object by specifying the method name. We also say: “you call the method upcase on the string”.

A dot is used to call a method on an object.

Imagine the string name is a person you can talk to. You can ask questions by “sending a message” to them, and they’ll respond by sending (returning) something back. The term “sending messages” actually is used instead of “calling a method” in programming, and specifically in Ruby.

So, you can ask the string to hand you an “upcased” version of itself. And it responds by doing so. Or you can ask it for its length, and it responds by returning the number 12 to you.

You can have a look at all the methods that the class String defines (responds to) on Ruby’s documentation page for this class.

Most methods in Ruby work this way: You ask an object to return a bit of information about itself (such as a String’s length), or a modified (transformed) version of itself (such as a downcased version of the String).

Most methods are questions, and return a relevant value.

Others modify the object itself, and some have so called side-effects, and modify something else, e.g. puts and p both output something to the screen. Other methods might save files, send emails, or store things to a database.

Some methods are commands, and change the object, or the system (e.g. by saving a file).

Passing arguments

Extra information needed

Sometimes an object needs a little bit of extra information in order to do what you ask for.

For example the class String defines the method delete which returns another String with some of the characters deleted. In order to do so, of course, it needs to know which characters we’d like to remove.

We can pass things by appending parentheses () to the method call (the name). We can then include the extra bit of information needed (in our case another string) inside the parentheses like so:

$ irb
> name = "Ruby Monstas"
> name.delete("by Mo")
=> "Runstas"

Hm. Not sure what “Runstas” means. Ideas? Let us know.

Anyhow, another example for a method that needs an argument is the method prepend on Strings. This method returns a new String with the given String prepended:

> name = "Ruby Monstas"
> name.prepend("Oh, hello, ")
=> "Oh, hello, Ruby Monstas"

These extra bits of information are called arguments. We’ll discuss them more once we get to define our own methods.

Not all methods need these extra bits of information (arguments) in order to do their job. E.g. the method length on Strings knows the length of their String just so (because it knows its String). Sometimes they need one or more arguments though.

So how do you know?

You might remember, over time, for some important methods, but most of us also check the documentation quite frequently, too. Some times it’s just fine to try it out quickly, and only check the documentation if it does not work as expected.

Listing methods

As said above, if you are curious what methods are defined on a certain object, then you can check the Ruby documentation for this class. (Usually the right page conveniently shows up at the top when you google for “ruby” and the class name.)

However, you can also quickly pop into IRB and ask the object for its methods. That’s right, methods is a method defined on all objects (just like class, and is_a?).

When you call it then it will return (respond with) an Array with all the method names that the object has.

It makes sense to sort the Array, so it is easier to read. Like so:

$ irb
> "Ruby Monstas".methods.sort
=> [:*, :+, :<, :>, :[], :class, :downcase, :delete, :include?, :is_a?, :length, :prepend, :start_with?]

Yep, the method names come as Symbols, because they’re considered code.

If you do this yourself, you’ll see that the String actually has a lot more methods. Many of these actually aren’t used very often, but some are quite useful. We have stripped the Array down a little, because we want to talk about some of these methods more.

Chaining method calls

Btw the code above also demonstrates that methods can be “chained”: When we call a method on an object it will return another object to us. We can then immediately call another method on that new object, and so on.

In our example above the method methods returns a Array of names. And Arrays respond to (have) the method sort, so we can call this method immediately, by using another dot.

We could chain some of the method calls from our String example above like so:

$ irb
> name = "Ruby Monstas"
> name.prepend("Oh, hello, ").upcase
=> "OH, HELLO, RUBY MONSTAS"

So we have a String "Ruby Monstas", prepend another String to it, which returns a new String "Oh, hello, Ruby Monstas", on which we immediately call the method upcase.

Pretty handy.

As you can see Ruby will first evaluate the bit name.prepend("Oh, hello, "). It needs to do that so it knows the object (the new String) that is going to be returned from this, so it can then call the method upcase on it.

Does this make sense?

Predicate methods

If you check the list of methods on our String above you see that in Ruby we can have methods that end with a question mark ?. What’s up with that?

By convention, in Ruby, these methods return either true or false. For example, we can ask a number if it is even or odd:

$ irb
> 5.odd?
=> true

> 5.even?
=> false

This makes them read like a question, which is pretty cool.

Or you can ask the number if it’s between two other numbers. Obviously this methods needs us to pass those two other numbers. So now we also have an example of a method that takes two arguments:

> 5.between?(1, 10)
=> true

> 5.between?(11, 20)
=> false

These methods are called predicate methods in Ruby. Not quite sure why, maybe because of the historical math context of programming.

Predicate methods that end with a question mark ? return either true or false.

Strings also define some predicate methods:

> name = "Ruby Monstas"
> name.start_with?("R")
=> true
> name.start_with?("a")
=> false

Do you also think it’s kinda odd that name.start_with?("a") reads almost like English, but not quite? Maybe the method could have been named starts_with? instead, right? That’s true. This is because Matz, the creator of Ruby, is not a native English speaker, and some names sound right in Japanese when translated literally.

Also:

> name = "Ruby Monstas"
> name.include?("by")
=> true

> name.include?("r")
=> false

When we check what methods there are defined on a number, we find some with the same name, but also different ones:

$ irb
> 1.methods.sort
=> [:*, :+, :-, :/, :between?, :even?, :odd?, :zero?]

Let’s try zero?:

> 0.zero?
=> true

> 1.zero?
=> false

Arrays have the methods include?, and Hashes respond to key?:

> [1, 2].include?(1)
=> true

> [1, 2].include?(3)
=> false

> { "eins" => "one" }.key?("eins")
=> true

> { "eins" => "one" }.key?("zwei")
=> false

Oh by the way, if you’re curious why operators like *, +, - and so on are also listed here, check the chapter that explains that operators are methods, too.

Bang Methods

All of the examples that we’ve discussed before have one thing in common:

They are questions, and do not modify the object they are called on.

For example:

name = "Ruby Monstas"
puts name.downcase
puts name

This will output:

ruby monstas
Ruby Monstas

As you can see the method downcase has returned a new String, which is the lowercase version of the String that the method is being called on. When we output the original String on the next line, we can then see that it’s still the same: The method downcase does not modify the String.

However, there also are variants of some of these methods, which end in an exclamation mark !. These methods are called “bang methods”, and they usually modify the object that they’re being called on.

Bang methods end with an exlamation mark, and often modify the object they are called on.

For example, next to the method downcase Strings also have a method downcase!.

Let’s try that:

name = "Ruby Monstas"
puts name.downcase!
puts name

This will output:

ruby monstas
ruby monstas

As you can see calling the method downcase! on the second line has modified the String itself (the object that name refers to), and also returned the new downcased version.

Nowadays programmers have learned that using these methods has a number of disadvantages, and usually should be avoided, unless there are very good reasons for it (usually, there are none).

Use bang methods with caution.

We mostly mention these methods because you might see them used elsewhere.

Writing Methods

A named block of code that takes input and returns output

Everything in programming is about data, and doing interesting things with it. If you think about Twitter, it essentially takes 140 characters of text (which is data) from their users and displays it to others.

You have already learned about the most important primitive (simple) types of data in Ruby: numbers, strings, true, false and nil. And we’ve had a look at the two most common data structures, Arrays and Hashes.

All of this is about the data part. Methods on the other hand are about the doing interesting things part.

In this chapter we’ll have a closer look at the anatomy of a method, and you’ll learn how to implement, and use, your own methods.

Methods define behaviour

Methods are all about defining behaviour, so that they can be applied to different bits of data in different contexts easily.

For example, there are methods that do things like: transforming a String, sorting a list, reading a CSV or Excel file, sending an email, signing in to Facebook, sending a Tweet.

Another way of putting this is: Methods are a way of assigning a name to a certain piece of code. Just like a variable allows to “look up” or refer to the object that the name was assigned to … methods allow to execute their code.

Variables name things, methods name behaviour (code).

Methods make code re-usable, by the way of packaging (“encapsulating”) code and sticking a name on it.

As you have seen Ruby comes with lots of methods predefined - written by experienced programmers. So, unless you’re studying computer science and you’re faced with the exercise of implementing your own, complicated sorting algorithms for data collections, … you’ll just use the method sort that already comes defined for Arrays in Ruby out of the box.

Ok, let’s see what makes up a method, and how we can define our own ones.

What makes a method

There are four things that constitute a method:

Not all methods actually need input (so they don’t take any), and not always do we care about the output that a method returns.

Imagine a vending machine where you can chip in some money, press some buttons, and the machine will spin a few gears and wheels, and spit out the chocolate bar you were after.

If the vending machine was a method, then your money, as well as the buttons you press are the input. The way the machine internally spins certain mechanics is the block of code, the stuff it does internally. And the product that it dispenses is the return value.

Although this would be an odd thing to mention to a non-programmer, we could say that a vending machine is a way of “transforming” money and data into chocolate.

Methods are a lot like that.

Methods have a name, take some input, do something with it, and return a result.

Programmers usually don’t use the term “input” in this context. Instead we say that a method accepts a number of arguments (pieces of input). And instead of “output” we use the term return value: the thing that we get back from the method.

A method’s input is referred to as “arguments”, while its output is called a “return value”.

This will become more clear in the following chapters. Let’s define a method next.

Defining a method

So far you have seen methods that “belong” to objects, or, in other words, are defined on objects, and can be called on objects. E.g. you have seen the method downcase which is defined on every string.

However, Ruby also knows methods that are not defined on any of these objects. They’re sort of “stand alone” methods.

For example, you can try this in irb:

$ irb
> is_a?(Object)
true

We’ll use this type of methods in this chapter because we want to focus on the characteristics of methods. If you’re curious what’s up with them have a look at the bonus chapter about the top-level object. Later when you learn how to define your own classes we also look at defining methods for these.

Ok, let’s get started.

Suppose we need to define a simple method that takes a number, adds the number 2 to it, and returns the result. Here’s how we can do that:

def add_two(number)
  number + 2
end

This defines a method. It does not use it, yet: You only build and place that vending machine, so it can be used (by yourself, or others) later.

Let’s walk through this method definition step by step:

Ruby will start reading the code at the top, and find the keyword def. This tells Ruby that we’re about to define a new method.

Methods need a name, so Ruby looks for it next, and finds the word add_two.

Ruby then checks if we define anything to “input” to the method (remember, this is optional). She finds the parentheses, and knows that we’re about to define a list of things that can be given to the method. This list is called an argument list.

An argument list defines names for objects passed to the method, enclosed by parentheses right after the method name.

In our case the argument list has one single argument number, which means our method can accept one single thing (object).

The next line is the block of code that our method has (“encapsulates”). This is also referred to as the method body. In our case that’s just one single line because the operation that our method encapsulates is very simple. Other methods (think of sort, defined on Arrays) would require more code, and are longer.

Inside the method body the arguments are known as local variables: You can see how the code in our method body uses the variable name number.

Finally the keyword end tells Ruby that we’re done with the method body, and the method definition.

All we’ve done so far is defining the method, we haven’t used it for anything, yet. We’ll do that in the next chapter.

On formatting: Note that the keywords def and end sit on the same level, while the method body is indented by two spaces. Also, there are no space before or inside the argument list, i.e. the () parentheses.

Using (calling) a method

Once defined we can use our method.

As programmers we usually say that we “call” a method. This means we ask Ruby to execute the code that the method body has, with some given arguments (input), if any.

Here’s how that looks:

def add_two(number)
  number + 2
end

puts add_two(3)

Let’s inspect what’s happening here under the microscope. If you don’t understand each part of this just yet, don’t worry, we’ll get back to all of this.

On the first three lines Ruby defines the method add_two as discussed above.

So Ruby now deviates from the normal flow, which just goes from top to bottom in our file. Instead she now jumps into the method body.

In this moment she now assigns the number 3 to a local variable number before she starts executing the method body.

That’s right. This is how method arguments work:

When a method is called and objects are passed as arguments, then Ruby implicitely defines local variables with the argument names. She assigns the passed objects to the variable names that are in the argument list. These local variables are then available in the method body.

In our case we have just one argument number. So we get one local variable number with the object 3 assigned (because that’s the object passed when we called the method).

You can imagine the method body now reads like this:

number = 3
number + 2

Ok, so we’re inside the method body now:

So Ruby now jumps back out of the method. The expression add_two(3) has just returned the object 5. Imagine the last line now reads like this instead:

puts 5

And that will now print the number 5 to the screen.

Let’s have a closer look at that thing with the return value (“output”), as we just rushed over that a little.

Return values

In Ruby, a method always return exactly one single thing (an object).

The returned object can be anything, but a method can only return one thing, and it also always returns something.

Every method always returns exactly one object.

The object returned could be the object nil, meaning “nothing”, but it still is an object. Also, in order to return a bunch of things at once we could return an Array that holds the things that we are interested in, but the Array itself is just one object.

Also note that in Ruby we do not have to use the statement return, as in other languages. In fact, most Ruby code does not use the keyword return at all.

This is extremely convenient, but it is also something we need to learn:

If we don’t do anything else, then a method will return the value that was returned from the last evaluated statement. Most often, this is the last line in the method body.

This is important to understand. Please read that sentence again:

If we don’t do anything else, then a method will return the return value of the last evaluated statement.

In our example method …

def add_two(number)
  number + 2
end

p add_two(3)

… the last evaluated statement is the expression number + 2. Since in our example number is assigned 3 this expression returns the number 5, and that is why the value returned by our method also is 5.

If, in certain cases, we do want to “return” from the method early, then we can still do this using the return statement. For now, you don’t need to worry about this case.

So, let’s move on :)

Scopes

Spheres of visibility, like rooms in a house

When we talked about variables we mentioned that the most common type of variables is the “local variable”, without explaining any further why they are local. Local to what? Where? We’re finally ready to explain that more.

Since we have now talked about methods, we can also discuss another important concept: scopes.

Wikipedia says: “In programming, the scope of a name is the part of a program where the name is valid: where the name can be used to refer to something else.” (slightly modified to match our own terminology)

Names are known (or defined) in a certain scope, and unknown (or undefined) outside of this scope.

You can think about a scope as of a sphere, a bubble, or a room (with no windows, and doors closed): Certain names, like variable names, are “known” and “visible” inside of the room. Other names, known and visible in another room are not known in this room, but only in the other room.

Every time there is a method call, and the flow of execution enters the method’s body, it enters a new scope, or “room”. Things that are “local” to this method’s scope (i.e. things that are “inside” of the room), are only visible in this scope. Outside of it, they are unknown.

Undefined local variable or method

This is also a good opportunity to talk about an error message that you might see most often. E.g. you’ll see it every time when you made a typo and misspelled a variable or method name.

Consider this code:

def add_two(number)
  number + 2
end

puts add_two(3)
puts number

The line puts add_two(2) will output 5, but the line puts number will then raise an error.

This is because the variable number that is assigned the number 3 when we call the method is a local variable. It is local to the method’s scope. It is created when the flow of execution enters the method.

Outside of this scope, when the flow of execution has returned from the method the method’s scope has been destroyed, and all local variables are gone. The local variable number is therefore not known, and Ruby raises an error saying undefined local variable or method 'number'.

If you think about this error message for little bit, does it make sense to you?

We have silently skipped over the fact that, in Ruby, both local variable names and method names, are written the same way: they’re just plain words. For example, here:

number = 2
puts number

number is a local variable, and it is used in the line puts number.

However, here:

def number
  2
end
puts number

number is the name of a method. And it can be used (called) in the exact same way: puts number

This is because Ruby, when it executes a program, evaluates one statement after another. And when it encounters a plain word like number then it will first check if, within the current scope, it knows a local variable with the same name. If so, it will use the value that is associated to this variable. If there’s no local variable with this name, then it will look for a method. If there’s also no method with this name it will then raise the error message undefined local variable or method 'number'.

So the error message is pretty precise, but also sounds kind of convoluted. What it basically tries to say is:

You’ve used the word “number” here, and i don’t know it (in this scope). Did you mean to use a local variable? Or a method?

Does that make sense?

Back to the topic of local scopes. Let’s look at another example:

number = 1

def add_to(number)
  number + 2
end

puts add_to(3)

What do you think the output will be? Will it be 3, or 5? Something else?

If you run the code you will see that it’s 5.

The reason for that is that we do assign the number 1 in the outer scope to a variable number, but this variable is then never used: the only other line in the outer scope is the last line puts add_to(3), and this line does not use the variable number.

Instead, when the control flow enters the method add_to Ruby will create a new local scope, and it will define a new local variable number which is assigned the number 3 that was passed to the method. This new variable number is local to the method’s scope, and therefore this is a different variable than the one on the very first line, in the outer scope.

We found the following a good metaphor for scopes:

When Ruby enters a method, it’s like she enters a shiny new room in a house. With her, she brings the objects that are passed as arguments to the method call. In the example above she brings an object that is the number 3.

Now, as soon as Ruby enters the method, she sticks post-it notes on the objects, according to the argument list from the method definition. In our example that is the name number. So from now on, in this room, there’s a known local variable that has a value assigned: The object (number) 3 with the post-it note number on it.

In our example, the outer scope and the scope of the method add_two, are two different rooms, and there are two different post-it notes stuck on two different numbers, which just happen to have the same name on them.

Combining Methods

We’ve discussed how to define a method, and how to call (use) it.

What if one method is not enough? What if methods need to do more complicated things?

Easy. We can call methods from other methods.

For example, we could re-write (“re-implement”) our method add_two using another method add_one, and simply call it twice:

def add_one(number)
  number + 1
end

def add_two(number)
  number = add_one(number)
  add_one(number)
end

puts add_two(3)

This would output 5 just like our previous examples. Do you understand how it works?

Of course, in Ruby we could also just solve this whole thing with simply using the + operator.

However, for the sake of the example, let’s have a look how we could add a method that does the exact same thing as the + operator, too:

def sum(number, other)
  number + other
end

We can now use that method like so:

puts sum(3, 2)

Which, again, would output 5.

Note that in this example our method sum now takes two arguments, and so, when we call (use) it, we also need to pass two numbers (i.e. add them inside the parentheses on the last line).

Now, with this method in place we could change (“refactor”) our previous methods to use it:

def sum(number, other)
  number + other
end

def add_one(number)
  sum(number, 1)
end

def add_two(number)
  sum(number, 2)
end

puts add_one(3)
puts add_two(3)

Again, these examples are not super realistic, as we’d probably just use the + operator in the first place, in practice.

However, we think this nicely demostrates how you can use one method from another … and how different methods require different numbers of arguments.

We’ll look at a more realistic example in the next chapter.

Printing things

Many of the exercises that you do while doing your first steps with Ruby basics include running a short Ruby program that outputs something to the terminal.

So far, we have mostly used the method puts to do that.

However, there’s another method that is even more useful when we are trying to figure out what a program is doing, why it is doing it, and what a certain error might be about.

This method is the method p. In order to understand p better, we want to look at another method first, which is the method inspect.

The method inspect is available on any object in Ruby. It returns a string that is a representation of the object itself: a representation that is as close as possible to the code that you use to create the object. So inspect is useful to inspect objects, duh :)

This becomes more clear when you try it in IRB:

$ irb
> puts 5.inspect
5

> puts "A string".inspect
"A string"

> puts [1, 2, 3].inspect
[1, 2, 3]

As you can see the string returned from inspect is exactly the same as the Ruby code that we used to create the object. That is really convenient.

However, typing puts something.inspect is quite a bit of work to do. That’s 12 characters to type next to the object itself!

Therefore Ruby has a method to make our lifes easier, and does this work for us. That’s the method p.

This method is implemented like so:

def p(object)
  puts object.inspect
end

Whenever you are trying to figure out what a certain line of code does, what’s assigned to a variable, or what a method call returns, we recommend to use p because it tells you exactly what the thing that you are looking at is.

puts on the other hand tries to be smart.

For example when you pass an array to puts then it will output each of the objects on a separate line:

$ irb
> something = [1, 2, 3]
> puts something
1
2
3

Also, the output for numbers and strings that contain numbers is exactly the same when you use puts:

$ irb
> puts 123
123
> puts "123"
123

From the output of puts it often is not clear whether the object that you are looking it is an array that contains numbers, or an array that contains strings, or just a long string that contains linebreaks.

In short, puts is useful when you are writing a program that is supposed to actually output something to the screen. Like, this could be a command line tool that you write in order to make your own life easier at your job, and that is helpful at automating some repetitive work. Or it is useful in Ruby programming exercises :)

On the other hand p is useful when you are trying to understand what your code does, e.g. when you are trying to figure out a certain error.

Writing classes

Finally, our first own class

Since in Ruby “everything is an object”, we have worked with objects quite a bit already.

We’ve created numbers, Strings, and seen objects like true, false, and nil. We have also looked at their class names by calling, e.g. "a string".class, and we have explored some other methods that these objects have. We have also talked about how you can define your own methods, and how you can call them, passing arguments as required.

That means we now have all the tools that we need to finally learn how to define and use your own classes. And this is where things suddenly become even more fun!

You can think of objects as having two things: They know stuff, and they can do something with stuff (their own stuff, as well as the stuff that gets passed to them).

Imagine you were an object that is an instance of the class Person. Well, in a certain way, you actually are :)

Since you are a Person, you are able to remember your own name. And you are able to do something with it: When asked, you can tell your name to others, that is, you can return it to the “caller”, to whoever asked.

We’ll define this exact class in just a few chapters. However, before we do that, we’ll first look at how to define the method add_two to a class Calculator … just because we can, and because you’re already familiar with these methods.

Defining classes

Let’s start by creating a class Calculator, and adding some methods to it, step by step.

In Ruby, you define a class like this:

class Calculator
end

That’s all. It’s not a very useful class, since it’s completely empty, but it’s a class.

A class is defined using the keyword class, a name, and the keyword end.

Also, you see that the class has the name Calculator, which starts with an uppercase letter. In Ruby, this is required, and you’d get an error if you tried to define a class calculator.

Also, for class names that consist of several words the Ruby community has the convention to separate these words by uppercase letters, as in RubyStudyGroup. This is called CamelCase, because of the humps. Whereas for variable and method names we use underscores, and keep everything lowercase: local_variable and method_name. This is called snake_case.

Class names must start with an uppercase letter, and should use CamelCase. Variable and methods names should use snake_case.

Ok, back to our class Calculator.

Since we’ve defined a full, valid class, we can now already use it to create a new, concrete calculator instance, an object from it.

You can think about the instance as the concrete calculator object that you can hold in your hands, and use to do actual calculations. The class on the other hand is more like the idea or concept of a calculator, like the idea of it that you have when you order a calculator online.

Ok, here’s how to do create a new, concrete instance from our class:

Calculator.new

That’s right. new is a method, and it is defined on the class itself (which, as you might remember, is also an object, so it can have methods). This method creates a new instance of the class, and returns it.

The method new is defined on every class, and returns a new instance of the class.

Cool. Let’s have a look at that object:

p Calculator.new

The output will seem a little bit weird, and technical at first:

#<Calculator:0x007fb2fbe50910>

The format #<...> tells you that this object is not a simple thing like a number, string, or array. Instead, it just tells you the name of the class, Calculator, and the internal id that Ruby has assigned to this object.

Every object has its own, unique, internal object id, and when I ran this code on my computer, Ruby assigned the id 0x007fb2fbe50910. If you run it, you’ll get a different one. In practice, most of the time, you can simply ignore this id.

Also, we can check that our new calculator instance indeed is an instance of the class Calculator:

$ irb
> class Calculator
> end
> calculator = Calculator.new
> calculator.class
=> Calculator
> calculator.is_a?(Calculator)
=> true

Defining instance methods

If you have read closely methods can be defined and called on objects (i.e. instances), e.g. 1.odd?. And you have just seen that they can also be defined on classes, e.g. Calculator.new.

Fairly straightforward, methods that are available on classes are called class methods, and methods that are available on instances are called instance methods.

In this chapter we want to add the “stand alone” methods that we’ve learned to port (move) in the previous chapters Writing Methods to our class Calculator so that they’ll end up as instance methods.

Here’s how we can do that.

class Calculator
  def sum(number, other)
    number + other
  end
end

That’s right. You simply move the method into the class body, so that it’s enclosed by it.

Instance methods are defined inside the class body.

Also note that the method definition is indented by one level, that is, 2 spaces. This signals that the method sum belongs to the class Calculator. Everything between the line class Calculator and the final line end is called the “class body”, and just like method bodies we indent them by one more level.

On formatting: the keywords class and end sit on the same level. The class body is indented by one level.

Cool.

So, how can we use the new method? That is, how can we call the method sum on a calculator?

Before you read more, think about this a little. In theory you have all the bits and pieces to answer this question:

We can instantiate (“order”) a new instance from our Calculator class, and call the method sum on it like so:

calculator = Calculator.new
puts calculator.sum(2, 3)

This will output 5. Success :)

A calculator that cannot do anything but additions is pretty useless. Let’s spice our class up by adding more operations, i.e. methods. Also, let’s rename sum to plus so it matches the operator:

class Calculator
  def plus(number, other)
    number + other
  end

  def minus(number, other)
    number - other
  end

  def multiply(number, other)
    number * other
  end

  def divide(number, other)
    number / other
  end
end

Now our calculator already is slightly more useful: We can do the most basic math operations with it.

calculator = Calculator.new
puts calculator.plus(2, 3)
puts calculator.minus(2, 3)
puts calculator.multiply(2, 3)
puts calculator.divide(2, 3)

This will output:

5
-1
6
0

Whoops!

This looks all good except for the last line, right. Remember why that is? Right, dividing one integer number by another returns, again, an integer number. And these aren’t quite great for calculating divisions.

One thing we could do about this is require the users of our calculator to pass (provide) the appropriate types of numbers themselves. So it would be their own responsibility if something goes wrong with the division.

However, we could also think that a calculator should be smart enough to notice this. So we could improve our calculator to always change the type of the numbers passed to floating point numbers as part of the method divide. In other words, the method divide would take the numbers, makes sure at least one of them is a Float (floating point number), and only then do the calculation.

The method used to convert an integer to a float is to_f. When called on a float it will just return the float:

$ irb
> 1.to_f
1.0
> 1.0.to_f
1.0

Alright, lets use that knowledge to improve our divide method. It will be sufficient to call the method to_f on one of the numbers, because that will make sure we get a Float back:

class Calculator
  # ...

  def divide(number, other)
    number.to_f / other
  end
end

With that in place our calculator always returns a Float from the method divide:

calculator = Calculator.new
puts calculator.plus(2, 3)
puts calculator.minus(2, 3)
puts calculator.multiply(2, 3)
puts calculator.divide(2, 3)

This will output:

5
-1
6
0.666666666666

Perfect.

Let’s move on, and define a class Person, which should be even more fun.

Initializing objects

In the moment of birth

Let’s start over, and define a new class.

Remember how we said that objects can be thought of as two things: They know stuff, and they can do things.

Let’s define a class Person. People obviously also know things, and can do things.

Here’s how to define a shiny, new, empty class Person:

class Person
end

Again, that’s not a very useful class, but we can instantiate it, and create an actual, concrete person instance (object) from it:

p Person.new

Now, before we add any behaviour (methods) to our class, we want to be able to give it some initial data: In our case, we want the person to know its own name.

We can do this like so:

class Person
  def initialize(name)
  end
end

You see that we add a method called initialize to the class, and this method accepts a single argument, which is called name. At the moment, this method is still empty. We’ll add some code to it in a bit.

The important bit to learn for you is: the method initialize is a special method with a special meaning in Ruby:

Whenever you call the method new on a class, as in Person.new, the class will create a new instance of itself. It will then, internally, call the method initialize on the new object. Doing so it will simply pass all the arguments that you passed to new on to the method initialize.

So we can now create a new person instance by calling …

Person.new("Ada")

… and the string "Ada" will be passed on to our initialize method, and end up being assigned to the local variable name.

The special method initialize is called under the hood when the object has been created by the class method new.

Obviously, our initialize method does not do anything with the String passed, yet. That’s right. We’ll get to that in the next chapter.

To recap, when you call new on the class Person, and pass the string "Ada" then the method new will create a new instance of the class, and call initialize on it, passing the same argument list, which in our case is the single string "Ada".

When we create a new instance of a class by the way of calling the method new on that class, we also say that we “instantiate” that object: By calling Person.new we instantiate a new person object.

Instance variables

An object’s own knowledge

Now that you understand how the string that we pass to the method new ends up being passed to the new object’s initialize method, we can start improving initialize, so it does something with the string, and actually initializes our new object:

class Person
  def initialize(name)
    @name = name
  end
end

This introduces another new concept: @name is a new type of variable, called an “instance variable”.

The body of the initialize method now does nothing else but assign the value of the local variable name to an instance variable @name.

You remember how we said that each method has its own local scope, which is created when the method is called, and populated with local variables from the arguments list. You have also learned that this scope is erased, and thrown away when Ruby exits the method body and returns from the method. And that local variables that are visible in one method are not visible in other methods: that’s why they are called local.

Now, the thing is: Every object also has its own scope.

An object’s scope is populated with instance variables, in the moment we assign something to them. And they are visible everywhere in the object, that is, in every method that the object has.

Instance variables live in, and are visible everywhere in the object’s scope.

You can think of the object’s scope as your own knowledge, or memories.

For example, you know your name, your email address, and your email password. You keep this knowledge around, and you can use it when you do things (such as responding to another person). Likewise, an object keeps its instance variables around, as long as the object exists.

Ok, let’s see how that works in practise.

If you create, and output an instance of our class Person, you’ll see that Ruby now prints out the instance variable, too:

person = Person.new("Ada")
p person

The first line creates a new instance of the class Person, passing the string "Ada", and assign this new object to the variable person. The second line will then print it out:

#<Person:0x007fd8947aa868 @name="Ada">

As you can see this includes the instance variable @name with the value "Ada": This specific, concrete instance of the class Person knows their name.

You can think of this as you, as a programmer, creating this new person, and in the moment of its creation, its birth, you also give it a name. Which kind of how it works with real people, too, isn’t it?

Hmm, well … Yeah, sort of. Anyhow, let’s move on.

Attribute readers

Asking for information

Remember how we initially said that people have the ability to remember their name, and tell it, when asked?

We’ve already implemented the first part of this. Our person instance now knows her name “Ada”.

Let’s look at the second part. You also remember that methods are either questions or commands. We want to add a method that implements answering the question “What’s your name?”.

And it is as simple as this:

class Person
  def initialize(name)
    @name = name
  end

  def name
    @name
  end
end

Before we discuss what this does, let’s look at how we can use our new method. We can now call the method on the person object, like this:

person = Person.new("Ada")
puts person.name

So this prints the name Ada, and that’s what we want: we can create a new person object, passing a name to it. Once that person has been created we are able to ask for its name, and we’ll get the name back.

How does this work, exactly, under the microscope?

Let’s walk through it, step by step:

Methods that do nothing else but return a value assigned to an instance variable with the same name are very common.

In fact they are so common that there’s a word for them: they are called “attribute readers”. By “attribute” the Ruby community means an instance variable, so an attribute reader is a method that reads an instance variable.

An attribute reader returns the value of an instance variable.

Another way of looking at this is that an attribute reader is a method that “exposes” an instance variable. It makes it accessible for others. I.e. it allows you to ask for the value of an instance variable with the same name, and does nothing but return its value. Once defined others can ask this object for knowledge that otherwise would be private, and unaccessible.

In our case the attribute reader name exposes the instance variable @name, so others can ask for it.

An attribute reader exposes an instance variable.

We don’t know why the community has chosen to use the term “attribute” here: It would be much less confusing to use the term “instance variable reader” instead. Maybe the simple reason is that programmers don’t like to type more than necessary, and this saves 8 characters. Who knows :)

Attribute writers

Setting information

Imagine in our application a person not only needs a name, but also a password. However, let’s also imagine that, at the time of the creation of a new person instance, this password is not yet known. (Who would give a toddler an email password anyway?)

Instead we want to be able to tell the person object about its email password later.

We can do this like so:

class Person
  def initialize(name)
    @name = name
  end

  def name
    @name
  end

  def password=(password)
    @password = password
  end
end

As you can see, the method password= does nothing else but take a single argument (called password) and assign the value of this local variable to the instance variable @password.

This method’s structure looks exactly the same as the method initialize, doesn’t it? Execpt that initialize is called whenever you call new on the class. Our new method password= needs to be called on the object itself, once it has been created.

Again, because this kind of method is used so often, there’s another name for it: it’s an attribute writer. (And again, we think it should have been called an “instance variable writer” instead.)

Now, we can use the attribute writer like so:

person = Person.new("Ada")
person.password=("super secret")
p person

If you execute this, then it will print out:

#<Person:0x007fb61c1edcf8 @name="Ada", @password="super secret">

So, yeah, we can see that, after calling person.password=("super secret") the object now has an instance variable defined, i.e., the person now knows their password, too.

An attribute writer allows setting an instance variable.

That method call looks a little odd though, doesn’t it?

Remember what we’ve said above about the syntax sugar that Ruby adds for the assignment operator =?

Exactly the same works for attribute writers, that is, methods that end with an equals sign =.

That’s right. So we can also write this instead:

person = Person.new("Ada")
person.password = "super secret"

And this reads just so much better, doesn’t it?

Just remember that, under the hood, when running your code, Ruby translates the line person.password = "something" to person.password=("something"), and this simply calls the method password=, passing the value on the right hand side as an argument: it’s just another method :)

We think this is pretty cool.

State and behaviour

Data and methods

Lets have another look our class definition for Person:

class Person
  def initialize(name)
    @name = name
  end

  def name
    @name
  end

  def password=(password)
    @password = password
  end
end

Do you notice something?

Our class demonstrates an important thing about objects:

There’s a way to ask a person for their name, but no way to set a new name. On the other hand there’s a way to set a new password to the person, but no way to ask for it.

If you think about it, that makes sense, doesn’t it?

If you join our Ruby beginners study group for the first time, and we ask you for your name, you’ll happily tell it. But if we ask for your Gmail password, you will probably just laugh at us, or stare at us, or show some other error message. ;) In any case, you won’t tell us your email password, because that’s private information.

The same is also true for objects.

Every object has its own object scope that might hold a bunch of instance variables. These are private to the object. Our person object knows their password, once it has been given to them. But from then on, they won’t tell anyone the password, because there’s no method for that. On the other hand, there’s a method name, which is an attribute reader, so we can ask our person object for their name. But there’s no way for others to give a new name to the person, because there’s no method for that, no attribute writer name=.

This concept is called encapsulation, and it is one of the main motivations behind the whole paradigm of object-oriented programing:

We can say that an object encapsulates state (data, knowledge), which is private to the object, and exposes behaviour by the way of having publicly accessible methods.

Objects have state (instance variables) and behaviour (methods).

So, we have now created our first little class, and it’s one that you could actually see in real applications.

Interacting Objects

We’re now able to create our own objects. However, they don’t do a whole lot, yet, right? Why not create two people, and let them greet each other.

Let’s see.

Here’s what we’d like to achieve:

class Person
  def initialize(name)
    @name = name
  end

  def name
    @name
  end
end

person = Person.new("Anja")
friend = Person.new("Carla")

person.greet(friend)

We’d like this to print out the following for starters:

Hi Carla!

If we run the code above we’ll get an error message that tells us what to do next:

NoMethodError: undefined method `greet' for #<Person:0x007fbb5e9c88c8 @name="Anja">

Right, we need to define a method greet. Let’s do that:

class Person
  # methods from above ...

  def greet
  end
end

If we run this code, we’ll now get a new error message. Great, that’s progress:

ArgumentError: wrong number of arguments (1 for 0)

Right, how would one person greet another without knowing who that other person is? So we need to make our method accept an argument:

class Person
  # methods from above ...

  def greet(other)
  end
end

If we run this we won’t see an error message any more. Yay! However, it also does not print anything so far - our method does not do anything, yet.

Alright, let’s add some actual behaviour, and print out “Hi!” for starters.

class Person
  # methods from above ...

  def greet(other)
    puts "Hi!"
  end
end

What happens when you run that? It works, right. This should output Hi! to the screen.

However, how can Anja greet Carla, specifically? How can any person greet any other person? Well, the method knows the person to greet (she has been passed as an argument to the method) so she can ask her for her name:

class Person
  # methods from above ...

  def greet(other)
    puts "Hi " + other.name + "!"
  end
end

Does this make sense?

Let’s have another look at the full code:

class Person
  def initialize(name)
    @name = name
  end

  def name
    @name
  end

  def greet(other)
    puts "Hi " + other.name + "!"
  end
end

person = Person.new("Anja")
friend = Person.new("Carla")

person.greet(friend)

So we instantiate two Person objects, and assign them two variables person and friend. Then we call the method greet on the first one (Anja), and pass the second one (friend, which is Carla) as an argument.

Now Ruby jumps into the method body of the method greet, and assigns the local variable name other to the Person instance passed (i.e. Carla).

It then asks the Person instance other for their name (which will return the String "Carla", and concatenates it to (glues it together with) two other strings "Hi " and "!". So this results in a new String Hi Carla! which it then passes to puts.

Ok, let’s spice that up a little, and let Anja add her own name to this String, too:

class Person
  # methods from above ...

  def greet(other)
    puts "Hi " + other.name + "! My name is " + name + "."
  end
end

Nice. This now outputs:

Hi Carla! My name is Anja.

Remember how you could call the method add_one from another method add_two before? The same works here, too: We can call the person’s own method name by just using it, since this method is defined on the same class, and thus every instance of Person. We’ll look at this a little more in the next chapter.

For now let’s add another line at the end, and let Carla greet Anja back.

Again, here’s the full code:

class Person
  def initialize(name)
    @name = name
  end

  def name
    @name
  end

  def greet(other)
    puts "Hi " + other.name + "! My name is " + name + "."
  end
end

person = Person.new("Anja")
friend = Person.new("Carla")

person.greet(friend)
friend.greet(person)

And this outputs:

Hi Carla! My name is Anja.
Hi Anja! My name is Carla.

What do you think?

Of course this is still quite a simplistic example. It already shows how you can “model” a certain “real-world” concept in terms of Ruby code, instantiate it, and let it interact with another thing.

By the way if you’d like to see how to make the method greet more pretty, and a little bit easier to read, check out the chapter on String interpolation.

Object Scope and Self

Remember how we said that when Ruby finds a method call she then deviates from the normal control flow which goes from top to bottom? Instead she jumps into the method body.

We also said that this method body has its own scope, like a shiny, new room where local variables from other scopes are not visible. Instead it has its own local variables, some of which might be defined via the method’s arguments.

And we also said that inside any object’s method all instance variables of this object, and all other methods of this object are also visible.

We also may have a look at that mysterious top-level object that Ruby enters when she starts executing a program, or IRB.

We are now finally ready to put all these things together a little more, and introduce a new keyword: self.

The Object Scope

In fact, in Ruby, there are even more scopes than just the local method’s scope:

There’s the method’s local scope, which holds all local variables. And there’s the object’s scope which holds all instance variables and method names.

When Ruby’s control flow jumps into a method then both of these scopes are visible at the same time. For any given name Ruby will first check the local scope, and then the object scope.

In reality this most importantly means that from any method on an object, you can access:

It also means that one can overwrite, sometimes accidentally, method names with variable names. Remember they read just the same in Ruby? While this is a really cool feature, it also means we need to be aware of it.

Consider this code:

class Person
  # ...

  def name
    @name
  end

  def greet(other)
    name = other.name
    puts "Hi " + name + "! My name is " + name + "."
  end
end

As you can see this defines a new local variable name. The code is very similar to what we had before, except that we store the other person’s name to a local variable name first, and then use this variable on the next line when we put together our String.

This breaks our code, of course, in the sense that we don’t get the expected greeting any more. Instead it contains the same name twice:

Hi Carla! My name is Carla.

That is because, on the last line of the method greet, when Ruby looks at the word (identifier) name she first checks the local scope of the method, and finds a local variable defined, so she uses it. Only if there was no local variable defined she would check the object’s scope, and find the method with the same name name, and call it.

When she finds an identifier, Ruby looks for a local variable first, and then for a method.

Luckily, there’s a way to still access the object’s scope:

Self

Every object knows itself, in every method, by the way of calling self. This is a special keyword in Ruby, that means just that: The object itself.

Let’s try that, and output self. In order to do that we need to add it somewhere inside the object. Any method would be good for that, but let’s just use the initialize method:

class Person
  def initialize(name)
    @name = name
    p self
  end
end

person = Person.new("Anja")
p person

This should output something like this:

#<Person:0x007f9994972428 @name="Anja">
#<Person:0x007f9994972428 @name="Anja">

As you can see we output the same object twice. Once in the initialize method using p self, and once in the outer scope using p person. You can also see that the cryptic looking object id is the same for both instances. So we can know it’s indeed the very same object.

Inside any method the object can be referred to using the keyword self.

So we can fix our code from above like this:

class Person
  def name
    @name
  end

  def greet(other)
    name = other.name
    puts "Hi " + name + "! My name is " + self.name + "."
  end
end

Now we call the method name on two different objects again. When Ruby sees self she knows that we’re referring to the person object, and she calls the method name on it.

This fixes our greeting:

Hi Carla! My name is Anja.

Keywords

Why do we keep saying that self is a keyword? Well, because is not a method. It’s a “special thing” in Ruby. For example this means that the following will raise an error:

person = Person.new("Anja")
p person.self

This raises the error:

NoMethodError: undefined method `self' for #<Person:0x007f9994972428 @name="Anja">

It’s not a method, it’s a special thing.

Other keywords that also aren’t methods (or objects, or classes) are, for example, def, class, and end. You’ll also learn about do, if, elsif and else a little later.

Keywords are words that have a special meaning in Ruby, such as class, def, end, and self.

Blocks

Like methods, but without a name

Blocks are one of the things programmers absolutely love about Ruby. They are an extremely powerful feature that allows us to write very flexible code. At the same time they read very well, and they are used all over the place.

So, what is a block?

A block, essentially, is the same thing as a method, except it does not have a name, and does not belong to an object.

I.e. a block is an anonymous piece of code, it can accept input in form of arguments (if it needs any), and it will return a value, but it does not have a name.

Moreover, blocks can only be created by the way of passing them to a method when the method is called.

A block is a piece of code that accepts arguments, and returns a value. A block is always passed to a method call.

Let’s jump right in:

5.times do
  puts "Oh, hello from inside a block!"
end

As you can see times is a method that is defined on numbers: 5.times calls the method times on the number 5.

Now, when this method is called the only thing passed is a block: that is the anonymous piece of code between do and end. There are no objects passed as arguments to the method times, instead it just passes a block.

The method times is implemented in such a way that it simply calls (executes) the block 5 times, and thus, when you run the code, it will print out the message "Oh, hello from inside a block!" 5 times.

The code almost reads like an English sentence Five times do output this message, right? It does, and that’s one of the reasons why Rubyists love using blocks.

One of the things that seem rather hard to grasp about blocks is that

Does that make sense?

Imagine you are the object that represents the number 5. You are a number and you do know your own value.

Now I hand you a piece of paper saying: Please print the following on the screen: "Oh, hello!", and I ask you to execute this instruction as many times as the value that you know.

You’d go ahead and follow the instructions on the paper, and thus print out the message. You repeat this 5 times, because 5 is the value that you know.

This is pretty much how the method times on numbers works, and how blocks work: times takes the block (the instructions), and runs it as many times as the value of the number.

To summarize: Methods can not only accept input in the form of objects passed as arguments. They can also accept this one special piece of input, which is an anonymous block of code. And they can then call (execute) this block of code in order to do useful things with it.

Let’s look at some other aspects of how blocks work next.

Alternative block syntaxes

Next to the syntax shown before, using do and end, Ruby comes with an alternative syntax, which uses curly braces for defining a block.

These two statements do exactly the same:

5.times do
  puts "Oh, hello!"
end

5.times { puts "hello!" }

Both statements define a block, which is passed to the method times. And both blocks contain a single line of code.

Blocks can be defined enclosing code in do and end, or curly braces {}.

So, when do you use one or the other syntax?

In the Ruby community there’s the convention to use curly braces if you have a single line block and it fits nicely on the same line (as, in our example, it does).

Whenever you need to have more than one line in your block, then you use the syntax using do and end. Sometimes people also use the do and end syntax when they feel it makes the code more readable.

Use curly braces {} for blocks, when the code fits on one line.

Block arguments

Blocks make a lot of sense on methods that are defined on collections like arrays and hashes.

Let’s have a look at some examples with arrays.

In our previous example that used the method times our block did not accept an argument. A block that accepts an argument looks like this:

[1, 2, 3, 4, 5].each do |number|
  puts "#{number} was passed to the block"
end

And, again, this is the same as:

[1, 2, 3, 4, 5].each { |number| puts "#{number} was passed to the block" }

It is unknown to us why Matz has chosen to not enclose the argument list of a block with round parentheses just like method argument lists. Instead, Ruby wants us to use vertical bars (we call them “pipes”).

So, for blocks, do |number| is the same that is def add_two (number) for a method definition, except that the method wants a name while a block is anonymous: |number| and (number) both are argument lists. The first one is used for blocks, the second one for methods.

Block arguments are listed between pipes |, instead of parentheses.

Now, when you run the code example above, you’ll see the message printed out for each of the numbers contained in the array.

Does that make sense? Again, our code almost reads like an English sentence:

With this array for each of its elements, naming it number, output the following message.

The method each is defined on arrays, and it does just this:

It takes each of the elements in the array and calls the block, passing the element as an argument. The block can then do whatever you want it to do with the element. In our case we interpolate it into a string and print it out to the screen.

Block return values

Remember that we said a block returns a value just like methods do? So far, in our two examples above, we did not do anything with the return values of the block.

Here’s an example that does that:

p [1, 2, 3, 4, 5].collect { |number| number + 1 }

This will take the array of numbers, and transform it into another array.

It does this by calling the method collect on the original array, which calls the given block for each of the elements, and collects each of the return values returned by the block. The resulting array is then returned by the method collect, and printed to the screen.

In other words, the method collect uses the block as a transformer. It takes each element of the array, passes it to the block in order to transform it to something else, and then keeps all the transformed values in a new array that the method collect then eventually returns.

Note that the method collect has an alias, which is map. These are exactly the same methods. Many programmers prefer map over collect because it is shorter, and also more commonly used in other languages. However, in our study groups we use collect more often, because it simply expresses more clearly what the method does.

Use the method collect to transform an array into another array.

Here’s another example that uses the return value of the block, can you guess what it does?

p [1, 2, 3, 4, 5].select { |number| number.odd? }

In this case, the method select uses the block in a different way: as a filter, or criterion, to select values out of the array, and then return a new array with the selected values.

Let’s walk through this step by step, under the microscope:

Thus, the code above prints out [1, 3, 5].

Use the method select to select a new array with values that match a criteria defined by the block.

Here’s another example of a method that uses the block as a criterion:

p [1, 2, 3, 4, 5].detect { |number| number.even? }

Again, detect will pass each of the elements of the array to the block, one by one, and check the return value of the block. However, as soon as the block returns something truthy (something that is “equivalent to true”), the method detect will return the current object itself. Therefore, this will print out 2: the first number in the array that is even.

Inversion of control

In Ruby there are a lot more methods that accept blocks, and they do very different things. However, they have one thing in common:

By accepting a block, from you as a programmer, the method can pass control to you.

This design is an example for the principle of inversion of control, and it’s the real reason why Rubyists love blocks so much.

What does that mean?

In short it means that Matz, the creator of Ruby, put a tool in place that can be used to allow methods to pass control to its users (i.e. you as a programmer).

“Control” in this context refers to the question who gets to decide how things work.

In older languages, where there was no such tool, people either had to implement lots of very specific methods, and guess what users might need in the future. Or they’d decide to just not implement any of these methods at all.

For example, in Ruby, we don’t have to define lots of methods like select_odd, select_even, select_lesser_than, select_greater_than and so on, … where each of these methods would be useful for one very specific usecase.

Instead, the class Array only has to implement one single, very generic method for arrays: select. Since Ruby has blocks, the method can allow you (as a programmer) to specify the criterion yourself: by passing a piece of code, in the form of block to the method.

That way Ruby lets you, as a programmer, take over control, and specify what is used as a criterion to select elements.

One of the reasons we mention this is because we think this is a nice example of a pretty abstract principle applied to software design. There are lots of other principles like these, and they’ll make more and more sense to you over time. Programming languages and code, from this perspective, is a subject of design, and thus art, as well as social and cultural questions … much rather than strictly logical or technical ones.

Iterators

Methods on arrays and hashes that take a block are also called iterators.

We say they iterate over the array, meaning that these methods take each element of the array and do something with it.

In Ruby iterators are “chainable”, adding functionality on top of each other.

That means that, if you do not pass a block to an iterator method, such as each, collect, select, then you’ll get an iterator object back. You can then call more methods on these iterator objects, and finally pass a block. Like so:

numbers = [1, 2, 3, 4, 5].collect.with_index do |number, index|
  number + index
end
p numbers

This will print out:

[1, 3, 5, 7, 9]

What’s going on here?

The method with_index can be called on any iterator object. All it does is pass the index of the element within the array to the block, as a second block argument, in addition to the element itself.

Inside of the block we can then use it, and add the index to the number itself.

So for the first iteration it will call the block with 1 and 0, since 0 is the first “position”, that is, index. It therefore returns 1. For the second iteration it calls the block with 2 and 1, and returns 3, and so on.

Therefore the method call eventually returns the array [1, 3, 5, 7, 9].

Iterators in Ruby are chainable.

Conditionals

If this is true, then do that. Otherwise do something else.

Often we want to check for a certain condition, and then based on it, do either one thing or another. Or we want to do something only if a condition is true.

All practical programming languages have some way of expressing this, and in Ruby it looks like so:

number = 5

if number.between?(1, 10)
  puts "The number is between 1 and 10"
elsif number.between?(11, 20)
  puts "The number is between 11 and 20"
else
  puts "The number is bigger than 20"
end

You can probably guess what it does, and how it works, can’t you?

Let’s walk through it one by one:

The elsif and else statements and branches are optional: you don’t need to have them. You can have an if statement without elsif or else branches, an if statement only with an else, or you could have an if statement with one or more elsif statements. Or combine all of them together:

Nothingness and the truth

Now is a good time to talk about the concepts of nothingness and truth in Ruby.

Nil

We have briefly mentioned that in Ruby there is an object that represents “nothing”: the object nil.

That’s right. “Nothing” is a thing in Ruby (as well as in many other languages), albeit a very special one. We could ramble on the philosophical implications of this, but instead we’ll just look at how this is used in practice:

Remember how we can receive a value associated with a key from a hash?

dictionary = { :one => "eins", :two => "zwei", :three => "drei" }
p dictionary[:one]

This will print out "eins". However, what happens if we try to receive the value for a key that has not been defined on the hash?

dictionary = { :one => "eins", :two => "zwei", :three => "drei" }
p dictionary[:four]

This will print out nil. Remember that every method call always will return some value? In cases where there’s nothing to return, it will return nil, which represents nothing :)

In Ruby, nil, nothing, is something else than, for example, 0, which represents something. An empty string "", an empty array [], or empty Hash {} also all represent something. So they’re not nil.

True and false

We have also discussed that in order to represent truth, and the opposite of it, Ruby also knows the values true and false.

You have seen them when we tried some of the methods on numbers, strings and arrays, like 3.odd?, "a string".start_with?("a"), or [1, 2, 3].include?(2).

These so called predicate methods always return either true or false.

Predicate methods end with a question mark, and return true or false.

The objects nil, true, and false also have classes, and you can check that in IRB yourself: nil.class, true.class and false.class.

For a reason that we don’t know Matz (the creator of Ruby) has decided to call these classes NilClass, TrueClass and FalseClass, instead of just Nil, True and False. If you ever meet him at a conference you can ask him :)

Truthiness and falsiness

Now, when we talked about if statements we used methods that actually return true and false values, like the odd? method on numbers does. Comparison operators like ==, < and > also return true and false, as in:

number = 3
if number >= 5
  puts "The number #{number} is greater than 5, or equal to 5"
else
  puts "The number #{number} is less than 5"
end

However, what happens when we use methods as conditions that do not return true or false, but something else, for example a string, number, or nil?

For example, consider the following:

dictionary = { :one => "eins", :two => "zwei", :three => "drei" }
key = :four

if dictionary[key]
  puts "The dictionary defines a value for the key #{key}."
else
  puts "The dictionary does not define a value for the key #{key}."
end

As we saw before dictionary[:four] will return nil because this key is not defined. Is nil equivalent to true or false? Or will this raise an error?

If you run the code above then you see that Ruby will execute the else branch. That means Ruby actually considers nil to be equivalent to not true, that is, false.

Now, lets use a key that actually is defined:

dictionary = { :one => "eins", :two => "zwei", :three => "drei" }
key = :one

if dictionary[key]
  puts "The dictionary defines a value for the key #{key}."
else
  puts "The dictionary does not define a value for the key #{key}."
end

As you saw before dictionary[:one] will return "eins", because that’s the value associated with the key :one. Again, do you think "eins" is equivalent to true or false? Or will this raise an error instead?

If you run the code then you’ll see that Ruby now executes the if branch, and considers the condition (i.e. the string "eins") to be equivalent to true.

Think about this for second: Ruby considers everything to be equivalent to true that is not false or nil. Or put the other way around, Ruby only considers nil to be equivalent to false.

Because “is equivalent to true” or “is equivalent to false” is quite a clunky thing to repeat so often the programming community has come up with terms for this: truthiness and falsiness. So we can say that the string "eins" is truthy. And nil is the only other thing that is falsy in Ruby, except false itself.

To sum this up, if and unless look at the truthiness of a the value that is returned by the condition. Everything except false and nil is truthy, including strings, numbers, arrays, hashes, and every other object.

This also includes the number 0, empty strings "", arrays [] and hashes {}. These aren’t nothing (nil), instead they’re something, and therefore, in Ruby, truthy.

Here’s a pattern that you might see used when you look at other people’s code:

dictionary = { :one => "eins", :two => "zwei", :three => "drei" }
key = :one
translation = dictionary[key]

if translation
  puts "The translation for #{key} is: #{translation}."
else
  puts "The dictionary does not define a translation for the key #{key}."
end

If you read this out loud, does it make sense to you?

The code first looks up the translation from the dictionary hash. And then it says If there’s a translation, then use it. Otherwise do something else.

Ruby’s concept of truthiness allows us to write our code in this concise way that almost reads like English. And that’s one reason why many people love Ruby so much.

Operators

We’ve already used some arithmetic operators (+ and *) above. You have also learned that operators, under the hood, are just methods. Ruby just adds a little bit of syntax sugar on top of these methods, so they’re sweeter to read, and write.

There also are operators for comparing things, for logical calculations, and other operations. Let talk about some more of them.

Arithmetical operators

For numbers, the operators + and * obviously mean the mathematical operations of adding and multiplying two numbers. Of course there are other arithmetical operators. Here’s a full list:

However, some of these methods are also defined on other objects, like strings and arrays.

Try it yourself in IRB:

$ irb
> "<3" + "!"
=> "<3!"

> "<3" * 3
=> "<3<3<3"

As you can see, these operators mean something different for strings. But they also make sense, don’t they?

Adding one string to another just means that they will be concatenated into one longer string. And multiplying a string by a number means repeating it as many times.

The same works for arrays:

$ irb
> [1, 2] + [3, 4]
=> [1, 2, 3, 4]

> [1, 2] * 3
=> [1, 2, 1, 2, 1, 2]

Again, adding two arrays means combining them into one big array. And multiplying an array with a number means getting a big array with the original elements repeated.

Logical operators

Logical operators are also, maybe more commonly, called boolean operators.

The term “boolean” originates from the book “The Mathemetical Analysis of Logic” written by George Boole in 1847. Boolean logic has been fundamental in the development of computers, and programming, since at their core, computers are all about processing whether or not there is current flow: on vs off (true vs false).

If you are curious, feel encouraged to google and read up on this online, but for now, we can simply look at the 3 fundamental boolean operators and what they do: and, or, and not.

The operator and returns true if, and only if, both values also are true. So, only the expression true and true is also true. All of the expressions true and false, false and true, false and false evaluate to false.

If you think about this, and come up with English sentences, then this will make a lot of sense: At the restaurant I’ll have a tomato soup IF it is vegan AND they still have some.

The operator or on the other hand returns true if at least one of the values is true. So, only if both values are false, the operator returns false.

That’s why it is logically correct to answer the question Would you like tea or coffee for breakfeast? with Yes, please. IF you’d like either tea, or coffee, or both. You’d only say Hell, no! if you’d like an orange juice instead :)

The operator not simply returns the negated, opposite value. not true returns false, and not false returns true. Therefore, the following lines of code are the same:

puts "Always true" if not false
puts "Always true" unless false

Each of these three operators comes in two versions:

The difference between them has to do with what is called “operator precedence”.

From math you know that 1 + 2 * 3 evaluates to 7, not 9. This is because the multiplication * operator binds stronger, and precedes the addition operator +. In other words 1 + 2 * 3 is same as 1 + (2 * 3), and not the same as (1 + 2) * 3.

In Ruby, the operators &&, ||, and ! bind stronger than, and thus precede their fellows and, or, and not.

Comparison operators

In order to compare things Ruby has a bunch of comparison operators.

The operator == returns true if both objects can be considered the same. For example 1 == 1 * 1 will return true, because the numbers on both sides represent the same value. The expression "A" == "A" also returns true because both strings have the same value.

Likewise, two arrays are equivalent when they contain the same elements, in the same order. For example [1, 2] == [1, 2] will return true, but [1, 2] == [2, 3] and [1, 2] == [2, 1] both will return false.

Note that we say “considered the same” and “equivalent” because technically the two objects do not have to be (and most often, as in our examples) are not the same objects. E.g. while evaluating the expression "A" == "A" Ruby will actually create two different string objects which both contain a single character A.

In practice this is almost always what you want. For the rare case when you actually need to check if two objects are the same object there’s the method equal?. E.g., "A".equal?("A") returns false.

Other comparison operators are: less than < , less than or equal <=, greater than >, and greater than or equal >=. They also work on numbers and strings, in the way you’ll expect it. Open IRB and try a few combinations on numbers and strings.

Comparison operators most often are used in order to formulate conditions in if statements. Like so:

number = 20
puts "#{number} is greater than 10." if number > 10

The most funny operator in Ruby is <=>, because it’s called the spaceship operator. No kidding :) It is rather rarely used, and it is useful for implementing custom ways of sorting things.

Operators are methods

As you have seen a number has methods named like the arithmetic operators +, -, *, and /. That’s right! Interesting.

If you think about this, it makes sense: If everything is an object then numbers are objects. If “doing things” means operating with methods by the way of calling them, then what would + be? A method of course.

But if we call methods on objects using that dot . notation, then where are the dots in 2 + 3 * 4?

The trick is: Ruby adds them for you, silently. If you write the following code:

number = 2 + 3 * 4

Then Ruby will translate this to the following:

number = 2.+(3.*(4))

Fun, isn’t it? These operators are all methods on numbers, and they can be called just like any other method. (The same is true for lots of other operators, as you can see in IRB, when you run 1.methods.sort.) The code above is valid Ruby code, and both lines do exactly the same.

Ruby just adds a little bit of syntax in order to make it easier to read and write for us: It allows us to write number = 2 + 3 * 4 instead of number = 2.+(3.*(4)), which is a pretty nasty thing to type.

This is something called “syntax sugar”, because it makes the language more sweet (no kidding).

By the way, this works the same way for other things too.

For example, you have learned about the array and hash syntax that uses square brackets [] for reading and writing.

Ruby translates this code:

array = [1, 2, 3]
array[3] = 4
puts array[3]

hash = { :one => 'eins', :two => 'zwei' }
hash[:three] = 'drei'
puts hash[:three]

to these method calls:

array = [1, 2, 3]
array.[]=(3, 4)
puts(array.[](3))

hash = { :one => 'eins', :two => 'zwei' }
hash.[]=(:three, 'drei')
puts(hash.[](:three))

Knowing this can be useful when you want to write classes that look and feel similar to arrays or hashes, but behave differently.

Bonus Chapters

String interpolation

As mentioned above you can stick strings together by using the + operator.

Consider the following code:

name = "Ada"
puts "Hello, " + name + "!"

This, of course, will output the message Hello, Ada!.

Glueing strings together like this works, and you can do it. However, there is another method of accomplishing the same, and it is widely used, and usually preferred over concatenating strings with +.

This method is called “string interpolation”, and this is how it looks:

name = "Ada"
puts "Hello, #{name}!"

Using this syntax everything between the opening #{ and closing } bits is evaluated as Ruby code, and the result of this evaluation will be embedded into the string surrounding it.

In other words, when Ruby finds #{name} in this string, then it will evaluate the piece of Ruby code name. It finds that this is a variable, so it returns the value of the variable, which is the string "Ada". So it embeds it into the surrounding string "Hello, #{name}!", by replacing #{name}.

Now we can also finally explain the difference between strings created with single and double quotes:

String interpolation only works with double quotes.

That means that:

puts "Interpolation works in double quoted strings: #{1 + 2}."
puts 'And it does not work in single quoted strings: #{1 + 2}.'

will print out:

Interpolation works in double quoted strings: 3.
And it does not work in single quoted strings: #{1 + 2}.

If you type the code above in your editor, and syntax highlighting for Ruby code is used, it should highlight the code in the double quoted string, so it gives you a visual clue about the interpolation.

So, why do people prefer string interpolation?

First of all, again, it’s slightly fewer letters to type. In our example, that’s just 5 characters, no big deal. However, consider a longer string, which is constructed using three, four, or more variables. Now this extra space quickly adds up, and things wouldn’t fit nicely on a single line anymore.

Also, many people find that the syntax reads a bit better. There’s a little bit less clutter, making it a little bit easier to see what’s going on.

One other, albeit pretty negligible reason is, that string interpolation actually uses less resources:

So, string concatenation creates 2 more string objects even in our simple example. These intermediate objects are immediately discarded, because they’re not used any more. We’re only interested in the final result "Hello, Ada!".

We recommend you get used to using string interpolation, just because this is what most developers use.

Escape sequences

There’s one other little difference between single and double-quoted string that we should mention while we’re at it.

In programming, strings can not only contain text as we normally think about it. They can also contain control characters. Control characters are also called “non-printing” characters, even though they can have visual effects.

Control characters can represent all sorts of things, such as removing the last character (“backspace”), the next one (“delete”), or even causing an auditable alert (“bell”).

The one most typically used in Ruby programs is the “newline” character.

Because there’s no way to represent a “newline” character using any of the keys on your keyboard programmers have come up with the idea of escape sequences: An escape sequence is a code that consists of a backslash and another character, and this combination is used in place of control characters.

For example, \n is the escape sequence that stands for the “newline” character.

So this code:

puts "one\ntwo\nthree"

Will print out:

one
two
three

Now, escape sequences also only work in double quoted strings. If you try to use them in a single quoted string like so:

puts 'one\ntwo\nthree'

then that will print out the string literally:

one\ntwo\nthree

Which means that escape sequences are not replaced in single quoted strings.

Top-level object

So, we’ve learned that objects come with lots of methods attached to them. And we’ve seen how we can use them to do interesting things with the object, by the way of calling these methods.

Now, if you pop into irb, or if you write the following code into an otherwise empty Ruby file, this works:

$ irb
> is_a?(Object)
true
> methods
[:to_s, :inspect, ... ]

So, as you can see we can use some methods in Ruby without even defining an object at all: They’re already there. And the method is_a? tells us that this already is an object … whatever “this” is.

What’s up with that?

This is something that pretty much blows some people’s minds, confuses the heck out of others, while yet others don’t even notice or think about it at all. It is also something, that, when you ask around on your local Ruby meetup, very few people can explain in a satisfying, and clear way. And neither do we, yet.

Let’s still try.

Whenever you open IRB and it presents that prompt to you, or when you create a new, empty Ruby file … Ruby will not only execute your code: Before she does she first creates an empty, anonymous Object, and kind of places you inside of it.

This empty Object kind of seems invisible, and it seems that those methods that we can define in this scope (space) were somehow “standing alone”. In fact they aren’t. They’re defined on this empty, anonymous Object that we usually don’t see.

This Object often is referred to as the top-level scope in Ruby.

The top-level scope is an empty, anonymous object. All Ruby code starts in here.

Confusing? Yeah. Don’t worry. This is something many Ruby programmers do and use everyday without ever asking the question why it works, exactly.

Hopefully some of this will become more clear once you’ve written your own methods and classes.

Lots of other methods

If you look at the methods that are defined on strings and arrays (e.g. run [].methods.sort or {}.methods.sort in IRB), then you’ll find quite a bunch of method names that look like they are doing exactly what their names describe.

For example, some of the things you can do with strings are:

Some examples for useful methods on arrays are:

How do you find all these methods?

The quickest way to find a certain method for an object often is to just ask Google: “ruby array sort”. That will point you to the Ruby documentation. Another way is to read through all the methods for the class on the respective Ruby documentation page. And of course, you can also read through the method names returned by [1, 2, 3].methods.sort.

Questions and commands

Generally speaking, methods play one of two roles: They either answer a question, or they perform a command.

For example, if we have a user object, and users have a name, then we would ask the user object for its name by calling the method name: user.name would return the user’s name. Arrays know their size (how many elements they have), so we can ask an array: [1, 2, 3].size will return 3.

Another example is the method sort on arrays. This method does not actually sort the array that it is called on. Instead it returns a new array with the same values, but in a sorted order:

array = [3, 2, 1]
p array.sort
p array

This will output [1, 2, 3] and then [3, 2, 1]. So we see that the original array is still the same.

Often questions need another bit of information passed. E.g., we can ask a string Do you start with this character?, and we’ll need to pass the character that we are talking about: "a string".start_with?("a"). The answer to this question will be true. Or if we ask an array if it includes a certain element, then of course we need to pass that element, as in [1, 2, 3].include?(1)

The other role that a method can play is being responsible for executing a certain command.

For example in Rails objects that can be stored to the database have a method save. Of course, the purpose of this method is to save the object to the database. E.g. user.save would save some changes that we’ve made to the user before, like, maybe we have given them a new password.

Another example is the method sort! on arrays. Different from the method sort (without an exclamation mark), this method tells the array to sort itself:

array = [3, 2, 1]
array.sort!
p array

If you run this code, then it will print out [1, 2, 3]: the array is now sorted.

Another example for a method that is a command is the method puts. All it does is print something to the screen, and it always returns nil.

Whenever you think about adding a new method to your code it makes sense to think about the role the method should have. Is it a question? Or a command?

Alternative Syntax

You have, so far, learned that Strings are defined using single or double quotes, like so:

"A String"
'Another String'

And Arrays are defined using square brackes, with a comma separated list of objects, like so:

["One", "Two", "Three"]

We’d like to quickly mention two alternative syntaxes for defining the same objects, even though they’re not used very often. However, you may sometimes find them in other people’s code, so it’s useful to know they exist.

Strings

First, Ruby has an alternative syntax for defining strings that goes like so:

%[any-character]The actual string[the same character]

Meaning, that when there’s a percentage character % followed by any other character, which also closes the whole thing, then this defines a string, too.

For examples these definitions all mean exactly the same:

"A String"
'A String'
%(A String)
%{A String}
%|A String|

Which character is used to open and close the string is a matter of style, and preference. The author of this text prefers round paratheses for readability, but others prefer curly braces or pipes. There’s no very clear convention in the Ruby community.

When would you use this alternative syntax?

Sometimes you need to define a string that itself contains (or may contain, in future versions) the same quote character that you’ve used to define the string. For example, if you have a string that contains the string "Name", including the quotes, but in the same string you’d also like to use String interpolation, so you’d normally use double quotes to define the string. In that case you’d need to escape the double quotes that are contained in your string.

It probably helps to look at an example. Imagine you’re working on an application that asks the user for an email address, validates the format of the given address, and then displays an error message if the format looks invalid:

The given email address "ruby@monstas" does not look like a valid email address.

Using double quotes your code might look like this:

address = "ruby@monstas"
message = "The given email address \"#{address}\" does not look like a valid email address."
puts message

Try running this code, and then also try removing the backslashes, and running it again. You’ll get a syntax error message because Ruby thinks the second double quote (after address) closes the first one, so it would look at #{...} outside of a string, which is not valid Ruby.

While the above code, including the backslash characters, is valid Ruby code, it looks a little ugly. Typing this stuff is kinda cumbersome, and programmers usually hate it.

So Ruby gives us another, nicer way to express the same:

message = %(The given email address "#{address}" does not look like a valid email address.)

Also, this allows us to freely change the message later, without having to change the quotes. For example, if our original message would have looked like so:

message = %(The given email address does not look like a valid email address.)

We could now change it to say the following without changing the quotes:

message = %(The given email address doesn't look like a valid email address.)

Arrays

Imagine you are running a programming study group, and you want to quickly write a piece of code that runs a little raffle to assign people to pairs randomly.

people = [
  "Anne",
  "Elizabeth",
  "Erica",
  "Iryna",
  "Johanna",
  "Juliane",
  "Katja",
  "Katrin",
  "Maria",
  "Renate",
  "Sureka",
  "Miriam",
  "Zazie",
  "Anja"
]
people.shuffle.each_slice(2) do |pair|
  puts pair.join(', ')
end

Well, this code works. But wouldn’t it be cool to be able to define the array without having to write out all those quotes and commas? They’re quite cumbersome to type, aren’t they? Also, if we could omit them then we could just copy and paste that list of names from some where else, without modifying it further.

Luckily, Ruby provides us with a piece of syntax that does exactly this:

people = %w(
  Anne
  Elizabeth
  Erica
  Iryna
  Johanna
  Juliane
  Katja
  Katrin
  Maria
  Renate
  Sureka
  Miriam
  Zazie
  Anja
)
people.shuffle.each_slice(2) do |pair|
  puts pair.join(', ')
end

The w in %w(...) stands for “words”, which means an array defined like this will always only contain strings. So, %w(1 2 3 4) would result in the same array as ["1", "2", "3", "4"].

Using the right words

Naming things is hard

Just like programmers are obsessed about formatting, they also care a lot about how to name the things they create.

Choosing good names for your variables, methods, and classes is important, because this makes your code more expressive and easy to read. In fact, once you’ve learned the basic concepts of Ruby, well crafted code will read almost like a prose text to you. Not necessarily like your favorite novel, but maybe like a recipe or other instructional prose. Ruby is particularly great for writing expressive, readable code.

Here are a few examples of great, and rather bad names to pick.

Consider this code:

class Email
  def initialize(str, string2, headers_hash)
    # ...
  end

  # more methods ...
end

an_email = Email.new("Hi there, Ruby Monstas!", "2015-01-02", { :from => "Ferdous" })

From looking at the first two lines of this code you can figure out that the author defines an Email class, and it takes 3 arguments, two of which probably are supposed to be strings, and one is a hash containing some headers.

But what’s the purpose of the first two arguments? All we know the author wants them to be strings. So we might have to consult the documentation, or look at examples using the class. Luckily we can find an example at the very bottom of the file, and see that the first argument is supposed to be the subject, while the second one is a date.

Using the “type” of an object as a variable name, or part of a variable name, usually is not a very good idea: string, array, hash often are bad names, except in contexts where the type of the object is all that matters. One example for such a context is the method definition def encrypt(string) in the Modules chapter.

In our case it makes sense to name these arguments subject and date in the first place, in order to make it easier for others to understand the purpose of these arguments:

When you tell your non-programmer friends that “An email requires two strings and a hash of headers.”, they’d probably stare at you weird and switch to another topic. When you instead say “An email requires a subject, a date, and some headers” then they might roughly understand what you’re saying.

So let’s rename them:

class Email
  def initialize(subject, date, headers)
    # ...
  end
end

email = Email.new("Hi there, Ruby Monstas!", "2015-01-02", { :from => "Ferdous" })

Also, the first argument name str in the first example is an abbreviation, which is something that isn’t very common in the Ruby world. People used to use abbreviated variable names back when memory was extremely sparse, and expensive: longer variable names would consume more memory. Nowadays there’s just no reason any more to make your fellow developers puzzle over abbreviated names. Consider var, var1, var_2 bad names, and instead use names that reveal (talk about) your intentions, and their purpose.

Did you notice the local variable name an_email in the first example? The name email in the second example also is much better in most situations. The prefix an_ doesn’t add any kind of information. It’s just noisy, and adds clutter.

Another example:

emailslist = [
  Email.new("Hi there, Ruby Monstas!", "2015-01-02", { :from => "Ferdous" }),
  Email.new("Keep on coding! :)", "2015-01-03", { :from => "Dajana" })
]
emailslist.each do |mail|
  puts mail.subject
end

Again, list says something about the type. Why not just call it emails. The plural already says that it’s some kind of list.

Also, the block argument mail deviates from the class name Email, and the variable name emails … and thus might raise a question “Wait, is this a mail maybe something different from an email in this code?”. So why not avoid confusion like that in the first place and call it email … simply the singular form of the name of the collection emails:

emails = [
  Email.new("Hi there, Ruby Monstas!", "2015-01-02", { :from => "Ferdous" }),
  Email.new("Keep on coding! :)", "2015-01-03", { :from => "Dajana" })
]
emails.each do |email|
  puts email.subject
end

The section “Naming variables” in this chapter of Ruby in 100 Minutes also has a couple great examples of good vs bad names.

Also, even though these examples are talking about local variables, the same reasoning applies to method names, class names, … basically any name that you pick.

Great names reveal your intention while you write this code. They talk about the purpose of your code, and explain things to your fellow developers.

Oh, and if you’re curious to read more about this, here is an interesting presentation on How to name things as well as a blog post on what programmers find the hardest tasks they face (guess what, it’s naming things …).

Arguments and parentheses

If you have read carefully, you may have noticed that we said about the code puts 5 that puts is a method call. And then later we’ve enclosed the value 3 in parentheses when calling the method: add_two(3).

That’s right:

In Ruby, when you define or call (execute, use) a method, you can omit the parentheses.

So these lines mean exactly the same:

puts "Hello!"
puts("Hello!")

And so do these:

add_two 2
add_two(2)

And all of these:

puts add_two 2
puts add_two(2)
puts(add_two 2)
puts(add_two(2))

So when do you use parentheses, and when do you omit them?

There is no clear rule about this, but there are some conventions. For now, you can just stick with the convention we are using at our study groups, which is:

So the idiomatic way to write the line above is:

puts add_two(2)

Methods without arguments

Also, so far we’ve only mentioned that sometimes methods do not take any arguments. But we haven’t looked at an example so far.

Here’s one:

def greet
  puts "Oh, hello!"
end

greet

The first three lines define a method, and we’ve picked the name greet for it. Again, the method body contains just a single line.

The last line consists of nothing but the word greet. When Ruby runs this code, and it finds the word greet it will know that this refers to the method defined earlier, and call it.

So Ruby jumps into the method body (this time it does not bring any objects with it as arguments, because our method does not need any). It then executes the line puts "Oh, hello!" which prints a greeting to the screen.

As you can see we do not use any parentheses here. We could do that. The following code would be perfectly valid, and do exactly the same:

def greet()
  puts "Oh, hello!"
end

greet()

However since we can omit the parentheses in this case we do just that. They just add visual noise and make the code slightly less readable.

Returning nil

Also, you might wonder what’s going on with the return value our our greet method. We just said that every method call always returns “something” (an object).

That’s right. The method call greet will return the object returned from the last evaluated statement (which, in our case, is puts "Oh, hello!").

What do you think that is?

The method puts always returns nil (because it was written that way): Its purpose is to print something to the screen, not return something interesting. It’s a command, not a question. So the most sensible choice for a return value is nil.

So where does the nil object go?

If you look at our example code you notice that we don’t do anything with the return value of the method call greet: We don’t assign it to a variable. And we don’t pass it to another method call. In fact, we simply discard it since we’re not interested it in.

In our example that’s just fine. In practice you should always be aware why you are calling a certain method. Is it a command like Please print this? Then you probably aren’t interested in the return value and you can discard it as we’ve done above. Or is it a more like a question What’s the result when you add 2 to this number? In that case obviously you want to use the return value later.

For the sake of demonstrating that puts and greet indeed return nil we can use p to inspect the return value like so:

$ irb
> def greet
>   puts "Oh, hello!"
> end
> p greet
Oh, hello!
=> nil

Here we go. The => thing in IRB signals that this is the return value. As you can see it first prints the greeting (using puts) and then, after returning from the method, outputs the nil value.

Terminology: Arguments vs Parameters

We should mention that we are slightly simplifying terminology here. We conflate two terms that normally would be defined separately: We simply use the term “argument” for both the variable names that are defined in the arguments list of the method definition, and the value that is passed as part of the method call.

In programming, normally the “argument list” is called a “parameter list” instead, and a single name on it is called a “parameter”. On the other hand, only the objects passed when calling the method are referred to as “arguments”.

E.g. in the code …

def add_two(number)
  number + 2
end

puts add_two(3)

… the word number in the first line is a “parameter”, whereas 3 in the last line is an “argument”.

We found making this distinction in our beginners classes unnecessarily confusing, and thus ignore it. We simply call both these things “arguments”, and point out that they create a local variable inside of the method body.

So, now you know :)

Writing a new method

As programmers we like to split up our tasks, and do one thing after another. This allows us to focus on one small task, and once we’ve solved it, we move on to the next one.

When you need to add some new functionality to your program you’ll often find yourself thinking “I should add a method for this”: methods add behaviour.

Now, the first thing you should ask yourself is: “What is it that this method should do?” The answer to this gives you a hint for a good method name.

Let’s say you are working on an application that deals with emails, and the thing you are trying to accomplish is formatting an email. So your method name can be format_email.

With this first task solved, knowing the method name, you can already go ahead and write down the method definition:

def format_email
end

While this is a pretty useless method, since it does nothing at all, it already is a valid method. So that’s good progress already: you’ve made the first step.

The next question to ask is: “Does this method need to be given any information in order to do its thing?” The answer to this question specifies the method’s arguments list.

In our example, the answer probably is that, in order to format an email, it needs the email.

So you can now add the argument list to the method:

def format_email(email)
end

With these two things solved you can now start thinking about implementing the method body. How can you transform the email into some formatted text?

You’d add a new line between def and end, and make sure it’s indented by two spaces (hit tab, unless your editor does it for you), and start focussing on the code that makes up the method body:

def format_email(email)
  ...
end

You see how we’ve split up the task of writing a new method into three smaller tasks, and worked on each one of them after another.

Even though this might seem trivial at first, we recommend you get into this habit, too.

Btw, good editors help you format things. For example, when you are on a line that starts with def something, and at the end of the line hit return, Sublime will already indent the next line for you by 2 spaces. If you now type end, then Sublime will notice that you are closing the method, and outdent it again, so def and end sit on the same level. Smart, isn’t it?

Also, you’ll notice that when you type an opening parenthesis (, then Sublime will add a closing one ) too, but keep your cursor placed between them, so you can type the argument list where it belongs.

Exercises: Now would be a good time to do some of the exercises on methods.

Advanced Topics

Using Libraries (1)

Our Person class does not define an attribute accessor method for its password, and thus, others cannot ask for and retrieve it.

However, our person object could freely give them an encrypted version of it.

Actually, this is pretty similar to how authentication often works in real web applications:

Applications do not store your actual password in plain text (hopefully!) That way if, for some reason, they get hacked, attackers wouldn’t have your actual password. Instead they store an encrypted version of the password.

Anyhow, we now want to add a method encrypted_password to the Person class, which should return an encrypted version of the password that is stored in the instance variable @password.

Encryption is one of the things in programming that require very deep expert knowledge, and it is one of the things we definitely wouldn’t want to implement ourselves.

So far, all the Ruby features and methods that we have used are available right away when the Ruby runtime ruby executes your code. However, Ruby also comes with a ton of functionality that is not available (loaded) right away. Instead it is stored in so called libraries (which are just Ruby files, too), and we have to load them manually, in order to make them available.

To do this, we use the method require, and pass it the name of the library:

require 'digest'

Normally require statements should be placed at the very top of the file, so it is easy to see what libraries a particular piece of code (class) uses.

We are going to omit the initialize and name methods here, indicate the omission with the comment # ..., and just keep the password= attribute writer. In order to run this code make sure you keep all the methods.

require 'digest'

class Person
  # ...

  def password=(password)
    @password = password
  end

  def encrypted_password
    Digest::SHA2.hexdigest(@password)
  end
end

The library digest that we required includes a something called Digest::SHA2.

In programming a “digest” is an algorithm to convert one string into another in a way that the original string cannot be recovered later. However digesting the same string will always result in the same other, unique string. There are a good bunch of algorithms that do this, and “sha2” is the name of one of them.

Ok. For our example here we only need to understand that, once we have required the library digest, we can use the method Digest::SHA2.hexdigest, and it will encrypt (“digest”) the string that we pass to it.

If now run the following code:

person = Person.new("Ada")
person.password = "super secret"
puts person.encrypted_password

it will output

eabd522910ccdd77aef079feff0c7bb6486f6ab207ae6d3ed9e671208c92ab0f

which is the digested form of the string "super secret". Every time you run the program you will see the same, unique string.

Modules

It now makes sense to introduce another language feature in Ruby: modules.

In Ruby, modules are somewhat similar to classes: they are things that hold methods, just like classes do. However, modules can not be instantiated. I.e., it is not possible to create objects from a module. And modules, unlike classes, therefore do not have a method new.

So, what are modules useful for?

With modules you can share methods between classes: Modules can be included into classes, and this makes their methods available on the class, just as if we’d copied and pasted these methods over to the class definition.

This is useful if we have methods that we want to reuse in certain classes, but also want to keep them in a central place, so we do not have to repeat them everywhere.

Let’s have a look at this pretty contrived code:

module Cream
  def cream?
    true
  end
end

class Cookie
  include Cream
end

cookie = Cookie.new
p cookie.cream?

We still haven’t been able to come up with a better minimal example of a module and class that makes more sense than this. And we fully admit that this code is rather weird. However, it’s good enough to quickly explain how modules work :)

If you run this code it will output true. Why is that?

The method cream? is defined on the module Cream, and all it does is always return the value true. Now, this module is included into the class Cookie. So, if we now instantiate a cookie, we can call the method cream? on it, and it will return the value true.

Cool. Let’s move on and use this for our Person class, which will hopefully then make more sense.

Let’s assume that our application has other classes that need to encrypt things. And we want to keep the exact way of how we encrypt things, the implementation in one single place.

Why would we want to do that?

Anyhow. Here’s how we can create a meaningful module for our application, and then use it in the class Person:

require 'digest'

module Encryption
  def encrypt(string)
    Digest::SHA2.hexdigest(string)
  end
end

class Person
  include Encryption

  # ...

  def encrypted_password
    encrypt(@password)
  end
end

person = Person.new("Ada")
person.password = "super secret"
puts person.encrypted_password

If you run this code, it will print out the same, encrypted version of the password: cool, that’s what we want.

We have moved the noisy details of the encryption algorithm to a module, and then included the module to the class Person. This, at the very least, makes the method encrypted_password much easier to read. Doesn’t it?

We refer to the process of moving some logic (code) from one method to another new method as “extracting a method”. In our case we have extracted the method encrypt from the method encrypt_password. When we do this, methods usually become shorter and more readable.

Private methods

Remember how we said that instance variables store data that is “private” to the object? Instance variables are only made accessible to the outside world (we say “it is exposed”) if we add attribute accessors to the class.

In the same way classes sometimes want to keep certain methods private: methods that aren’t supposed to be called from outside of the object. Only the object itself is supposed to use them internally, from other methods.

Imagine I am an instance of a class ItalianRestaurant, and I have a method pizza, which is supposed to return an instance of the class Pizza.

When you approach me, and call the method pizza (i.e. ask me to bring a pizza) then I’ll know what to do, and how to do it. I’ll get some prepared pizza dough from somewhere, some tomato sauce, vegetables and other stuff from somewhere else, prepare the pizza, bake it, put it on a nice plate, and finally give (return) it to you.

However, you don’t really care about any of these details. You are hungry, and just want the pizza. All the exact steps involved are something that I keep private to me, and maybe they’ve been our family’s best kept secret for generations.

This is pretty much how objects work, too. The Italian restaurant object exposes some stuff to the outer world (you), and keeps other things private. They’ll let you order a pizza, and other things. But they won’t tell you the exact ingredients of their tomato sauce, or how they manage to make this damn great pizza dough.

In our Person example it makes sense to make the method encrypt private.

Currently, if you run the following code it will execute just fine, even though it makes little sense:

person = Person.new("Ada")
p person.encrypt("some other secret")

Why would a person encrypt some arbitrary string for someone else, and return it? This is something that the person object should keep private. The restaurant wouldn’t turn flour, water, olive oil and other ingredients into pizza dough for everyone else either.

We can make the method encrypt private like so:

module Encryption
  private

  def encrypt(string)
    Digest::SHA2.hexdigest(string)
  end
end

The keyword private tells Ruby that all methods defined from now on, are supposed to be private. They can be called from within the object (from other methods that the class defines), but not from outside.

If you now try to call the method it will raise an error:

person = Person.new("Ada")
p person.encrypt("super secret")

This will print the error message:

private method `encrypt' called for #<Person:0x007fa179863770 @name="Ada">

Nice. Does this make sense?

Procs

TBD

Yield

TBD

Regular Expressions

Some people, when confronted with a problem, think “I know, I’ll use regular expressions.”
Now they have two problems.

That’s a pretty famous joke, and it refers to the fact that regular expressions can be quite a pain to figure out.

However, once you know some basics about them, they’re also extremely powerful, and you can do amazing things with them, not only in Ruby, but also, for example, in your editor, and command line tools.

Regular expressions are sort of a swiss army knife for finding things in strings (text), extracting parts of them, or mass replacing certain bits with something else.

E.g. you could do:

Regular expressions are a language to describe patterns of text. Wikipedia says: a sequence of characters that define a search pattern.

For example the pattern [0-9]+! means: There needs to be at least one digit, and it needs to be followed by an exclamation mark. The pattern ([\w]+)-([\d]+)\.mpeg

Does this stuff look scary and cryptic? You bet. That’s why regular expressions have kind of a strange reputation in programming. They’re super powerful, but they’re also kind of a pain: Like black magic, this power comes at a price.

The main reason why the language that is defined as regular expressions is so hard to read is that it dates back as far as 1956, and their first implementations in programming came up in the late 1960s. Back then every single character of your code was kinda worth its weight in gold. Memory was extremely limited, and code had to be as terse as possible.

Now, the most commonly used features of this language are the following:

String literals

Let’s walk through some examples, to make this more practical. Let’s say we have the following text:

text = "A regular expression is a sequence of characters that define a search pattern."

… and we are interested to know if it contains the words character and sentence. In Ruby, we could use a regular expression like so:

matches = text.match(/character/)
p matches

This will return an instance of the class MatchData. Whereas, when we look for sentence we’ll get nil:

matches = text.match(/sentence/)
p matches

Note how in Ruby one can define a regular expression by enclosing it with slashes /. There are other ways to define regular expressions, too, but this is the most common one.

But that’s kinda boring, right? We could just use the method include? for strings, which lets us figure out the same thing. Let’s spice this up a little.

Anchors (boundaries)

The most commonly used anchors are: Beginning or end of the string, beginning or end of a line, beginning or end of a word.

For example:

text = "A regular expression is a sequence of characters that define a search pattern."

puts 'Found "A" at the beginning of the string.' if text.match(/^A/)
puts 'Found "O" at the beginning of the string.' if text.match(/^O/)

puts 'Found the string "character".' if text.match(/character/)
puts 'Found the word "character".' if text.match(/character\b/)

This will output:

Found "A" at the beginning of the string.
Found the string "character".

So it finds the string “character”, but not the word “character”. This is because the regular expression /character\b/ requires a word boundary to be found after the string literal (i.e. the literal piece of text) “character”. Since in our example the text “character” is followed by another “s”, the regular expression won’t match.

Character classes

Let’s say we want to find all the words that start with a vowel. For that we can use a character class, i.e. a set of allowed characters. Again, we use the anchor word boundary \b, this time to express that the vowel needs to be at the beginning of the word.

While the method match returns an object (i.e. something “truthy”) when the pattern matches (and nil when it doesn’t), the method scan returns an array with all the occurances of text that match the pattern.

So let’s use it:

text = "A regular expression is a sequence of characters that define a search pattern."

p text.scan(/\b[aeiou][a-z]*\b/)

This will output:

["expression", "is", "a", "of", "a"]

Our regular expression defines that we’re looking for a piece of text that

We’ll explain the star * quantifier in a bit.

Notice something though?

Regular expressions are case sensitive. I.e. our piece of code did not match the word “A” in the beginning of the string. In order to fix that we need to allow uppercase letters as well:

p text.scan(/\b[AEIOUaeiou][a-z]*\b/)

Our output will include the capital “A” at the beginning of the string as well:

["A", "expression", "is", "a", "of", "a"]

This example also demostrates the difference between a word boundary and whitespace. A single space would count as whitespace, and we could use it to match our words, too. However, that would not work at the beginning and end of a string. And it would not work when our word is followed by punctuation, such as a comma or fullstop. The word boundary \b allows all of these, too.

So, what about the star * in the expression above?

Quantifiers

This is a quantifier. It means “allow the stuff defined before zero, or any number of times”.

In our case it means that we’re looking for a single vowel, followed by either nothing, or one or many characters between “a” and “z”. This means we match both the words “A” and “a” (not followed by anything before the word boundary), as well as the words “is”, “of”, and “expression” (which are followed by one or many characters).

Does that make sense?

Let’s say we want to omit single character words, but we do want to allow all words longer than one character. For that we could change the “none, one, or many” quantifier * to another quantifier + meaning “at least one, or many”:

p text.scan(/\b[AEIOUaeiou][a-z]+\b/)

This won’t match the words “A” and “a”, and instead output the following:

["expression", "is", "of"]

What if we are looking for words that start with a vowel, and are no more than 2 characters long? We could use the quantifier ? which means “none, or exactly one”:

p text.scan(/\b[AEIOUaeiou][a-z]?\b/)

This will output:

["A", "is", "a", "of", "a"]

If we remove the quantifier entirely, then the regular expression will look for a word that starts with a vowel, followed by exactly one character:

p text.scan(/\b[AEIOUaeiou][a-z]\b/)
["is", "of"]

Captures

Using the method scan with regular expressions like this is quite useful in many situations. But sometimes, we need something more powerful.

Imagine we need to find all words that are followed by a word that starts with a vowel.

Let’s try using scan for that:

p text.scan(/\b[A-Za-z]+\b +\b[AEIOUaeiou][a-z]*\b/)

The second part of this regular expression is just the same as above: Any word that starts with a vowel, and that is one or many characters long.

Can you figure out the first part?

It also says: Match something that starts at a word boundary, then has one or many characters between “A” and “Z” or “a” and “z” (that bit is new: you can combine ranges as character classes), and that is followed by at least one space.

If you run this you’ll get the following output:

["regular expression", "is a", "sequence of", "define a"]

Looks alright, doesn’t it?

However, we were only interested in words that are immediately followed by a word starting with a vowel. Our strings contain two words.

So either we’d have to work on these strings more (e.g. use split to split off the second word). Or there’s a smarter way of doing the same.

Enter captures.

In regular expressions one can “mark” certain parts of a patterns, saying: “Give me the bits that match this stuff here”. In order to mark a part of the pattern to be captured you’d enclose it with parenthese, like so:

/\b([A-Za-z]+)\b +\b[AEIOUaeiou][a-z]*\b/

Note how we’ve enclosed the first part of the pattern with parentheses. This means “match the full pattern, but only capture the parts that we’ve marked as interesting”.

p text.scan(/\b([A-Za-z]+)\b +\b[AEIOUaeiou][a-z]*\b/)

This returns a nested array like this:

[["regular"], ["is"], ["sequence"], ["define"]]

Awesome! We get all the words that we were interested in.

But why is this a nested array? The method scan looks for each bit of text that matches the given pattern (regular expression). It then extracts all the “marked” (captured) parts from it, and keeps these as an array. As there can be many occurances that match the pattern, and each of them can have many captures, we get back a nested array.

Let’s capture the second word (starting with a vowel) as well to demonstrate this:

p text.scan(/\b([A-Za-z]+)\b +\b([AEIOUaeiou][a-z]*)\b/)

This will return:

[["regular", "expression"], ["is", "a"], ["sequence", "of"], ["define", "a"]]

More on character classes

So far we have used character classes like [aeiou] (listing all allowed characters literally), and [a-z] (specifying a range of characters).

There’s more to these.

One can negate classes by prepending a “not” character ^ inside the square brackets. E.g. [^AEIOUaeiou] allows every character that is not a vowel. So we can find all words that do not start with a vowel like so:

p text.scan(/\b[^AEIOUaeiou ][^ ]*\b/)

This means: Start at a word boundary, and allow everything that is not a vowel or a space as a first character, when it is optionally followed by one or many characters that are not a space, followed by a word boundary.

This will output:

["regular", "sequence", "characters", "that", "define", "search", "pattern"]

Also, regular expressions come with “baked-in”, predefined classes. For example \d means “any digit”. Here’s a list of common classes:

That means we could refine our expression from above:

/\b[A-Za-z]+\b +\b[AEIOUaeiou][a-z]*\b/

Like so:

/\b\w+\b +\b[AEIOUaeiou]\w*\b/

This might yield slightly different results if we have words that contained dashes or underscores, but it is same in our case:

["regular expression", "is a", "sequence of", "define a"]

One can also combine these predefined classes with each other, and literal charachters. For example [\w!?]+ would find a sequence of at one or many characters that is a word character, an exclamation or a question mark.

Anything

Finally, there’s one special character that matches anything: the dot ..

I.e. the regular expression .* matches “any character, zero, or any number of times”. This may be useful if you are looking, for example, for whatever text is enclosed in parentheses:

text = "Regular expressions are powerful (and sometimes confusing, even to experienced developers)."
p text.scan(/\(.*\)/)

Notice the backslashes before the opening and closing parentheses? We want to match these literal characters, and not use them with their special meaning of capturing their content here. Therefore we need to escape them to tell Ruby: Yep, we really mean a parenthesis here.

By the way this will output the following:

["(and sometimes confusing, even to experienced developers)"]

Whoops. Maybe we actually also do want to capture a part or this, and omit the actual parentheses from the result. We can do that by placing an extra pair of un-escaped (capturing) parentheses inside the escaped (literal) ones:

p text.scan(/\((.*)\)/)

And now we’ll get this result, which has the parentheses stripped off:

[["and sometimes confusing, even to experienced developers"]]

Rubular

Confused? Don’t worry. We all are.

Try to remember some of the most basic, simple stuff. Then try using it, maybe in your text editor, when you search for a certain phrase. Over time you’ll remember a few more things, bit by bit, and things will become a little less confusing. Writing a long, complicated regular expression, that actually works, without thinking, trying, and re-trying a lot is something that only few developers actually can do - and the author of this book isn’t one of them.

If you cannot figure out a certain regular expression, or if you want to experiment with something then Rubular is a great tool for that. Enter some text to the “test string” text area, and then start writing a regular expression, one bit after another. The app will display the parts that match, and your captures if you define some.

Exercises (old)

These exercises are an outdated set of exercises that need to be ported and adjusted in order to reflect the current order of topics in our book.

Many of them at the moment assume things early on that only are explained later in the book.

Working with Numbers

In order to start irb open your terminal and type irb, then hit the return key (enter). In order to quit irb again (and get back to your system shell prompt) you can type exit or press ctrl-d, which does the same.

Exercise 1.1

In irb, calculate:

Exercise 1.2

What do you think happens when you combine the following floats and integers?

Try computing these in irb:

Is the result a float or an integer?

Exercise 1.3

Methods are a way of “doing something with an object”. E.g. in Ruby, numbers have two methods that allow you to check whether the number is odd or even.

Look through the documentation for integer numbers (called Fixnum) and find the methods that tell if a number is odd or even.

Exercise 1.4

In irb, use these methods to find out if certain numbers are odd or even. Numbers like 0, 1, 2, 99, -502 etc.

You can use a method by appending a dot . and then the method name to the object. E.g. -99.abs uses (we also say: “calls”) the method abs on the number -99.

Try for yourself what it does, and google for “ruby abs” to find the documentation for this method.

Working with Strings

In order to start irb open your terminal and type irb, then hit the return key (enter). In order to quit irb again (and get back to your system shell prompt) you can type exit or press ctrl-d, which does the same.

Exercise 2.1

What do you think this will do?

$ irb
> "hello".length + "world".length

Try it yourself.

Exercise 2.3

Skim through the documentation for strings in the Ruby documentation, and look for a method that prepends one string to another string.

Using that method prepend the string "Learning " to the string "Ruby"

Show solution

Exercise 2.4

Skim through the documentation for strings in the Ruby documentation, and look for a method that removes characters from a string.

Using that method turn the string "Learning Ruby" into the string "Lrnng Rb".

Show solution

Exercise 2.5

Find out how to convert the string "1.23" into the number 1.23.

You can either, again, skim the documentation page for strings, or google for “ruby convert string to number”.

Then also find out what method can be used to turn the string "1" into the number 1 (remember floats and integers are different kinds of numbers).

Confirm that you have found the right methods by trying them in irb.

Show solution

Exercise 2.6

There is a method that allows to justify a string, and padding it with another string.

Find that method and use it on the string "Ruby" together with "<3" so that you get the following string back:

"Ruby<3<3<3"

We’ll admit that this is a rather creative usage of this method. Normally you’d use it to align strings to columns (e.g. so that they line up nicely when you format a table). You’ll use this method in other exercises later on.

Show solution

Working with Arrays (1)

Before you get started, make sure you have your text editor and terminal open, and you have navigated to your exercises directory in the terminal. E.g. cd ~/ruby-for-beginners/exercises.

Exercise 3.1

Create a new, empty file. Save it as arrays_1-1.rb. Fill in the following line:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# your code goes here

So that, when you run your code (run ruby arrays_1-1.rb), you get the following output:

5

Show solution

Exercise 3.2

Copy your file to a new file: cp arrays_1-1.rb arrays_1-2.rb, then open this new file.

Add another line before the line that you just added, so that, when you run your code, you get the following output:

99

Show solution

Exercise 3.3

Make a new file arrays_1-3.rb, and fill in the following line:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# your code goes here
p numbers

So that you get the following output:

[2, 4, 6, 8, 10]

Read the documentation for the method select that you can use on arrays on the Ruby documentation

Show solution

Exercise 3.4

Again, copy your last file to a new file: cp arrays_1-3.rb arrays_1-4.rb, then open this new file.

Now change the code that you just added so that you get the following output:

[10, 8, 6, 4, 2]

The method select that you used in the last exercise returns an array. On this array (the return value) you can use another method, by, again, just appending a dot . and the method name to it, i.e., to the end of the line.

There is another method that reverses the order of the array. You can find it by googling for “ruby array reverse”.

Show solution

Exercise 3.5

Again, copy your last file to a new file: cp arrays_1-4.rb arrays_1-5.rb, then open this new file.

Now change your code so that you get the following output:

[10, 8, 4, 2]

Bonus: Find at least three different solutions for this last change.

Show solution

Working with Hashes (1)

Before you get started, make sure you have your text editor and terminal open, and you have navigated to your exercises directory in the terminal. E.g. cd ~/ruby-for-beginners/exercises.

Exercise 4.1

Make a new file hashes_1-1.rb, and fill in the following line:

dictionary = { :one => 'uno', :two => 'dos', :three => 'tres' }
# your code goes here

So that it prints out dos.

Show solution

Exercise 4.2

Make a new file hashes_1-2.rb, and fill in the following line:

dictionary = { :one => 'uno', :two => 'dos', :three => 'tres' }
# your code goes here
puts dictionary[:four]

So that it prints out cuatro.

Show solution

Exercise 4.3

Copy that file to a new file cp hashes_1-2.rb hashes_1-3.rb, and change your code so that it prints out the following.

Cuatro

There’s a method that upcases the first letter of a string. Find it by googling for “ruby string upcase first letter”.

Show solution

Exercise 4.4

There is a method on hashes that allows to check if a certain key is defined on the hash. Find that method by googling for “ruby hash key defined”.

Try this method in irb by creating a hash like the one above, calling the method and passing keys like :one, :two, :four, and :ten.

Show solution

Exercise 4.5

There is a method on hashes that flips keys and values. Find that method on the Ruby documentation about hashes

Make a new file hashes_1-5.rb, and fill in the following line using that method:

dictionary = { :one => 'uno', :two => 'dos', :three => 'tres' }
# your code goes here

This should then output:

{ 'uno' => :one, 'dos' => :two, 'tres' => :three }

Show solution

Defining methods

Exercise 5.1

Write a method greet that takes a name, prepends "Hello ", and appends an exclamation mark "!":

def greet(name)
  # your code goes here
end

puts greet("Ada")

This should print out Hello Ada!.

Show solution

Exercise 5.2

Once you’ve implemented the method this should print out: Hello Ada!.

Now change your method so that instead of always using "Hello " it picks a random string from the array ["Hello", "Hi", "Ohai", "ZOMG"].

Every time you run the program it should print out either "Hello Ada!", "Hi Ada!", "Ohai Ada!", or "ZOMG Ada!".

The method shuffle on arrays does, well, shuffle the array :) That means it changes the order of the elements in the array in a random way.

Show solution

Exercise 5.3

Write a method that converts a distance (a number) from miles to kilometers:

def miles_to_kilometers(miles)
  # your code goes here
end

puts miles_to_kilometers(25)

This should print out:

40.2336

Show solution

Exercise 5.4

Write a method leap_year? that takes a year (a number), and calculates if it is a leap year.

def leap_year?(year)
  # your code goes here
end

p leap_year?(2012)
p leap_year?(2015)

This should print out:

true
false

Hint: The operator % returns the rest of a division. E.g. 14 % 3 returns 2.

Bonus: Also make it so that the method returns true for the year 2000 and false for 1900 … because that’s really the definition of leap years.

Show solution

Working with Arrays (2)

Note: At the moment these exercises require reading up until “Block return values”. You should know how to use the method collect on arrays.

Before you get started, make sure you have your text editor and terminal open, and you have navigated to your exercises directory in the terminal. E.g. cd ~/ruby-for-beginners/exercises.

Exercise 6.1

Create a new, empty file. Save it as arrays_2-1.rb. Fill in the following line:

words = ["one", "two", "three", "four", "five"]
# your code goes here
p words

So that you get the following output:

["one", "three", "five"]

Show solution

Exercise 6.2

Copy your file to a new file: cp arrays_2-1.rb arrays_2-2.rb, then open this new file.

Now change your code so that you get the following output:

["One", "Three", "Five"]

Google for ruby string uppercase first letter.

Show solution

Exercise 6.3

Copy your file to a new file: cp arrays_2-2.rb arrays_2-3.rb, then open this new file.

Now change your code so that you get the following output:

["One <3", "Three <3", "Five <3"]

Use string interpolation for this.

Show solution

Exercise 6.4

Copy your file to a new file: cp arrays_2-3.rb arrays_2-4.rb, then open this new file.

Now change your code so that you get the following output:

["One <3", "Three <3<3<3", "Five <3<3<3<3<3"]

Show solution

Exercise 6.5

Copy your file to a new file: cp arrays_2-4.rb arrays_2-5.rb, then open this new file.

Now change your code so that you get the following output (hint: again, that’s now a string, not an array):

One <3, Three <3<3<3, Five <3<3<3<3<3

Show solution

Exercise 6.6

Copy your file to a new file: cp arrays_2-5.rb arrays_2-6.rb, then open this new file.

Now change your code so that you get the following output, using the newline character "\n":

One <3
Three <3<3<3
Five <3<3<3<3<3

Show solution

Exercise 6.7

Copy your file to a new file: cp arrays_2-6.rb arrays_2-7.rb, then open this new file.

Now change your code so that you get the following output, aligning the second column:

One   <3
Three <3<3<3
Five  <3<3<3<3<3

As you may guess, strings have a method that is helpful for this. Ask Google: “ruby string align”.

Show solution

Working with Nested Arrays

Note: At the moment these exercises require reading up until “Block return values”. You should know how to use the method collect on arrays.

Before you get started, make sure you have your text editor and terminal open, and you have navigated to your exercises directory in the terminal. E.g. cd ~/ruby-for-beginners/exercises.

Exercise 7.1

Make a new file nested_arrays-1.rb, and fill in the following line:

numbers = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]
# your code goes here
p sums

So that you get the following output:

[6, 15, 24]

Show solution

Exercise 7.2

Make a new file nested_arrays-2.rb, and fill in the following line:

Fill in the following line

numbers = [
  [1, 2, 3],
  [2, 2, 2],
  [3, 2, 1]
]
# your code goes here
lines.each { |line| puts line }

So that you get the following output:

* ** ***
** ** **
*** ** *

Show solution

Working with Hashes (2)

Exercise 8.1

Make a new file hashes_2-1.rb, and dd the following lines:

languages = {
  :de => 'German',
  :en => 'English',
  :es => 'Spanish',
}
dictionary = {
  :de => { :one => 'eins', :two => 'zwei', :three => 'drei' },
  :en => { :one => 'one', :two => 'two', :three => 'three' },
  :es => { :one => 'uno', :two => 'dos', :three => 'tres' }
}

Now, at the end of the file, add code that prints out the following:

In German, eins means one, zwei means two, drei means three.
In Spanish, uno means one, duo means two, tres means three.

Show solution

Exercise 8.2

Now, in a new file hashes_2-2.rb, with the same hashes from above, add code that prints out the following table:

de eins zwei drei
en one two three
es uno dos tres

Show solution

Exercise 8.3

Copy your file to a new file cp hashes_2-2.rb hashes_2-3.rb and change your code so that it aligns the table columns:

de eins zwei drei
en one  two  three
es uno  dos  tres

Show solution

Exercise 8.4

Copy your file to a new file cp hashes_2-3.rb hashes_2-4.rb and change your code so that it adds delimiters:

| de | eins | zwei | drei  |
| en | one  | two  | three |
| es | uno  | dos  | tres  |

Show solution

Truthiness

Exercise 9.1

Make a new file truthiness-1.rb, and add the following lines:

This exercise is about validating what we’ve learned about truthiness.

You have the following array:

objects = [true, false, 0, 1, "", [], Object.new, Class.new, Module.new]

Add some code that outputs the following table. The last column should be filled in with by either true or false depending what the operation !!object, which is the same asnot not object` for each of the objects returns:

object                     | !!object
true                       | [true|false]
false                      | [true|false]
nil                        | [true|false]
0                          | [true|false]
1                          | [true|false]
""                         | [true|false]
[]                         | [true|false]
#<Object:0x007fb3dc0ea1b8> | [true|false]
#<Class:0x007fb3dc0e2cd8>  | [true|false]
#<Module:0x007fb3dc0d9ea8> | [true|false]

You can use the method inspect in order to, for each of the values, get a representation that looks like the code.

Of course you will get different object ids for the object, class, and module instances everytime you run your code.

So let’s prettify this table by removing the object ids. You can do this calling sub(/:.*>/, ">") on whatever inspect returns.

Your table should now look like this:

object    | !!object
true      | true
false     | false
nil       | false
0         | true
1         | true
""        | true
[]        | true
#<Object> | true
#<Class>  | true
#<Module> | true

Show solution

Bonus: Exercise 9.2

Copy your file to a new file truthiness-2.rb, and change your code so that it outputs the following table. Fill each cell with the result that == returns for each combination.

          | true      | false      | 0          | 1          | ""         | []         | #<Object> | #<Class>  | #<Module>
true      |           |            |            |            |            |            |           |           |
false     |           |            |            |            |            |            |           |           |
0         |           |            |            |            |            |            |           |           |
1         |           |            |            |            |            |            |           |           |
""        |           |            |            |            |            |            |           |           |
[]        |           |            |            |            |            |            |           |           |
#<Object> |           |            |            |            |            |            |           |           |
#<Class>  |           |            |            |            |            |            |           |           |
#<Module> |           |            |            |            |            |            |           |           |

Tip: Break this up in sub-tasks:

  1. Write some code that collects an array of arrays containing all rows: An array rows that has many arrays, each of which holds 9 results (cells).
  2. Add the value’s representation to the beginning to the row. If you don’t know how, google for “ruby array add to beginning”
  3. Make sure each of the cells is 9 characters wide.
  4. Join each of the row with the string " | ".
  5. Add the table headers row.
  6. Join all rows with the string "\n" (newline), and output the result.

Show solution

The Email Class

Exercise 10.1

In a new file email_1.rb write a class Email that has a subject, date, and from attribute. Make it so that these attributes can be populated through new and initialize.

The following code

class Email
  # fill in this class body
end

email = Email.new("Homework this week", "2014-12-01", "Ferdous")

puts "Date:    #{email.date}"
puts "From:    #{email.from}"
puts "Subject: #{email.subject}"

should then output the following:

Date:    2014-12-01
From:    Ferdous
Subject: Homework this week

Show solution

Exercise 10.2

Once you have this class, copy your file to email_2.rb.

Change your class so that the initialize method now takes a subject string, and a headers hash. This is then more in line with how actual emails are stored in the real world: the values date and from are stored on a hash, which is called the “email headers”.

Doing so, in the code above the only line you should change is the one that instantiates the email object, which should now read:

email = Email.new("Keep on coding! :)", { :date => "2014-12-01", :from => "Ferdous" })

Your program should now still produce the same output.

Show solution

The Mailbox Class

Exercise 11.1

In a new file mailbox-1.rb Write a class that has a name and emails attribute. Make it so that the these attributes can be populated through the initialize method (name being a string, and emails being an array of Email instances).

The following code

class Email
  # your class from the last exercise
end

class Mailbox
  # fill in this class body
end

emails = [
  Email.new("Homework this week", { :date => "2014-12-01", :from => "Ferdous" }),
  Email.new("Keep on coding! :)", { :date => "2014-12-01", :from => "Dajana" }),
  Email.new("Re: Homework this week", { :date => "2014-12-02", :from => "Ariane" })
]
mailbox = Mailbox.new("Ruby Study Group", emails)

mailbox.emails.each do |email|
  puts "Date:    #{email.date}"
  puts "From:    #{email.from}"
  puts "Subject: #{email.subject}"
  puts
end

should then output the following:

Date:    2014-12-01
From:    Ferdous
Subject: Homework this week

Date:    2014-12-01
From:    Dajana
Subject: Keep on coding! :)

Date:    2014-12-02
From:    Arianne
Subject: Re: Homework this week

Show solution

The Mailbox Text Formatter

The mailbox text formatter exercise is a milestone in the beginners group curriculum, and it may take a little bit longer to complete it. That is fine, and, to some extent, the point :)

Exercise 12.1

Make a new file mailbox_text-1.rb. Fill in and complete the following class definitions:

class Email
  # your class from the last exercise
end

class Mailbox
  # your class from the last exercise
end

class MailboxTextFormatter
  # fill in this class body
end

emails = [
  Email.new("Homework this week", { :date => "2014-12-01", :from => "Ferdous" }),
  Email.new("Keep on coding! :)", { :date => "2014-12-01", :from => "Dajana" }),
  Email.new("Re: Homework this week", { :date => "2014-12-02", :from => "Ariane" })
]
mailbox = Mailbox.new("Ruby Study Group", emails)
formatter = MailboxTextFormatter.new(mailbox)

puts formatter.format

Your goal is to complete the code in a way so it outputs the following:

Mailbox: Ruby Study Group

+------------+---------+------------------------+
| Date       | From    | Subject                |
+------------+---------+------------------------+
| 2014-12-01 | Ferdous | Homework this week     |
| 2014-12-01 | Dajana  | Keep on coding! :)     |
| 2014-12-02 | Ariane  | Re: Homework this week |
+------------+---------+------------------------+

You are allowed to add as many methods to the classes Email, Mailbox and MailboxTextFormatter as you deem useful. In your final solution you are not allowed to change any of the code outside (after) the class definitions. For debugging purposes, you can, of course, change all the code you want :)

If you do this exercise in one of our study groups then best do it together with someone else. We found pairs to work best, and a three person team would be better than doing it on your own.

Try to come up with a working solution first. It doesn’t matter how elegant, generic, or pretty it is. Whatever produces the required output is fine for a first solution.

Then, later, look at your code, and try to improve it by cleaning up everything that you don’t like, or deam ugly.

Eventually, one goal to aim for would be: Adding another column to the table only requires mimimal changes, e.g. changes to one or two places in your formatter class.

Show solution

The Mailbox Html Formatter

Separation of concerns

One question that may have come up while working on the mailbox text formatter exercise is:

Why would we have a separate class for formatting the ASCII table (that is, a plain text table that uses characters like +, -, and |)?

The reason is: We want each one of our classes to encapsulate one concept that is useful in our application. We also say: each one of our classes should be concerned with one responsibility.

An email vaguely resembles the concept of an analog letter, written on paper: some message is being sent from one person to another. Nowadays everyone knows what an email is: it stores all information about this particular message. The same is true for mailboxes, which are used to store a bunch of emails. Formatting a number of emails in order to be displayed on a text based terminal is a very different concept, and concern.

Therefore it makes a lot of sense to have three different classes implement each one of these concepts, or concerns. And it even makes so much sense that it is called a design principle in programming: The principle of separation of concerns.

Aside from being comprehensible and mapping to concepts that we already know, one other advantage is: We can now easily implement other formatter classes that format our emails in a different way, suitable to be displayed in other media.

And that’s what this exercise is about: We want to display our mailbox contents in HTML, the format that browsers like to use. If you are unfamiliar with what HTML is, and how it looks like, you can read up on it here. This will be our first step towards learning how to build a web application.

Model, View, Controller

Before we get to that, we’d like to point out one other aspect, that you’ll remember when we get to talk about the architecture that Rails use to structure and separate concerns, called “model, view, controller”.

If this doesn’t make a whole lot of sense to you at the moment, don’t worry. You’ll understand it more once we build our first Rails application.

Exercise 13.1

Ok, now to our exercise. We will start over with the same code again, except that our formatter class now will be called MailboxHtmlFormatter.

Copy your file mailbox_text-1.rb to mailbox_html-1.rb and change it like so. Then fill in the MailboxHtmlFormatter class.

class Email
  # your class from the last exercise
end

class Mailbox
  # your class from the last exercise
end

class MailboxHtmlFormatter
  # fill in this class body
end

emails = [
  Email.new("Homework this week", { :date => "2014-12-01", :from => "Ferdous" }),
  Email.new("Keep on coding! :)", { :date => "2014-12-01", :from => "Dajana" }),
  Email.new("Re: Homework this week", { :date => "2014-12-02", :from => "Ariane" })
]
mailbox = Mailbox.new("Ruby Study Group", emails)
formatter = MailboxHtmlFormatter.new(mailbox)

puts formatter.format

Your goal is to complete the code in a way so it outputs the following:

<html>
  <head>
    <style>
      table {
        border-collapse: collapse;
      }
      td, th {
        border: 1px solid black;
        padding: 1em;
      }
    </style>
  </head>
  <body>
    <h1>Ruby Study Group</h1>
    <table>
      <thead>
        <tr>
          <th>Date</th>
          <th>From</th>
          <th>Subject</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>2014-12-01</td>
          <td>Ferdous</td>
          <td>Homework this week</td>
        </tr>
        <tr>
          <td>2014-12-01</td>
          <td>Dajana</td>
          <td>Keep on coding! :)</td>
        </tr>
        <tr>
          <td>2014-12-02</td>
          <td>Ariane</td>
          <td>Re: Homework this week</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

Does that look scary? A little bit, maybe. It’s probably fair to say that manually writing HTML isn’t very popular amongst most programmers. Therefore there are quite a few tools that make our lives easier. And your task is to write such a tool.

Also, this exercise should actually be easier for you to complete than the previous one. You already have a bunch of practice in iterating over emails, and working with arrays and strings. And this time, you don’t need to deal with the maximum length of strings per column. You can just interpolate things together.

Show solution

Storing our HTML to a File

Exercise 14.1

In this exercise our goal is to store the generated HTML for our mailbox to a file, so that we can finally view it in an actual browser.

Your objective is to write a file (using Ruby) that contains all the HTML from the last exercise.

Building on the last exercise, copy your file to a new file cp mailbox_html-1.rb mailbox_file-1.rb and change the last line:

Instead of passing the HTML to puts you should be passing it to a different method, so that running your program writes the HTML file that we are after. In order to find that method try googling for “ruby write file”. Call this file emails.html.

When you open this file in a text editor you should see the same HTML from the last exercise. When you open it in your browser it should look like this:

image

Show solution

Reading from a CSV File

So far our program has all the email data hardcoded: All the data is baked right into our code. Everytime you run it, it will display all the same emails. Obviously that’s not a very useful for a real world program.

Let’s change this to read our data from an external data source instead.

One very simple and pretty popular way to store data to files is using the format CSV. This stands for “comma separated values” (although, often times semicolons are used as a separator instead of commas), and it is something that spreadsheets can read and export. Being able to work with CSV can be pretty handy: just write a little Ruby script, and filter that data, or work with it otherwise.

The first line in the code below require "csv" makes Ruby’s CSV library available to your program so that you can then use the class CSV.

Exercise 15.1

Building on the same code from the last exercises, your objective is to read the email data from a file emails.csv. This file should be stored in the same directory as your Ruby program, and contain the following data:

Date,From,Subject
2014-12-01,Ferdous,Homework this week
2014-12-01,Dajana,Keep on coding! :)
2014-12-02,Ariane,Re: Homework this week
2014-12-11,Maria,I'm back in Berlin

You can create that file by copying the four lines from above to your editor.

In order to complete this exercise you’ll need to find out how to:

In other words, you should replace the following lines of code:

emails = [
  Email.new("Homework this week", { :from => "Ferdous", :date => "2014-12-01" }),
  Email.new("Keep on coding! :)", { :from => "Dajana", :date => "2014-12-01" }),
  Email.new("Re: Homework this week", { :from => "Ariane", :date => "2014-12-02" })
]

Once you have figured out how to read and parse the CSV file, and create an array of Email instances out of that data, your next task is to encapsulate all of that into a class EmailsCsvStore. This class should take a filename, and have a method read, which returns the emails array.

In the end that part of the code should read:

require "csv"

class Email
  # your class from the last exercise
end

class Mailbox
  # your class from the last exercise
end

class MailboxHtmlFormatter
  # your class from the last exercise
end

class EmailsCsvStore
  def initialize(filename)
    # fill in this method
  end

  def read
    # fill in this method
  end
end

store = EmailsCsvStore.new('emails.csv')
emails = store.read
mailbox = Mailbox.new("Ruby Study Group", emails)
formatter = MailboxHtmlFormatter.new(mailbox)

# your code from the last exercise, writing the file

Show solution

Exercises

If you haven’t done the try ruby course already, we recommend you do at least a couple of lessons over there too.

Whenever you sit down to do some of the exercises in this book make sure you have your text editor and terminal open. In your terminal:

Credits: The exercises 1.1, 1.2, and 2.1 are taken from Introduction to Ruby.

Working with Numbers

In order to do these exercises you should have read at least the chapter about [built_in_classes/numbers.html].

Exercise 1.1

In irb, calcluate:

To start irb open your terminal and type irb, then hit the return key (enter). To quit it (and get back to your system shell prompt) type exit or press ctrl-d.

Exercise 1.2

What do you think happens when you combine floats and integers the following in the following calculations?

Try computing these in irb:

Is the result a float or an integer?

Exercise 1.3

Try finding out what “modulo” means by asking Google.

In Ruby (and many other languages) the operator for modulo is %.

Try the following in irb:

And:

Exercise 1.4

Methods are a way of “doing something with an object”, and you’ll learn a lot more about them in a few chapters.

In Ruby, numbers have methods that allow you to check whether the number is odd or even.

Look through the documentation for integer numbers and find the methods that tell if a number is odd or even.

Look at the examples for some of the other methods on that page.

You can use a method by appending a dot . and then the method name to the object. E.g. -99.abs uses (we also say: “calls”) the method abs on the number -99.

Exercise 1.5

In irb, use these methods to find out if certain numbers are odd or even.

Try a bunch of numbers like 0, 1, 2, 99, -502 etc.

Try for yourself what it does, and google for “ruby number odd even” to find the documentation for these methods.

Show solution

Working with Strings

In order to do these exercises you should have read at least the chapter about [built_in_classes/strings.html].

Exercise 2.1

In irb try figuring out how to produce the following String: "Ruby<3<3<3".

Try using no more than two other String objects.

Show solution

To start irb open your terminal and type irb, then hit the return key (enter). To quit it (and get back to your system shell prompt) type exit or press ctrl-d.

Exercise 2.2

Look through the documentation for Strings.

Do you spot any interesting methods?

Exercise 2.3

What do you think this will do?

$ irb
> "hello".length + "world".length

Try it yourself in irb.

Show solution

Exercise 2.4

Look through the documentation for Strings, and find out how to convert the string "1.23" into the number 1.23.

If you can’t find it, google for “ruby convert string to float”.

Then also find out what method can be used to turn the string "1" into the number 1 (remember floats and integers are different kinds of numbers).

Confirm that you have found the right methods by trying them in irb.

Show solution

Working with Arrays (1)

In order to do these exercises you should have read at least the chapter about [built_in_classes/arrays.html].

Make sure you have your text editor and terminal open, and you have navigated to your exercises directory in the terminal. E.g. cd ~/ruby-for-beginners/exercises.

Exercise 3.1

In the Array [1, 2, 3, 4, 5], what’s the index of the number 4?

Show solution

Exercise 3.2

In irb, how can you ask the Array, and check if your previous answer was correct?

Show solution

Exercise 3.3

In irb, how can you ask the Array for the number of elements it contains?

Show solution

Exercise 3.1

Create a new, empty file. Save it as arrays_1-1.rb. Fill in the following line:

numbers = [1, 2, 3, 4, 5, 6]
# your code goes here

… so that, when you run your code (run ruby arrays_1-1.rb), you get the following output:

5

Show solution

Exercise 3.2

Copy your file to a new file: cp arrays_1-1.rb arrays_1-2.rb, then open this new file.

Add another line before the line that you just added, so that, when you run your code, you get the following output:

99

Show solution

Exercise 3.3

Make a new file arrays_1-3.rb, and fill in the following line:

numbers = [1, 2, 3, 4, 5, 6]
# your code goes here
p numbers

… so that you get the following output:

[2, 4, 6]

You know how to get the individual numbers. And you know that you can list things separated by comma, and enclosed with square brackets in order to get a new Array. Try combining this, and “listing” the code that gets a number from the array.

Show solution

Exercise 3.4

Again, copy your last file to a new file: cp arrays_1-3.rb arrays_1-4.rb, then open this new file.

Now add another line after the one that you just added (i.e. before you finally output the array using p).

Try to figure out how to transform your Array so you get the following output:

[6, 4, 2]

Before you do anything else, try describing the problem in English. What verb do you use to describe this transformation?

Look through the methods listed on the left side of the documentation for Arrays. to see if any of these describes what you’re looking for.

Show solution

Working with Hashes (1)

In order to do these exercises you should have read at least the chapter about [built_in_classes/hashes.html].

Make sure you have your text editor and terminal open, and you have navigated to your exercises directory in the terminal. E.g. cd ~/ruby-for-beginners/exercises.

Exercise 4.1

Make a new file hashes_1-1.rb, and fill in the following line:

dictionary = { :one => 'uno', :two => 'dos', :three => 'tres' }
# your code goes here

… so that it prints out dos.

Show solution

Exercise 4.2

Make a new file hashes_1-2.rb, and fill in the following line:

dictionary = { :one => 'uno', :two => 'dos', :three => 'tres' }
# your code goes here
puts dictionary[:four]

… so that it prints out cuatro.

Show solution

Exercise 4.3

Copy that file to a new file cp hashes_1-2.rb hashes_1-3.rb, and change your code so that it prints out the following.

Cuatro

There’s a method that upcases the first letter of a string. Find it by googling for “ruby string upcase first letter”.

Show solution

Exercise 4.4

There is a method on hashes that allows to check if a certain key is defined on the hash. Find that method by googling for “ruby hash key defined”.

Try this method in irb by creating a hash like the one above, calling the method and passing keys like :one, :two, :four, and :ten.

Show solution

Exercise 4.5

There is a method on hashes that flips keys and values. Find that method on the Ruby documentation about Hashes

Make a new file hashes_1-5.rb, and fill in the following line using that method:

dictionary = { :one => 'uno', :two => 'dos', :three => 'tres' }
# your code goes here

This should then output:

{ 'uno' => :one, 'dos' => :two, 'tres' => :three }

Show solution