Ruby is a tremendously expressive language that is also incredibly easy to get started with. In fact, it would be easy to write Ruby off as a simple language because of this, but that is just not the case. As you grow as a programmer, Ruby will grow in depth and flexibility with you; it can be as simple or as complicated as you need it to be.

7.1 | Setup

Before we getting into Ruby itself (as we will quite shortly), we'll need to make sure that it's properly installed.

7.1.1 | RVM

There are certainly other ways of installing Ruby, but the current favorite has got to be Ruby Version Manager (RVM).

Why on earth would I need to manage my version of Ruby?

There are newer versions of Ruby that are not backwards-compatible with older versions. For example, some Ruby code written and run with Ruby 1.9.3 will break when run with Ruby 1.8.7.

Why is that a problem?

Well, not everybody has the time, money, or passion to keep their Rails app completely up to date, so many people are still running Rails 2.3 applications on Ruby 1.8.7, while you might have Rails 3.2 and Ruby 1.9.3 set up on your machine. If you were to work on an application for someone with a legacy Rails project, you don't want to uninstall your version of Ruby 1.9.3 so much as you want to be able to work with Ruby 1.8.7 for this one project.

This is where RVM comes in. RVM lets you install multiple rubies, select which one you want to use, and more.

In Bash you can install RVM like so:

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

You may first have to install curl, which in Debian systems (including Ubuntu and Linux Mint) can be done with sudo apt-get install curl.

You'll also want to close the terminal you used to install RVM and then open a new one up to get everything working properly.

Also, this is an interesting Bash example to break down, but first let's see what's at that URL.

First, open up Dev Tools and switch to "Network".

Next, visit https://get.rvm.io. Notice anything funny? The URL we ended up at is not the one we entered. See the first HTTP request? It was in fact made to the URL we entered, but check out that "Status Code": 301. The response body is also empty, but if you look in the response headers, you'll see a "Location" set to the URL we eventually landed on. This is what's referred to as a redirect and is the result of the 3XX status codes, like 301. Why would anyone bother setting this up? Because 'get.rvm.io' is shorter and more awesome.

So let's try using curl now. curl is a robust tool, but in its most simple usage will pull a file down from a URL and print it to stdout (and, conveniently, it can do it over HTTP). Let's try:

$ curl https://get.rvm.io/

We'll get some kind of HTML back that tells us something like "301 Moved Permanently". Not what we wanted. Instead, we need to tell curl to follow the redirect and grab whatever it leads to. We can do this with the -L flag:

$ curl -L https://get.rvm.io/

There. Now we're looking at the same Bash script that we just saw in Chrome, but now its printed to the terminal via stdout. And you know what that means: if its sent to stdout, we can pipe it to something else.

In this case, what we ultimately want to do is just have it run, so we can just pipe it straight into bash. To have bash execute from stdin (where the text will be piped), we have to pass it the -s flag. And stable is an argument passed into the script we've downloaded, used to dictate that we want to install the stable version of RVM.

Note that though this method is incredibly handy, you don't typically want to download random text from the Internet and execute it. Someone malicious could have made the file in the first place or switched the file on the server or changed the redirect (in this case) or any number of awful things. Don't live in fear of this, but be cautious. Projects like RVM and Heroku use this method as a way to let users install their tools and users know they can be trusted. They also use https for the URL's they provide for these scripts, which provides an extra layer of trustworthiness.

If you're using gnome-terminal or mate-terminal, you'll also need to adjust your settings as described here.

Close out of the terminal you used to install RVM, open a new one, and you'll find that you now have access to rvm in the shell. And now that you have rvm installed, you can install rubies.

This is to say that you can install different Ruby interpreters. As a scripting language, Ruby is executed as plaintext by way of being run through an interpreter. This is in contrast to compiled languages that first need to be run through a compiler to convert them into a binary format that can then be executed.

Let's install the most current stable version, Ruby 1.9.3:

$ rvm install 1.9.3
...

You'll end up with ruby-1.9.3-pXXX where the X's are filled in with digits to specify the exact version of 1.9.3 you installed.

After everything is downloaded, compiled, and installed, we'll have to tell rvm what version of Ruby we want to use by default. Then we can finally check what version of ruby we have.

$ rvm use 1.9.3 --default
Using /home/brad/.rvm/gems/ruby-1.9.3-pXXX
$ ruby --version
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]

Looks good. Furthermore, this acts just the same as if we had installed ruby in a more conventional manner, but we can see the truth with the which command:

which - returns the pathnames of the files (or links) which would be executed in the current environment, had its arguments been given as commands

It shows us where programs live.

$ which ruby
/home/brad/.rvm/rubies/ruby-1.9.3-p194/bin/ruby

There's RVM at work.

Okay, so even though we won't be needing to switch versions of Ruby, you can do so by passing use as an argument in place of install as seen above. So if we also had Ruby 1.8.7 installed through RVM, we could switch to it with:

$ rvm use 1.8.7
Using /home/brad/.rvm/gems/ruby-1.8.7-p358

And then back to Ruby 1.9.3 with:

$ rvm use 1.9.3
Using /home/brad/.rvm/gems/ruby-1.9.3-p194

We're really just interested in RVM as a convenient way of installing Ruby 1.9.3, but it's capable of much more, so keep it in mind if you find yourself needing to manage different rubies or gemsets.

What's a Gem?

7.1.2 | Gems

In the Ruby community, Gems are libraries or entire programs that other developers have written (mostly in Ruby) and packaged in such a way that we can easily install them on our own systems. In Bash, the gem command accomplishes this for us and even allows us to specify what version of the gem we wish to use.

As an example let's take some time to install Rails.

And boy will it take some time.

You may actually have Rails installed on your system already, but this will get us all on the same page.

gem calls take the form $ gem [command] [arguments].

$ gem install rails -v 3.2.8

gem install rails is pretty straightforward. We also specify that we specifically want version 3.2.8 by passing that value in after a -v flag (for "version").

Feel free to continue reading while that command runs in the terminal. And don't worry if it prints some errors for the documentation.

It certainly did for me.

And, before we continue, it should be noted that this book was originally written when 3.2.8 was the current version of Rails. Since then, this release of Rails has been found to contain several critical security vulnerabilities. Because of this, if you intend to actually run your Rails app in production, please be sure to use version 3.2.14 or later. If, however, you're simply writing a Rails app on your own machine to learn Rails, version 3.2.8 will be just fine. (Just don't forget to update if you do deploy!) Okay, back to it!

Once that $ gem install rails ... is done, you can ensure that Rails is properly installed on your system with which:

$ which rails
/home/brad/.rvm/gems/ruby-1.9.3-p194/bin/rails

Now we're in business.

We can also see all the gems starting with rails using gem list:

$ gem list rails

*** LOCAL GEMS ***

rails (3.2.8, 3.2.6, 3.2.5, 3.2.3, 3.2.2, 3.2.1, 3.2.0, 3.1.0, 3.0.9, 3.0.7)

As you can see, rails 3.2.8 is not the only version I have installed on my system.

We'll come back to rails later, but for now all we need to understand is that gem can be used to download and install Ruby Gems to our system.

7.1.3 | ruby

Though we won't be needing to run any Ruby directly like this to work with Rails, it is worth noting that you can execute a file containing Ruby with ruby from the terminal, like this:

$ echo >program.rb "puts 'hey world'"
$ ruby program.rb
hey world

Notice here that the conventional file extension for Ruby it .rb, because we will be seeing this throughout our Rails app.

You can also have ruby interpret a string as Ruby if you use the -e flag:

$ ruby -e "puts 'hey world'"
hey world

That's great, but what is that puts?

Glad you asked, because we're finally going to start playing with some Ruby.

7.1.4 | IRB

An incredibly useful tool for learning Ruby is IRB, which stands for "Interactive Ruby Shell".

Fire it up with irb from the terminal:

$ irb
irb(main):001:0> puts 'hey world'
hey world
=> nil

# we can exit an IRB session by pressing
# ^D (Ctrl-d) or by running `exit`
irb(main):002:0> exit
$ 

And from here on out, the IRB prompt will be represented in this book simply with >.

The first line shows us starting irb from a Bash prompt, then the second line shows the irb prompt. Here we typed puts 'hey world', hit ENTER, and were presented with two more lines: the value that puts prints and the value puts returns.

As you might have guessed, puts will print the arguments passed to it. We can see here that it also returns nil.

What is nil?

Great question. Let's start looking at Ruby itself and work towards answering that.

7.2 | Ruby Syntax

To keep from being boring and repeating a bunch of basic programming explanations that can already be found in the chapter on JavaScript, this section assumes that you have read that chapter or have a functional understanding of a scripting language (e.g. JavaScript) as you read through this section.

Speaking of, Ruby is a scripting language and is dynamically/duck typed, just like JavaScript, so you'll be right at home!

"When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck." - William Whitcomb Riley

And remember: we'll be taking a pretty thorough look at Ruby here, but we'll only need a portion of it to work with Rails in the coming chapters. So read through and aim for a general understanding.

It is also highly recommended that you play around with the examples in IRB now and check out the Ruby books listed in the resources later.

Let's do this

The best place to start seems to be the simple line of Ruby that we've already seen:

puts 'hey world'

This line calls the method puts and passes it 'hey world' as the one and only argument. Like we just noted, puts then prints the argument (to stdout actually) and returns nil.

One important thing to notice about puts though is that it will place a newline after each argument. Let's see this in irb:

> puts 'foo', 'bar'
foo
bar
=> nil

If you don't want the newlines added, you can use print instead:

> print 'foo', 'bar'
foobar=> nil

But perhaps the most striking thing about the lines above is that we see no () surrounding the arguments. Though Ruby parens can be used to wrap the arguments during method calls, they are not syntactically required.

> print 'foo', 'bar'
foobar=> nil
> print('foo', 'bar')
foobar=> nil

We can even call a method without any arguments this way:

> puts

=> nil
> puts()

=> nil

A bit contrived, yes, but you can see that when puts is called without arguments it simply prints a newline, regardless of whether or not we use ()'s.

So what is "right" here?

Well, there are cases where the parens will be syntactically required to accomplish what we're trying to do, but in cases like the one above, it's really up to you. Calling methods and not using parens when no arguments are passed can be ambiguous at times though, so be cognizant of those who will have to read your code (and your future self).

So moving along, in the original example of puts 'hey world', we see a string literal: 'hey world'.

But we also see from the => "Brad Chase" return after the variable assignment, double quotes are used for strings too.

Is there a difference?

For the text in the above example: no. Overall: yes.

There are caveats, but one rule will hold true: single quotes are for literal text only.

This implies that double quotes have some superpowers. They do.

First, let's talk about string concatenation.

To save space below, the returns from the lines are displayed as Ruby comments. Anything following a # until a newline is a comment and ignored by the Ruby interpreter.

Okay, concatenation:

'foo' + 'bar' # => "foobar"
"foo" + "bar" # => "foobar"

foo  = 'foo' # => "foo"
foo += 'foo' # => "foofoo"

bar  = "bar" # => "bar"
bar += "bar" # => "barbar"

Notice that we don't need to end lines with ;'s (though we can) because Ruby interprets a newline as the end of a line of code.

So, we can concatenate Ruby strings together much like we would in any other scripting language, regardless of single or double quotes.

Having seen that, let's head back to irb to observe one difference between single and double quotes:

The newlines between commands below were added for readability.

> print 'foo\n'
foo\n=> nil

> print "foo\n"
foo
=> nil

Here we see that you can only escape characters inside double quotes; single quotes treat \ as a literal character without exception.

Another difference between the two is in regards to a very helpful feature of Ruby called string interpolation. String interpolation lets us dump a value into a string literal using #{}.

An example:

> name = "Brad Chase"
=> "Brad Chase"

> "Hello, my name is " + name + "."  # the long, medieval way
=> "Hello, my name is Brad Chase."

> "Hello, my name is #{name}."       # using interpolation
=> "Hello, my name is Brad Chase."

> 'Hello, my name is #{name}.'       # interpolation doesn't work with single quotes
=> "Hello, my name is \#{name}."

So here again, we see that single quotes hold to our rule and don't treat #{} specially, instead treating all of the characters literally.

Something similar that you won't see nearly as often is the use of % to mimic sprintf to do something similar.

"%02d" % 5
=> "05"

We won't be using this in the book, but it is part of Ruby and good to know.

In Ruby, we'll also find integer values of the class Fixnum and decimal values of the class Float that both inherit from the Numeric class:

1 + 1      # => 2
2.5 + 2.5  # => 5.0

Class? Inherit?

Oh, right.

Unlike JavaScript, Ruby is a classically typed language.

If you're unfamiliar with classes, think of them for now like the "types" we saw in JavaScript until we get into the details; the class of an object explains what kind of object it is.

In fact, almost everything in Ruby is a first-class object, even literals:

1.to_s   # => "1"
"2".to_i # => 2

See how we can call methods directly on the literals?

This is possible because they're just objects, like everything else. Both methods used above cast an object to another class, to_i stands for "to integer" and to_s stands for "to string".

An object's class can be obtained by calling .class on the object:

1.class   # => Fixnum
"2".class # => String

We can even call .class on classes:

Fixnum.class # => Class
String.class # => Class

That's right: even classes are objects.

"What on earth is going on?"

Oh, right. We'll get to all the class and object stuff shortly, but right now all we need to take away is that pretty much everything in Ruby is an object. ...and by extension, everything has a class.

Okay, so going back to interpolation, we can even toss in things that aren't strings, like numbers:

"$#{99}.#{99}" # => "$99.99"
"$#{99.99}"    # => "$99.99"

And we can even put logic in #{}, like so:

"#{2 + 2}" # => "4"

Keep in mind that what's happening here is that anything inside of #{} will be run and then have .to_s called on it before being dumped into the string.

All right, now that we've thrown around terms like "class", "object", and "method", let's take a look at what these actually mean. A logical place to start would be to define a class of our own.

Classes

class Book
end

There, we just defined a totally useless, empty class named Book.

Why would we do this?

Well, to demonstrate that we can, but also to see the basic syntax of defining classes.

We can see that the keyword class is used to open up the class definition, that class names begin with a capital letter, and that the class definition is concluded with the keyword end.

Perhaps the use of capital letters in the class names seems the least significant here, but this is not just a convention, it is syntactically required.

Why?

We'll let's try using a lowercase name in irb and see how it goes:

> class foo
> end
SyntaxError: (irb):1: class/module name must be CONSTANT

Ruby constants begin with a capital letter and Ruby requires that class names be constants.

Why?

Because it does.

Up to this point we've only seen variables, which are mutable, meaning that they can have their values changed. Constants work just like variables, except that they are immutable, meaning that once they are set, their values cannot be changed.

Hence the names.

There's a caveat here for classes though, because they can be added to, but before we look into that, let's look at some constants that aren't classes.

The convention for non-class constants is to use all uppercase characters for their names.

Some examples:

PI = 3.14159265359
API_KEY_SECRET = c46d55ef9fbb88747c76bc4c1deaf841

As mentioned earlier, Ruby will treat anything with a leading capital as a constant. Traditionally, regular constants, like we saw above, are written with all uppercase characters, while class names have only an initial uppercase character or only capitals for the beginning of the words that make up the class name (e.g. ChaptersController).

Now, classes are constants, but you can open classes back up (so to speak) and define more things inside of them, like this:

# from earlier
class Book
end

class Book
  def title
    return 'A Tale of Two Cities'
  end
end

Here we open our Book class back up and define a method title that simply returns a string representing a title.

We can see that the method definition is opened with the keyword def, which is followed by the method name (title). Then we again see the keyword end, but this time it closes the method definition.

Inside the method is a single line that returns a string literal, using the return keyword.

So now that we have this Book class defined, let's instantiate it. When we instantiate a class, we create an object of that class. This resulting object is referred to as an instance of its class.

To do this, we will simply call the new method on Book and this will return a new instance of Book:

book1 = Book.new
book1.title 
# => 'A Tale of Two Cities'

You may notice that we didn't define new. Every class has a new method that can be used to instantiate it. This is a feature offered to us as a basic part of Ruby.

Score! Now we have our very own object to play with.

Attributes

There is one glaring problem with what we've done though. Any ideas?

The problem specifically is that not every book's title is going to be 'A Tale of Two Cities', but more generally the problem is that we've hard coded information where it doesn't belong.

To fix this, we'll work our way from the most laborious solution all the way down to the best practice for implementing something like this.

First of all, the title method we've defined is working in a capacity of what is commonly referred to as a "getter". The opposite of this would be a "setter". This pair will pertain to a specific attribute for an object. In our case, the attribute here is the title of the book. Together, the getter and setter for an attribute are referred to as the attribute accessors.

The setter will store a value for an attribute and a getter will return the stored value, but where should the value be stored?

The common answer for this in Ruby is what is referred to as an instance variable. An instance variable is a variable that is only available to the instance in which it is defined and is not available to any other objects of that class. Instance variables always start with an @, so we'll be using @title to store our books' titles.

Furthermore, it should be noted that instance variables can only be defined and accessed inside instance methods. Instance methods are methods defined for and called on instances of a class. title from above would be an example of an instance method.

As you might expect, there is another kind of method we can define that it not an instance method that we'll learn about later.

Until you hear otherwise though, every method we'll be defining is an instance method.

Let's give instance variables a try by starting over with Book, giving it a proper getter/setter pair for title, and instantiating it into a book1 variable again:

class Book
  # the title setter
  def title=(title)
    @title = title
  end

  # the title getter
  def title
    @title
  end
end

book1 = Book.new
book1.title # => nil

book1.title = 'A Tale of Two Cities'

book1.title # => 'A Tale of Two Cities'

It may seem kind of funny that we're using a title variable in the title instance method above, but because of the way Ruby handles scope, this isn't a problem. The Ruby book on meta-programming in the resources will explain this and then some.

This is a proper implementation for a getter and setter for a title attribute for the Book class, but one curious thing you may have noticed is that our return disappeared.

If we don't explicitly return something from a method, Ruby will just return the value returned by the last line of code in the method. Basically, having the last line of the title method as @title is exactly the same functionally as if it were instead return @title.

Another interesting thing is our use of = in title=. = is a valid character for use at the end of a method name and for just this type of situation. Notice though that in the second to last line we call this method with book1.title = and not book1.title=; Ruby knows what we meant and uses the .title= method. That said, book1.title= 'foo' would have worked just the same.

We can also see that parameters for methods are defined inside of ()'s that follow the method name, just as we saw with JavaScript function definitions.

Constructors

So while our code above works just fine, it is a bit of a pain to have to instantiate a book and then set its title. It would be nice if we could do this all inline.

Fortunately, this is easily accomplished by defining a constructor for Book. A constructor is simply a method that is run when an object is first instantiated; it can even be passed arguments.

Constructors are defined for a class in Ruby by defining a method in that class named initialize. We won't need to do anything special to let Ruby know that it's a constructor, it will just assume that.

Assuming our code from above has already been run, let's reopen Book and define a constructor:

class Book
  def initialize(title)
    @title = title
  end
end

book1 = Book.new 'War of the Worlds'
book1.title # => 'War of the Worlds'

Much better.

You'll notice that we didn't wrap the string argument we're passing to new in parens here. Remember that Ruby is okay with this, but this is probably about the extent to which you'll want to take advantage of this ability. book1 = Book.new('War of the Worlds') is probably a little more declarative and immediately understandable, but skipping the parens does that job.

I write code like this all the time, but depending on your own preference or the preferences of the people you're collaborating with, you might want to spend a few extra keystrokes to properly wrap your args.

All right, so we now have a complete solution for a class with a constructor and attribute accessors for one attribute.

Metaprogramming

Despite being complete, this is not the way that people typically define attribute accessors in Ruby.

Before the how, let's examine why this is.

What happens when we also want Book to allow for a pages attribute to store a page count?

Well, we can just open Book back up define the attribute accessors:

class Book
  def pages=(pages)
    @pages = pages.to_i
  end

  def pages
    @pages
  end
end

See the problem?

These accessors are exactly the same as our title accessors except that the attribute is pages instead of title.

The problem here is that the code is not DRY.

Sooner or later in reading about Rails, you're bound to come across the term "DRY", which stands for "Don't Repeat Yourself". We are failing to obey that rule here, if only subtlety.

So if that is the problem, then attr_accessor is the answer here.

First, let's assume that Book has never been defined and that we are starting from scratch.

We can write an equivalent version of what we had before with just the following:

class Book
  attr_accessor :title, :pages

  def initialize(title)
    @title = title
  end
end

Much cleaner.

Here attr_accessor is performing a meta-programming task, that is, it's "code that writes code". More specifically, it is code that writes attribute accessors for the attribute names we've passed in.

There are many other interesting instances of meta-programming to be found in Ruby, but this is likely the most simple.

Speaking of passing attribute names, what are the values :title and :pages?

Well, let's find out!

> :title.class
=> Symbol

Okay. What on earth is a Symbol?

Symbols are something like strings, except they are immutable (e.g. they cannot be concatenated), which makes :a as unique and unchanging as 1. Symbols always begin with a : and are used frequently for situations like this where we need to pass something to describe part of our program (here, we need something to represent the desired attributes). As we'll see later, they are also used very frequently as keys in Ruby hashes.

If symbols seem foreign at first, don't worry, I didn't understand how they were useful myself until I had been writing Ruby for a while.

We'll be getting plenty of exposure to them once we get into Rails.

As seen above, We can define symbols as literals, but we can also convert strings to symbols, and back again:

sym = :foo     # => :foo
str = sym.to_s # => "foo"
str.intern     # => :foo
str.to_sym     # => :foo

to_s called on a symbol works just as we'd expect, while intern or to_sym called on a string will turn it into a symbol.

Optional Parameters

We did come up with an equivalent implementation of our Book class, but we kind of overlooked something from earlier: we never adjusted the constructor to have a page count parameter.

While we correct this, let's make things even more interesting and say that we want pages to always return an integer, even if we don't pass a page count to this new constructor we're going to make.

To do this we can make the pages parameter for the constructor optional and assign it a default integer value.

Let's rewrite the constructor and see what this looks like:

class Book
  def initialize(title, pages=0)
    @title = title
    @pages = pages.to_i
  end
end

Book.new('Foo', 250).pages # => 250
Book.new('Foo').pages      # => 0

See the pages=0 in the parameter definition?

What this does is assign 0 to pages if no second argument is passed in. Regardless, the value of pages is assigned to @pages.

Additionally, we're also calling to_i on pages when we set @pages to make sure that whatever is passed in gets casted to an integer.

Actually, there's an even more compact way to define these instance variables with the same result:

class Book
  def initialize(title, pages=0)
    @title, @pages = title, pages.to_i
  end
end

Now that is a clean constructor.

As seen above, Ruby allows us to assign multiple variables at once if we separate the variable names and their values with commas. The variables are assigned in order, left to right, so foo, bar = 'foo', 'bar' will result in foo holding 'foo' and bar holding 'bar'.

String Methods

We've been calling to_s on pretty much everything, but what happens when we call it on an instance of Book?

Let's try!

> Book.new('A Tale of Two Cities', 450).to_s 
=> "#<Book:0x00000000c8fbe0>"

Well that isn't helpful. What do we do?

If we have something in particular we want to_s to return instead, we can simply override the useless default to_s method that Ruby made for us and define our own.

But what should it return?

Well, a logical option would be @title. Let's try it:

class Book
  def to_s
    @title
  end
end

Book.new('A Tale of Two Cities', 450).to_s # => "A Tale of Two Cities"

Perfect.

With that set up, let's look at another commonly used Ruby method that also returns a string representation of a given object: inspect.

The purpose of both to_s and inspect is to return a string that represents the object they are called on, but to_s is used to provide a string that is used to something that will (eventually) be displayed to the user, whereas inspect returns a string that is helpful to the programmer.

The default return for inspect that we would find for an instance of Book will looks something like this:

"#<Book:0x000000016c5858 @title=\"A Tale of Two Cities\", @pages=450>"

As you can see, this has the same nonsense at the beginning as the default for to_s, but it also lists all of the instance variables.

But what if we only wanted inspect to list only the attributes?

Wait, what's wrong with listing all the instance variables? Doesn't that show all of our attributes?

Yes, it does, in this case. But we might end up storing other things in instance variables that aren't attributes, things we don't want printed with inspect.

Well, we could write our own inspect method.

What do we want it to return?

The pattern we'll use for our inspect return mimics what we'll see later in Rails. For the instance of Book we just created above it would look like this:

"#<Book title: \"A Tale of Two Cities\", pages: 450>"

Let's make a first pass at achieving this result:

class Book
  def inspect
    "<#{self.class} title: #{title.inspect}, pages: #{pages}>"
  end
end

Okay, we're just dropping in our attribute values by interpolating a string, but there are still a couple of interesting notes here.

First, we see self.class used at the start of the string to create the text <#Book.

Since inspect is an instance method, self inside of it will represent the instance of Book that the method (inspect) was called on. We then call class on that self object to get back Book.

Normally, method calls like this are assumed to be made on self, which is the reason that we can call title and pages above rather than self.title and self.pages. For these, we're free to use self. before the calls, but we don't have to.

class is an exception to this though, because class is also a keyword in Ruby and if it were used here alone, Ruby would think we were starting off another class definition and would eventually blow up as a result (because we aren't defining a class and we would never properly end the "class definition" we were accidentally making). To avoid this, we must explicitly call class here as self.class.

Secondly, you'll notice that self.class (a Class) and pages (a Fixnum) are being interpolated, but neither of those values are strings. Ruby realizes this, calls to_s on each, and places the result into the string we're building.

And finally, you'll see that we're calling inspect on title even though it is a string. What?

This one is best illustrated with a quick example:

> "foo".to_s
=> "foo"

> "foo".inspect
=> "\"foo\""

> puts "foo"
foo
=> nil

> puts "foo".inspect
"foo"
=> nil

Looking carefully at this, inspect will return the string representation of the string its called on. This might seem contrived, but notice that when we use puts on the inspect value above, we get it surrounded by double quotes. This is what we're looking for with title.inspect above as well.

It's worth noting that there is also a variant of puts that will print the inspect version of something instead of its to_s value.

Try this out now that we have an inspect defined for Book:

> book = Book.new('A Tale of Two Cities', 450)

> puts book
A Tale of Two Cities
=> nil

> p book
#<Book title: "A Tale of Two Cities", pages: 450>
=> nil

Now that we have an understanding of inspect, let's rewrite our inspect method so that any new attributes are automatically placed in the output from inspect.

This may sound a bit like magic, but it's quite attainable if we structure our class properly.

First, we'll need to understand Ruby arrays and how to loop through them.

Arrays and Iterating

Ruby arrays themselves are straightforward and will resemble what we've seen in JavaScript.

Looping through them, however, is done with the each method, instead of with a for. There are also two syntaxes available when using each, so let's see the code, then work through it.

> [1,2,3].each {|i| puts i}
1
2
3
=> [1, 2, 3]

> [1,2,3].each do |i|
*   puts i
* end  
1
2
3
=> [1, 2, 3]

Here, we can see that we're looping through an array and printing each item in it.

Now for the terminology.

Each of these calls to each is passed a block. In the first call, the block is the {} and what it contains. In the second, it's the do/end and its contents. Both blocks contain a |i| which is the syntax used to define a block variable.

The block here represents code to be executed for each element of the array. each loops through the array and calls the block for each element, passing that element into the array. Therefore the block acts like an anonymous function (as we saw in JavaScript) and its block variables serve as parameters, in this case there is just one "parameter" which represents the current element in the array (i).

The way this works is that each is called on an array along with a block to be executed for each item of the array. As the array is iterated through, the value of the current element of the array is assigned to the block variable.

There is actually a for syntax available in Ruby, but it's just an alias for each, so we'll just use each.

Taking a closer look at Ruby arrays we will find that we can:

  • push new items on the top (end) of them, or pop items off
  • unshift new items into the front of them, or shift items off

These methods are traditionally found in the stack and queue data structures, but Ruby allows them on arrays.

Keep in mind though that shift and pop are destructive methods, meaning that they will change the object that they are called on.

If we just want to see what the first element of an array without changing the array itself, we could just use first. And, as you'd expect, last for the last element.

An example is certainly in order for these methods:

# build an array
arr = [2]
arr.unshift 1     # unshift a 1 onto the beginning of the array
arr.push 3        # push a 3 onto the end of the array
arr # => [1,2,3]

# look at first/last without changing the array
arr.first # => 1
arr.last  # => 3
arr       # => [1,2,3]

# shift/pop on the array, changing it
first = arr.shift # => 1
last  = arr.pop   # => 3
arr               # => [2]

first # => 1
last  # => 3

All these methods have their place, but push seems to be the one most frequently used. Because of this, it has another, shorter method that will work just the same: <<

arr = [1]
arr.push 2 # => [1,2]
arr << 3   # => [1,2,3]

Believe it or not, the above is actually calling the << method on arr, so we can also do the same thing like this:

[].<<(1) # => [1]

So why do we need arrays for our new inspect method?

Because we're going to need a way to keep track of our various attribute names and an array will do that nicely. In fact, that will actually be done outside of inspect, but we'll also be needing another array inside of inspect to store the different attribute display strings that we'll end up with (e.g. "pages: 450").

Let's see what this looks like and what we want kind of string we'll want to turn it into.

# we'll have something like this 
# outside of `inspect`
attributes = [:title, :pages]

# and then we'll end up with a
# bunch of attr strings inside
# of `inspect` in an array
attr_strs = [
  "title: \"A Tale of Two Cities\"",
  "pages: 450"
]

# we'll want to be able to turn 
# the array above into the string
"title: \"A Tale of Two Cities\", pages: 450"

# which will then get placed into
# the string that `inspect` returns

So let's see what to_s and inspect get us for an array.

[1,2,3].to_s    # => "[1, 2, 3]"
[1,2,3].inspect # => "[1, 2, 3]"

This is useful for seeing the array contents, but not the format we're looking for.

We don't want the []'s around our values.

This is a perfect time to use the join method.

# random examples
[1,2,3].join(' | ') # => "1 | 2 | 3"
[1,2,3].join(', ')  # => "1, 2, 3"

# now let's try it with our values
attr_strs = [
  "title: \"A Tale of Two Cities\"",
  "pages: 450"
]

attr_strs.join(', ') # => "title: \"A Tale of Two Cities\", pages: 450"

Perfect!

Let's do a rewrite of inspect with what we know now.

First without comments.

class Book
  def inspect
    attr_str_pairs = []

    title_str = "title: \"#{title}\""
    pages_str = "pages: #{pages}"

    attr_str_pairs << title_str
    attr_str_pairs << pages_str

    attrs_str = attr_str_pairs.join(', ')

    "#<#{self.class} #{attrs_str}>"
  end
end
And here it is with some comments to walk through what's going on:
class Book
  def inspect
    # array to hold the attr str pairs
    attr_str_pairs = []

    # title/pages strings
    title_str = "title: \"#{title}\""
    pages_str = "pages: #{pages}"

    # add them to the array
    attr_str_pairs << title_str
    attr_str_pairs << pages_str

    # join all the attributes together
    # into one string to be used in the 
    # final string
    attrs_str = attr_str_pairs.join(', ')

    # build the final string to return
    "#<#{self.class} #{attrs_str}>"
  end
end

This works, but we're still hardcoding our attribute strings meaning that we won't automatically get new attributes added to our inspect output. Let's push on.

send

So we now know how we'll be joining our attribute strings together, how are we going to get those strings in the first place?

Well, we'll need an array containing the symbols for each attribute, but we're also going to need a way call the methods represented by each symbol. To do this, we'll need to use a method named send.

send is used to send a message to an object. Though we haven't heard this terminology yet, we've been sending messages to objects this whole time.

For instance, when we do book.title, what's happening under the hood is that the message :title is being sent to book.

Let's see how this works:

book = Book.new('A Tale of Two Cities', 450)
book.pages        # => 450
book.send :pages  # => 450

So, how exactly is this useful?

It's useful because it allows us to call methods programmatically. We'll be needing this when we want to call the getters for every attribute.

Assuming that book is defined as above, we can emulate this:

> attributes = [:title, :pages]
=> [:title, :pages]

> attributes.each do |att|
*   puts book.send(att).inspect
* end
"A Tale of Two Cities"
450
=> [:title, :pages]

So using this knowledge, let's take another step towards a solution inspect.

No comments.

class Book
  def inspect
    attributes = [:title, :pages]

    attr_str_pairs = []

    attributes.each do |att|
      str = "#{att}: #{self.send(att).inspect}"
      attr_str_pairs << str
    end

    attrs_str = attr_str_pairs.join(', ')

    "#<#{self.class} #{attrs_str}>"
  end
end
Comments:
class Book
  def inspect
    # array of attributes symbols
    attributes = [:title, :pages]

    # empty array to hold the strs
    attr_str_pairs = []

    # for each attribute symbol...
    attributes.each do |att|
      # build the attribute string
      str = "#{att}: #{self.send(att).inspect}"

      # and push it on the array
      attr_str_pairs << str
    end

    # join the attr strings together
    attrs_str = attr_str_pairs.join(', ')

    # build the complete `inspect` string
    "#<#{self.class} #{attrs_str}>"
  end
end

Now we're talkin'.

Notice the inspect in self.send(att).inspect. In the case of a number, this will just return the number, but in the case of a string it will return the string representation that we want (e.g. "\"A Tale of Two Cities\"").

All set?

Not quite, we're still repeating ourselves somewhere here. Can you spot it?

Here's a hint by way of looking at an abbreviated version of our class in its present state:

class Book
  attr_accessor :title, :pages
  ...

  def inspect
    attributes = [:title, :pages]
    ...
  end
end

We have :title, :pages in our class twice, first as two arguments and then as the contents of an array. Clearly, this works as things are, but if we were to add an attribute to one and not the other, things would eventually not function as we expect them to, and that would be a problem.

And really, the attributes variable doesn't belong in the instance method inspect. It's not specific to a particular object, but applies to every object in the class.

Fittingly, we could instead assign these values to a class variable. Just as instance variables are available only to the instance that they belong to, class variables are available to every instance of the class. You can pick class variables out quite easily, because they'll start with @@.

Let's see what one at the top of our class for our attributes would look like:

class Book
  @@attributes = [:title, :pages]
  attr_accessor :title, :pages
  ...
end

We're still repeating ourselves there. Why haven't we just done attr_accessor @@attributes?

Because if we do that, we'll get TypeError: [:title, :pages] is not a symbol.

See what's happening there? attr_accessor @@attributes is the same as attr_accessor [:title, :pages], not attr_accessor :title, :pages. Basically, we'd be passing the array [:title, :pages] as the first and only argument to attr_accessor.

Which it doesn't like from the looks of that TypeError.

To remedy this problem we can use Ruby's splat operator: *. The splat will turn an array into a list of arguments, which is exactly what we need. It works like this:

> puts 1, 2, 3
1
2
3
=> [1, 2, 3]

> puts [1,2,3]
[1, 2, 3]
=> [1, 2, 3]

> puts *[1,2,3]
1
2
3
=> [1, 2, 3]

Using the splat we can instead pass the @@attributes array as a list of arguments to attr_accessor like this:

attr_accessor *@@attributes
This is useful all on its own, but we can also use this operator to collect parameters as an array. Let's see it in action:
def make_array(*args)
  args
end

make_array(1,2,3) # => [1, 2, 3]

It's also worth noting that the character * is used in Ruby for multiplication too, so be sure to not confuse that for the splat operator. It should be pretty clear from the context what it's being used for though.

Here's some arithmetic in Ruby:

2 + 3 # => 5

2 * 2 # => 4

3 - 2 # => 1

4 / 2 # => 2

We can even handle powers with relative ease:

4 ** 4 # => 256

Shew. Now that we've gone through arrays, send, class variables, and splats, we're finally ready to trash our Book class entirely (again) and rewrite the whole thing from scratch. Here we go!

class Book
  @@attributes = [:title, :pages]
  attr_accessor *@@attributes

  def initialize(title, pages=0)
    @title, @pages = title, pages.to_i
  end

  def inspect
    attr_str_pairs = []

    @@attributes.each do |attr_sym|
      attr_str = "#{attr_sym}: #{self.send(attr_sym).inspect}"
      attr_str_pairs << attr_str
    end

    "#<#{self.class} #{attr_str_pairs.join(', ')}>"
  end
end

Now that's a class we can be proud of.

map

...can we make it any cleaner?

We absolutely can!

You'll see in our new inspect that calling each to essentially transform the array @@attributes into an attribute string array. That is, each attribute symbol in @@attributes is mapped to its associated attribute string (e.g. :title becomes `"title: \"A Tale of Two Cities\"").

Conveniently enough, Ruby offers another iterator method named map for just this purpose.

Let's first see how it works with a simple integer array:

# map the array's items to their string equivalent
[1,2,3].map {|i| i.to_s} # => ["1", "2", "3"]

# map the array's elements to double their value
[1,2,3].map {|i| i * 2} # => [2, 4, 6]

So map works exactly like each, executing a block for each element as it iterates through an array, except that map returns an array containing the returns from each of blocks.

Whereas each returns the array that it was called on.

With that knowledge and looking again at the calls to map above, we should note that blocks work much like methods do: they can make use of the return keyword, but they will also return the value of the last line, even without an explicit return.

So let's see the of map call we'll be making to refactor our inspect method:

# assuming `book` is still defined from above

[:title, :pages].map do |attr_sym|
  book.send attr_sym
end
# => ["title: \"A Tale of Cities\"", "pages: 450"]

So all we'll have to do is store the return of a map call like that in attr_str_pairs and we'll have everything we need to build the full inspect string. Here's what it looks like:

def inspect
  attr_str_pairs = @@attributes.map do |attr_sym|
    "#{attr_sym}: #{self.send(attr_sym).inspect}"
  end

  "#<#{self.class} #{attr_str_pairs.join(', ')}>"
end

Now that's succinct.

Class Methods

We noted earlier that classes (e.g. Book) are objects themselves. We've also seen that classes have methods too (e.g. Book.new). How can we define methods like these ourselves?

Well, these methods are called class methods and we can define them a couple different ways:

# from within the class
class Book
  def self.foo
    'bar'
  end
end

Book.foo # => "bar"

# from outside of the class
def Book.baz
  'boo'
end

Book.baz # => "boo"

Inheritance and Subclasses

Other times, we'll end up with data that can't properly be described with an existing class, but we might have a class that does part of the job.

For example, think about the case of an e-book.

An e-book will have a title and some kind of page count, but it will also have a file size (something a print book does not have). It would be silly to force every Book to have a file size, because it just doesn't apply to physical books. It would be equally silly to repeat all the functionality that we've defined in Book that will apply to an e-book as well (e.g. title).

Instead, what we should do is create a new class to describe an e-book, but have it inherit from Book.

class EBook < Book
  attr_accessor :file_size
end

EBook.new('foo', 100).respond_to? :file_size # => true
Book.new('foo', 100).respond_to?  :file_size # => false

ebook = EBook.new('A Tale of Two Cities', 450)
ebook.file_size        # => nil
ebook.file_size = 1024 
ebook.file_size        # => 1024

ebook.title # => "A Tale of Two Cities"
ebook.pages # => 450

First of all, we're using < Book in class EBook < Book to declare EBook as a subclass of Book. It can also be said that EBook inherits from Book.

Next up, we're using respond_to? to check if new instances of Book and EBook have a method named file_size. As we see by the returns, EBook does (as we just defined with attr_accessor) and Book does not, just as we'd expect.

respond_to? is the first method we've seen that has a ? at the end of its name. This is a Ruby convention that implies that the method will return a boolean value (true or false).

You'll also notice that it takes a symbol representing the method name as an argument, sticking to the other Ruby convention of using symbols to refer to attributes, method names, and other meta-programming tasks.

That said, respond_to? will also accept string as arguments.

And finally we test out our new attribute accessors for file_size on an instance of EBook.

And it works.

super

So that gets us off and running to describe e-books, but notice that we didn't pass a file_size to the constructor. ...because we can't.

On the bright side, we see that EBook.new does assign our title and page count properly. Why is this?

It's possible because Ebook doesn't define an initialize method of its own, so it just inherits the one found in Book.

So to allow a third parameter for file_size in the constructor, we could absolutely just copy the initialize method from Book and put it in EBook, but in doing that, we'd be repeating ourselves and that would be wasteful.

Actually repeating ourselves here would not only be wasteful, it could actually be dangerous later on to our application.

We might change the Book constructor somehow, but forget to make the changes to the EBook constructor too. We'd continue programming, thinking that everything had been updated until we got an error or, worse, one of our users got an error.

Instead, we can use the super keyword from within a new initialize method in EBook to call the initialize method from Book. Let's see what this would look like.

class EBook 
  def initialize(title, pages=0, file_size=0)
    super(title, pages)
    self.file_size = file_size
  end
end

ebook = EBook.new('A Tale of Two Cities', 450, 1024)
ebook.file_size # => 1024

First, notice that when opening the EBook class back up we don't need to specify the class it inherits from.

Next, we see the call to super. Put simply, super calls the method of the same name in the parent class. In this case, we are in initialize for EBook, so this results in a call to the initialize in Book. Also, we are passing only two of the three arguments into super because that is all the constructor in Book can handle.

super works without explicit argument passing as well, but if you use it all on its own, it passes all the arguments on to the parent method.

In this case, super (or super()) alone would be equivalent to super(title, pages, file_size), which would blow up the parent constructor.

Lastly, we can also see that we don't hold onto the return of super. The reason for this is that calling super changes self (i.e. the object being initialized). Because of this, we can simply assign our file_size with self.file_size= on the final line of the constructor.

Speaking of the last line of the constructor, you may have noticed that we don't need to return the new object affected by initialize at the end of our constructors.

Calling EBook.new is wired in such a way that it will create a new instance of EBook, run initialize, and return the new instance. This is just the special relationship between new and initialize in Ruby.

A final note on this new subclass is that the inspect string will not include file_size. We could certainly move things around to accomplish this, but we've got other things to see.

Booleans

So now that we've covered the basics of Ruby classes, we're going to abandon our trusty Book class for the moment and delve into some more elementary Ruby code to outline some of the features that haven't yet been covered.

Perhaps most notable among these are booleans, conditionals, and looping, so let's start with booleans.

Ruby has two booleans: true and false.

These have classes of TrueClass and FalseClass, respectively.

In addition to false itself, nil is the only other falsy value in all of Ruby because it stands for "nothing". This means, of course, that all other values are truthy.

The double bang (!!) works to elicit boolean values in Ruby just as we saw in JavaScript, so let's use it to prove this.

true   # => true
false  # => false

!true  # => false
!false # => true

!!nil  # => false
!!0    # => true
!!''   # => true
!![]   # => true

In addition to !, we also have a not keyword:

!true     # => false
!false    # => true

not true  # => false
not false # => true

Then there are boolean operators to combine and compare:

2 == 2   # => true
2 != 2   # => false

# these don't exhibit any of the
# nonsense we saw with the same
# JavaScript operators
2 == "2" # => false

# checks that the objects are 
# not equal but _the same_
2 === 2 # => true
2 !== 2 # => false

2 <= 2  # => true
1 <= 2  # => true

2 >= 2  # => true
3 >= 2  # => true

true || false  # true
true or false  # true

true && false   # false
true and false  # false

There's also the spaceship operator (<=>), which doesn't get used nearly as much as the others, but is still important to know.

It compares two values and returns -1, 0, or 1 to indicate that the value to the right of the operator is less, equal, or greater than the value on the left, respectively.

5 <=> 10 # => -1

5 <=> 5 # => 0

5 <=> 0 # => 1

Also, be aware of the operator precedence of and, or, and not because they may not work exactly as expected. Unless you have a strong command of Ruby operator precedence, it is recommended that you instead use &&, ||, and !. Otherwise, it is strongly recommended that you use () to be sure that things are combined in the order you intend.

So there's Ruby truth in a nutshell.

Conditionals and Loops

Ruby comes with a variety of conditionals, all of which can be used in a couple different configurations.

To kick things off, let's see if and else.

foo = true
bar = false

val = ''

if foo
  val = "foo was true!"
elsif bar
  val = "foo wasn't true but bar was!"
else
  val = "foo and bar were both falsy!"
end

val # => "foo was true!"

This is pretty self-explanatory, but notice that:

  1. the conditions don't need to be wrapped in ()
  2. there is an elsif keyword (in lieu of else if)

In Ruby there is also an unless keyword that works just like you think it would, the opposite of if.

unless false
  puts 'this is going to print'
end

# `if` equivalent
if !false 
  puts 'this is going to print'
end

Syntactically speaking, you can use else with unless, but since it doesn't make much sense to read in English, it's pretty universally discouraged.

As for looping, Ruby has several options. Let's see how we could write infinite loops in each of them.

while true
  puts 'INFINTE LOOP!'
end

until false
  puts 'INFINTE LOOP!'
end

loop do
  puts 'INFINTE LOOP!'
end

All of these conditionals and loops we've just seen can also be placed at the end of a line to dictate how it's executed.

puts 'gonna see me' if true

puts 'not gonna see me' unless true 

puts 'INFINTE LOOP!' while true

puts 'INFINTE LOOP!' until false

puts 'INFINTE LOOP!' loop do

Another feature of Ruby that fits in here is the case statement, which is really convenient if you find yourself needing a long if elsif elsif.

This is the Ruby equivalent of the JavaScript switch statement.

str = 'foo'

case str
when 'foo'
  puts 'str was foo' # this will print
when 'bar'
  puts 'str was bar'
else
  puts 'str was not foo or bar'
end

Also, be aware that case works differently when testing for classes.

str = 'string'
=> "string"

case str
* when String
* puts 'String value!'
* end
String value!
=> nil

So if we are testing str for its class with a case, we simply use case str (not case str.class) and when String.

I've looked this up numerous times, so don't worry if you don't remember, just note the difference.

All of these structures offer another incredibly useful feature: they all return something.

> if true
*   'foo'
* end  
=> "foo"

> if false
*   'bar'
* end  
=> nil

More specifically, they each return the value of their last line if they are run. If they are not run (i.e. the condition fails), they return nil.

We can even assign variables inline with all of these loops and conditionals.

> if foo = 'bar'
>   puts foo
> end
(irb):1: warning: found = in conditional, should be ==
bar
=> nil

And notice that IRB thinks we're doing something wrong.

Ruby also offers a break keyword to break out of looping structures.

> i = 1
=> 1
> while true
*   break if i > 4  
*   puts i  
*   i += 1  
* end  
1
2
3
4
=> nil

While looping we can use the next keyword to skip to the next iteration in the loop without executing anything that follows that particular next.

> i = 0
=> 0
> while i < 10
*   i += 1  
*   next if i.odd?  
*   puts i  
* end  
2
4
6
8
10
=> nil

In fact, next can also be used within a block used by an iterator like each.

As we take a look at this, let's take the opportunity to learn about ranges too. Ranges are another thing that are served well by examples, so let's see some along with the use of next in an each block.

to_a below stands for "to array".

# first some ranges
> 1..10
=> 1..10

> 'a'..'c'
=> "a".."c"

# ranges to arrays
> (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

> ('a'..'c').to_a
=> ["a", "b", "c"]


> r = 1..10
=> 1..10
> r.include? 10
=> true
> r.include? 11
=> false

# a Range, from 1 up to but no including 10
# notice the use of `...` instead of `..`
> r = (1...10)
=> 1...10
> r.include? 5
=> true
> r.include? 11
=> false

# now let's look at `next` with `each`
# iterate through 1 to 10, printing 
# items, skipping those that are odd
> (1..10).each {|i| next if i.odd?; puts i}
2
4
6
8
10
=> 1..10

Modules

And while we're talking about each, it should be noted that there are many iterators like each, with varied uses. To see a list of all of them, take a look at the documentation for Ruby's Enumerable module.

Enumerable is a standard module in Ruby, but we can also define our own. Modules are essentially just a collection of methods. They mostly resemble classes, except that a module cannot be instantiated. They are, however, able to be included in a class, which will add the methods of the module to that class. Because of this, they are also referred to as mix-ins.

This is yet another topic that is best explained by example, so let's see one.

Going back to our Book class, you'll remember that it had the following:

class Book
  @@attributes = [:title, :pages]
  attr_accessor *@@attributes

  def inspect
    attr_str_pairs = @@attributes.map do |attr_sym|
      "#{attr_sym}: #{self.send(attr_sym).inspect}"
    end

    "#<#{self.class} #{attr_str_pairs.join(', ')}>"
  end
end

So let's say that we find ourselves with another class, Car:

class Car
  @@attributes = [:name, :make, :model_year]
  attr_accessor *@@attributes
end

and we want an inspect method that works like the one in Book, listing all the attributes and their values.

Well, we could write it again, but that would be a waste.

We could have Car inherit from Book, but that wouldn't make a lick of sense; semantically, the concept of a book and the concept of a car are not related.

So let's start over, assuming none of this was defined yet, and rewrite everything. This time around, we'll define inspect inside of a module and use it in both classes.

module CustomStringMethods
  def inspect
    attr_str_pairs = @@attributes.map do |attr_sym|
      "#{attr_sym}: #{self.send(attr_sym).inspect}"
    end

    "#<#{self.class} #{attr_str_pairs.join(', ')}>"
  end
end

class Book
  @@attributes = [:title, :pages]
  attr_accessor *@@attributes

  include CustomStringMethods

  def initialize(title, pages=0)
    @title, @pages = title, pages.to_i
  end
end

class Car
  @@attributes = [:name, :make, :model_year]
  attr_accessor *@@attributes

  include CustomStringMethods
end

Using include CustomStringMethods, we take all of the methods defined inside of module CustomStringMethods and mix them into the current class.

We can also attach class methods from a module to a class. We do this by calling the extend method on the class and passing the module whose methods we want added as class methods as an argument.

> module Baz
*   module ClassMethods
*     def bar
*       'test'
*     end  
*   end  
* end  
=> nil

> class Foo
* end  
=> nil

> Foo.extend Baz::ClassMethods
=> Foo

> Foo.bar
=> "test"

Notice here that we use :: to indicate "the ClassMethods module inside of Baz" with Baz::ClassMethods.

We can also make this happen more automatically by defining a `self.included` method for our module, because this method will get called every time the module is included into a class, and the class it is included in will be passed in as an argument.
module Baz
  module ClassMethods
    def bar
      'test'
    end
  end

  # this method is called whenever this 
  # module is included in a class (base_class)
  def self.included(base_class)
    # this is the line that actually
    # adds the class methods to base_class
    base_class.extend(ClassMethods)
  end
end

class Foo
  include Baz
end

Foo.bar # => 'test'

Hashes

Another fundamental class we haven't yet seen is Hash.

In Ruby, a hash is an associative array used to store key/value pairs.

Ruby hashes work a lot like the JavaScript objects we saw earlier.

You'll see this functionality in other languages, but a special characteristic of hashes in Ruby is that the key can be anything. Very frequently though, we will see symbols and strings used as keys.

Let's see some examples.

# creation by hash literal
hash1 = {}
# creation by direct Hash instantiation
hash2 = Hash.new

hash1 == hash2 # => true
# see! the two are the same

# set/get value by key
hash1[:foo] = ['bar']
hash1[:foo] # => 'bar'
hash1[1] = [1,2,3]
hash1[1] # => [1,2,3]

# hash literal with pairs
hash3 = {:foo => 'bar', 1 => [1,2,3]}

hash1 == hash3 # => true

Having already worked with arrays, the [] syntax for getting/setting a value by key is not that novel, but notice the => used in the hash literal. This => is referred to as a "hashrocket" and will work in hash literals for any and all keys and values.

As of Ruby 1.9 though, there is a shortcut if we're using a symbol as a key in a hash literal.

hash1 = {:foo => 'bar'}
hash2 = {foo: 'bar'}

hash1 == hash2 # => true

hash1[:foo] # => "bar"
hash2[:foo] # => "bar"

hash1[:foo] == hash2[:foo] # => true

So assuming we're using Ruby 1.9, if we're using a symbol as a key in a hash literal, we can just move the : of the symbol to the end and skip the hashrocket altogether. This very much resembles the JavaScript object syntax, but as you can see from the last line above, the key is still, in fact, a symbol (and not a string as it would be in JS).

This is something you'll see in newer code and we'll continue to use it throughout the book, but be aware it is not compatible with older versions of Ruby.

In Ruby, Hash and Array are both examples of what is known as a collection and because of this, they both include Enumerable. This means that all hashes will also have each, map, and the like.

In Ruby 1.9, iterating over a hash is as simple as doing so over an array, but with just one extra block variable. Let's have a look.

> {foo: 'bar', 'baz' => [1,2,3]}.each do |key, val|
*   puts "key: #{key.inspect}, val: #{val.inspect}"  
* end  
key: :foo, val: "bar"
key: "baz", val: [1, 2, 3]
=> {:foo=>"bar", "baz"=>[1, 2, 3]}

As we can see above, when iterating over a hash with each we need a block variable for the key and another one for the value.

Destructive Methods

Something else we're likely to see along the line with these Enumerable methods is something that ends in !, like map!.

Though you might wonder at first why the method name is being shouted, it's actually a Ruby convention used to show that the method is destructive. Let's see this difference by using map and map!.

arr1 = [1,2,3]
arr2 = [1,2,3]

arr1.map {|i| i.to_s}
arr2.map! {|i| i.to_s}

arr1 # => [1, 2, 3]
arr2 # => ["1", "2", "3"]

Seen here, map will return the mapped array, whereas map! replaces the original array with the mapped array.

Not all destructive methods end with a bang (!), such as pop and shift, but if you see a bang, don't expect the object you called it on to be the same after that call.

Passing Blocks

There's also a really handy Ruby shortcut for situations like this. That is a situation where we don't have a ton of work to do on each object with our iterator block, we just want to call a single method on that object and grab its return (e.g. to_s as above).

The shortcut is this: we simply pass the symbol for the object prefixed with & as an argument, instead of using a block.

It works like this:

arr1 = [1,2,3]
arr2 = [1,2,3]

arr1.map! {|i| i.to_s}
arr2.map! &:to_s

arr1 # => ["1", "2", "3"]
arr2 # => ["1", "2", "3"]

But what is the & used here?

Ruby has a number of uses for & and they all have something to do with iterators or blocks.

In the case of map! &:to_s, we're using map! as we normally would, but using & to illustrate that the symbol argument :to_s should be treated as the method name to be called on each item in the collection.

We actually haven't looked at how to write our own methods that make use of blocks yet, so let's see some examples of how to use blocks in method definitions as well as the other usages of &.

# even if we don't define the block in the params
# we can still call it with `yield` if it's given
def run_block
  if block_given?
    yield
  end
end

run_block {'return string'} # => "return string"

# we can also catch the block in a param as long
# as we prefix the name with an `&` and leave it 
# at the end of the list of params
def run_block(&block)
  # notice the lack of `&` when calling the block
  block.call
end

run_block {'return string'} # => "return string"

# and finally, we can pass the block we've defined
# in the params into another call so long as we
# prefix it with an `&`
def run_block_proxy(&block)
  run_block &block
end

run_block_proxy {'return string'} # => "return string"

In a way, we can also store blocks in variables, but we have to do so using the lambda keyword or a Proc.

There are differences in how these two handle arguments and returns, but we won't bother going into that here.

Here are some examples:

> l1 = lambda { puts 'foo' }
=> #<Proc:0x00000000930788@(pry):43 (lambda)>
> l1.call
foo
=> nil

> p = Proc.new { puts 'bar' }
=> #<Proc:0x00000000bb5260@(pry):45>
> p.call
bar
=> nil

> l2 = -> { puts 'baz' }
=> #<Proc:0x00000000c7b528@(pry):47 (lambda)>
> l2.call
baz
=> nil

The last example is a new syntax for lambda that only works in Ruby 1.9 and later.

Errors

Sometimes in Ruby, things go wrong and Ruby will raise an error.

Fortunately, if we structure our code correctly, we can rescue ourselves from this error as well as ensure that certain code that must be run, is.

First, let's cause an error!

> foo.bar
  NameError: undefined local variable or method `foo' for main:Object
    from (irb):1
    from /home/brad/.rvm/rubies/ruby-1.9.3-p194/bin/irb:12:in `<main>'

So that error was deserved, since that variable wasn't defined, but we can also raise errors of our own.

> raise RuntimeError
  RuntimeError: RuntimeError
    from (irb):2
    from /home/brad/.rvm/rubies/ruby-1.9.3-p194/bin/irb:12:in `<main>'

> raise RuntimeError, 'You broke it!'
  RuntimeError: You broke it!
    from (irb):3
    from /home/brad/.rvm/rubies/ruby-1.9.3-p194/bin/irb:12:in `<main>'

Note that the 'You broke it!' argument we passed made it into the error output as: RuntimeError: You broke it!.

Now that we know what errors look like, let's see how we could rescue ourselves from that first case.

begin
  foo.bar
rescue
  # handle any kind of error that
  # might arise when the code in 
  # the `begin` is run
end

We can get even more specific:

begin
  foo.bar
rescue NameError => name_error
  # handle a `NameError`, with the error
  # object saved as `name_error`
rescue RuntimeError
  # handle a `RuntimeError`
rescue
  # handle any other kind of error
ensure
  # code here is run no matter what
end

The rescue rescue keyword can even be used at the end of a line, in the same manner an if statement might be.

> foo.to_s
  NameError: undefined local variable or method `foo' for main:Object
    from (irb):1
    from /home/brad/.rvm/rubies/ruby-1.9.3-p194/bin/irb:12:in `<main>'

> foo.to_s rescue ''
=> ""

Regular Expressions

Like any good scripting language, Ruby also does a fantastic job with regular expressions.

A regular expression (also known as a "regex") can be used on a string to test for specific patterns and can even save groups that they find. Regexs are defined in ruby with // or Regexp.new and are used with either the String method match or with the =~ and !~ operators.

Let's see how some basic matching works in Ruby.

> Regexp.new 'foo'
=> /foo/

> 'foobar'.match /foo/
=> #<MatchData "foo">

> 'foobar'.match /baz/
=> nil

> 'foobar' =~ /foo/
=> 0

> 'foobar' =~ /baz/
=> nil

> 'foobar' !~ /foo/
=> false

> 'foobar' !~ /baz/
=> true

Notice that match and =~ have different kinds of returns.

Whenever a regex match is attempted, certain global variables are set with values pertaining to the match.

Global variables can be accessed from anywhere, regardless of scope, and are defined in Ruby by prefixing a variable name with a $.

Two global variables that are set for a regex match are $` and $'. These, can be read respectively as "string before the match" and "string after the match".

Let's see some examples.

> 'foobarbaz'.match(/bar/)
=> #<MatchData "bar">

> $`
=> "foo"

> $'
=> "baz"

Within the regex we can use ^ and $ to represent the beginning and end of a string, respectively, like this:

> 'foobarbaz'.match(/^foo/)
=> #<MatchData "foo">

> 'foobarbaz'.match(/baz$/)
=> #<MatchData "baz">

> 'foobarbaz'.match(/^bar/)
=> nil

> 'foobarbaz'.match(/bar$/)
=> nil

So far, regexes probably don't seem that useful, but we haven't yet seen them match anything other than literal values. To start looking at our options, let's look at character sets:

Character Set Meaning
[abc] a, b, or c
[abc]{3} any 3 character combination of a, b, or c
[a-z] any character from a to z (any lowercase character)
[a-z]? zero or one characters from a to z (any lowercase character)
[a-z]+ one or more characters from a to z (any lowercase character)
[a-z]* zero or more characters from a to z (any lowercase character)
[0-9] any digit from 0 to 9 (any digit)

Easier yet, a lot of these can be accomplished instead with shortcuts.

Shortcuts Meaning
\d any digit
\s any whitespace character
\w any letter (upper or lowercase), number, or underscore
\D anything but a digit
\S anything but a whitespace character
\W anything but a letter (upper or lowercase), number, or underscore
. anything but a newline character

Character sets and shortcuts become useful when used in conjunction with groups in regex to pluck the actual values matched for particular patterns. Groups are defined with ()'s within a regex and during a match Ruby will assign the group matches to global variables like $1, $2, $3, and so on, depending on their place in the regex.

Here's an example:

# assuming our str from above is still defined

> str[/(\d{3}-\d{3}-\d{4})/, 1]
=> #<MatchData "555-555-5555" 1:"555-555-5555">

# a little cleaner
> re = /(\d{3}-\d{3}-\d{4})/
=> /(\d{3}-\d{3}-\d{4})/

> str[re, 1]
=> "555-555-5555"

If we want to use ()'s, .'s, ?'s, etc in our regular expressions, we can escape them with a \.

A regex to match the literal text "(...)" would look like this:

/\(\.\.\.\)/

Ruby also offers another regex syntax that is really handy when all we want from a match is the value from a matched group. It looks like this:

> str = "let's say we wanted to grab the phone number 555-555-5555 out of this string"
=> "let's say we wanted to grab the phone number 555-555-5555 out of this string"

> str.match /(\d{3}-\d{3}-\d{4})/
=> #<MatchData "555-555-5555" 1:"555-555-5555">

> $1
=> "555-555-5555"

This syntax is not to be confused with one method of string slicing available in Ruby that also uses []'s:

"foobar"[0]
=> "f"

"foobar"[0..2]
=> "foo"

method_missing

We can even define a method_missing method to handle situations where calls are made to methods that haven't been defined.

This sounds and acts like magic, but it's just another part of Ruby.

First, let's see method_missing in action in IRB:

> foo
NameError: undefined local variable or method `foo' for main:Object
  from (irb):1
  from /home/brad/.rvm/rubies/ruby-1.9.3-p194/bin/irb:12:in `<main>'

# we don't have a `foo` method defined here, so we get a `NameError`
# makes sense

> def method_missing(method_symbol)
> end
=> nil

# now that we've defined a `method_missing`, let's try `foo` again

> foo
=> nil

# no error, just `nil` returned
# that's not what we want, we want to pass execution on to the default
# Ruby functionality if we don't do something special ourselves

> def method_missing(method_symbol, *args, &block)
>   super
> end
=> nil

# let's try accomplishing this by calling `super`

> foo
NameError: undefined local variable or method `foo' for main:Object
  from (irb):6:in `method_missing'
  from (irb):8
  from /home/brad/.rvm/rubies/ruby-1.9.3-p194/bin/irb:12:in `<main>'

# there. now we get the error, but notice that it originates from `method_missing`

We didn't really do all that much above, but we can now see how method_missing is called as well as the importance of calling super if we don't do something with the call to the missing method ourselves.

Also, notice the arguments we have access to inside of method_missing. The first is the symbol representing the name of the method called (:foo), a splat of all the arguments passed to that method (captured with *args), and the block passed to the method (&block).

So if we called foo('bar', 'baz'), we'd end up with method_symbol == :foo, args == ['bar', 'baz'], and nothing in &block.

Also, remember that the call to super by itself automatically passes all of the arguments along, making it equivalent to super(method_symbol, *args, &block).

So there are all kinds of tricky things we can do using method_missing, but let's simply use it to create some dynamic methods that return the class of our attributes.

For example, without defining a pages_class instance method, we want Book.new('title string', 1000).pages_class to return Fixnum.

Couldn't we just do book_instance.pages.class?

Yeah, but then we wouldn't be playing with method_missing!

Here's what a solution to this (contrived) problem would look like using method_missing:

class Book
  @@attributes = [:title, :pages]
  attr_accessor *@@attributes

  def initialize(title, pages=0)
    @title, @pages = title, pages.to_i
  end

  ...

  def method_missing(method_symbol, *args, &block)
    attr_sym = method_symbol.to_s[/(.+)_class/, 1].intern

    if @@attributes.include?(attr_sym)
      return self.send(attr_sym).class
    end

    super
  end
end

Assuming the class above is defined in an IRB session, we can now use methods like pages_class:

> book = Book.new 'title string', 1000
=> #<Book:0x00000002b5cd70 @title="title string", @pages=1000>

> book.title_class
=> String

> book.pages_class
=> Fixnum

> book.foo_class
NoMethodError: undefined method `foo_class' for #<Book:0x00000002b5cd70 @title="title string", @pages=1000>
  from (irb):16:in `method_missing'
  from (irb):23
  from /home/brad/.rvm/rubies/ruby-1.9.3-p194/bin/irb:12:in `<main>'

Perfect.

Now let's take a quick look at the internals of our method_missing.

First we use attr_sym = method_symbol.to_s[/(.+)_class/, 1].intern to grab turn :pages_class into :pages.

Then we check to see if that attr_sym is an attribute of the class using if @@attributes.include?(attr_sym).

If it is, we'll want to return the class of that attribute straightaway. We do this with return self.send(attr_sym).class.

Notice that the return will return a value from method_missing without executing anything else.

Also, if we call book.pages_class, then self.send(attr_sym).class is equivalent to book.self(:pages).class or, simpler yet, book.pages.class.

If we don't find the attribute, the call gets made to super.

Now that we breezed through all of that let's take a closer look at attr_sym = method_symbol.to_s[/(.+)_class/, 1].intern. This takes a value from symbol, to string, to a specific part of that string, and then takes that back to a symbol.

Let's see this step-by-step in in IRB using a literal symbol value:

# the whole thing `:pages_class` to `:pages`
> :pages_class.to_s[/(.+)_class/, 1].intern
=> :pages

# first we take the symbol to a string
> :pages_class.to_s
=> "pages_class"

# then we match on the string
> :pages_class.to_s[/(.+)_class/]
=> "pages_class"

# we can see that it does match

# but we don't just want to match, we want 
# to capture the first group from the match
> :pages_class.to_s[/(.+)_class/, 1]
=> "pages"

# now we have the value we want, but as a string

# finally, we convert that string to a symbol
> :pages_class.to_s[/(.+)_class/, 1].intern
=> :pages

This is a really fantastic example that lets us bring a lot of different Ruby features together, but don't worry, most of the logic in the later chapters won't be this involved.

Method Visibility

Switching gears yet again, let's look at method visibility.

Sometimes methods for a given object are only to be used by the object itself. In cases like these, the methods should be private.

Thus far, all the method we've written have been public. The fact that we haven't declared anything one way or another is taken by Ruby to mean that we want the methods to be public.

We could, however, be redundant and explicitly declare them public with the public keyword. It would look like this:

class Foo
  public
  def bar
    'bar return'
  end
end

Anything below the public keyword will be a public method, until another visibility keyword is used and then that will dictate method visibility.

...until the next one and so on.

Also, remember that indentation holds no syntactic significance, so we can place these keywords as we like.

I frequently see it indented with the method definitions, as we saw above, but I prefer it to be lined up with the class keyword myself, so that's what I'll be using.

This is another preference that someone will probably gripe to you about regardless, so just pick the one you like or try to go with the majority preference of your team.

Let's see all the keywords in use.

class ParentClass
  def public_method
    'public string'
  end  

private

  def private_method
    'private string'
  end  

protected

  def protected_method
    'protected string'
  end  
end  

class ChildClass < ParentClass
  def call_private_method_of(object)
    object.private_method
  end

  def call_protected_method_of(object)
    object.protected_method
  end
end

Assuming those are all defined in an IRB session, let's see what this gets us:

> parent_instance = ParentClass.new
=> #<ParentClass:0x00000001bc8d78>

> child_instance = ChildClass.new
=> #<ChildClass:0x00000001e46280>

> parent_instance.public_method
=> "public string"

> parent_instance.private_method
NoMethodError: private method `private_method' called for #<ParentClass:0x00000001bc8d78>

> parent_instance.protected_method
NoMethodError: protected method `protected_method' called for #<ParentClass:0x00000001bc8d78>

> child_instance.call_private_method_of parent_instance
NoMethodError: private method `private_method' called for #<ParentClass:0x00000001bc8d78>

> child_instance.call_protected_method_of parent_instance
=> "protected string"

In summary:

  • public methods can be called by anything
  • private methods can only be called within the instance the call is being performed on
  • protected methods are available to instances of the same class and their ancestors
We can also completely get around this with `send`, though this is likely not a good idea (unless you have a great reason for it).
> parent_instance.send :private_method
=> "private string"

> parent_instance.send :protected_method
=> "protected string"

require

When we want to pull another Ruby file or Gem in to be executed along with the Ruby we're running, we can use to require.

We won't be doing this much ourselves, but the configuration files of our Rails app will be loaded up with require's.

As an example though, let's say we're working outside of Rails in IRB, but want to use Rails' ActiveSupport::JSON to parse some JSON.

> ActiveSupport::JSON.decode("{\"foo\":\"bar\"}")
NameError: uninitialized constant ActiveSupport
  from (irb):1
  from /home/brad/.rvm/rubies/ruby-1.9.3-p194/bin/irb:12:in `<main>'

> require 'active_support'
=> true

> ActiveSupport::JSON.decode("{\"foo\":\"bar\"}")
=> {"foo"=>"bar"}

The require 'active_support' here pulls in the module ActiveSupport that is defind by a Gem.

This follows the convention of downcasing and underscore separating class/module name strings for use in file names.

In Rails, we can convert class/module name strings to this format using the underscore method:

"ActiveSupport".underscore
=> "active_support"

Scope

One topic that we have not touched on is Ruby scoping. I would take it upon myself to write my very own explanation of it here, but the book Ruby meta-programming book listed in the resources does such an amazing job of describing it, that I will leave you to read it instead.

</ruby>

So that's it for our dive into Ruby specifically, great job on getting through all that!

Again, feel free to re-read, but the goal of this section is to broadly familiarize the reader with Ruby. Having read everything above, you should be able to understand the gist of what we see moving forward, but I will try to accompany particularly dense chunks of Ruby with an English explanation from here on out.

If nothing else, rest assured that we won't be running across any syntactic surprises when we get into Rails.

7.3 | Vital Gems

Before wrapping up with Ruby and getting into Rails itself, let's see a few Gems that we just couldn't live without.

7.3.1 | Bundler

Rails is distributed as a Gem itself, but it also relies on many different Gems and can incorporate the use of many, many more.

Not particularly long ago, people would more or less just gem install what they needed for a given project.

This worked initially, but the problem grew to be they had many projects that required many different versions of the same Gems. And since you can only have one version of a Gem installed locally at a time, this was quite a pain.

Bundler came onto the scene and made the whole situation easier to manage.

Using a file named Gemfile, Bundler works within the directory holding your Rails app to fetch, install, and manage the gems you tell it to for that particular app. The text inside this file is actually just Ruby code, used for a specific purpose by bundler.

Here's an example of what you'll likely see at the top of a basic Gemfile (comments are mine):

# this tells bundler where to 
# download the gems from
source 'https://rubygems.org'

# this tells bundler to download
# and install the gem 'rails',
# specifically version 3.2.6
gem 'rails', '3.2.6'

When you create a new Rails app or when you update your Gemfile, you need to tell bundler to fetch and install the new gems. Assuming you're in the directory for your Rails app, this will do the trick:

$ bundle install

This is primarily what we'll be using bundler for, but there's much more it can do.

7.3.2 | Rake

A tool that has been around much longer is Rake.

The name "Rake" is also known as "Ruby Make", [Make](http://en.wikipedia.org/wiki/Make_(software)) being a program commonly used in Unix-like systems while building a program from source.

Rake tasks (Ruby code) will be saved in files ending in .rake and can be run using the rake command. This helps us by standardizing the way we store and run tasks that aren't part of our application itself. Instead of hunting down that-script-we-know-we-wrote-but-where-on-earth-was-that-saved, we simply place them all in the same spot and have a clean syntax for calling them later with rake.

We'll be seeing all the necessary usage of rake once we get off and running in Rails.

7.3.3 | Rack

Another relative newcomer to the Ruby/Rails world is Rack. We won't have to directly interact with Rack at any point during our time here, but it's worth mentioning for familiarity's sake.

According to the Rack website:

"Rack provides a minimal interface between webservers supporting Ruby and Ruby frameworks."

Rails has recently adopted Rack and now uses it to communicate with the chosen web server(s) for a project. Doing this allows there to be more flexibility in regards to web servers for frameworks, since all the frameworks have agreed to play by the same rules — running on top of Rack.

What are these rules?

According to the Rack SPEC:

"A Rack application is an Ruby object (not a class) that responds to call. It takes exactly one argument, the environment [Hash] and returns an Array of exactly three values: The status, the headers, and the body."

This may not make a lot of sense at first (it sure didn't to me), but it just basically specifies the input and output for our application (i.e. for Rails).

The input to a Rack app is an "environment" hash that will contain information like the request path, HTTP method used, query string parameters, etc. Assuming the app object is stored in app, this hash will be passed in with each request as app.call(env_hash).

The output is a three element array and those elements represent the following:

  1. an integer value for the HTTP response code (e.g. 200, 404)
  2. a hash representing header values (e.g. {'Content-Type':'text/html'})
  3. a response body, either a string or an object that will respond_to?(:each)

Each and every Rack-compliant web server will simply need to expect this kind of interface with the web app, leaving us free to switch web servers without much thought.

In fact, we won't have to think much about Rack for the duration of the tutorial, it's just good background knowledge to have.

7.3.4 | thin

Speaking of web servers, we'll be needing one for use with our own web application and, in fact, we'll be using one that works with Rack.

Due to the fact that we'll be using Heroku for our production environment, we'll be using Thin (as required by Heroku).

Other common web servers used with Rails include WEBrick, Mogrel, Unicorn, and Nginx. There are plenty more though.

To sum this section and the last, we will be using Thin as our web server and it will communicate with our Rails app through Rack.

This won't really come up in practice, but it's good to have an understanding of what these pieces are and how they fit together.

We'll soon see that we have to add Thin to our Gemfile and bundle install, but even though we can start it thereafter with the thin command in Bash, there's a better way of doing this for our Rails app.

How?

Well, let's get into that. Wave goodbye to our chapter on Ruby, because it's finally time to start building our web application.