Learning Ruby: Playing with irb

Introduction

I have this book, called Beginning Ruby, written by Peter Cooper. It’s one of the first book I’ve bought about programming. I’ve read… 20 pages probably… For some reason, I barely started it. The book is getting old, in programming terms, but I feel like learning a little bit of Ruby, and I feel like it will get the job done to teach me the basics. I never used Ruby before, so I’m starting from scratch here.

irb ( Interactive RuBy )

Note: I’ll assume you have Ruby installed on your machine. You can check by running ruby -v in a terminal. You should get something like:

➜  ~ git:(master) ✗ ruby -v
ruby 2.3.3p222 (2016-11-21 revision 56859) [universal.x86_64-darwin17]

To start the ruby’s REPL, called irb, simply type irb and press Enter:

➜  ~ git:(master) ✗ irb
irb(main):001:0>

To exit the REPL, type exit and press Enter.

For this article, I think I will only use irb.

As basic as it gets

From what I read, Ruby aims to be a very readable language, close to the English language. To follow the ancient traditions of our people, we must print a friendly greeting to our terminal. Let’s type the following in our terminal:

10.times do print "Hello Ruby" end

Well, it is true it reads like English. You could read that to anyone understanding English and they would understand what you are talking about. We can guess pretty easily what this command will do:

Hello RubyHello RubyHello RubyHello RubyHello RubyHello RubyHello RubyHello RubyHello RubyHello Ruby=> 10

Prints 10 times “Hello Ruby” !!! For now, I think it’s safe to forget the => 10 at the end. I don’t know what it means yet 😀

Maths

Of course, we can also do some maths:

irb(main):005:0> 2+2
=> 4
irb(main):006:0> 3-2
=> 1
irb(main):007:0> 8-45
=> -37
irb(main):009:0> 4*5
=> 20
irb(main):008:0> 10/3
=> 3

Notice the result of the last operation. Returns 3. We know it’s not true. If you provide Ruby with integers, you will get an integer as a result. You want a floating point number? Provide floating points numbers in the operation:

irb(main):013:0> 10.0 / 3
=> 3.3333333333333335
irb(main):014:0> 10 / 3.0
=> 3.3333333333333335

Tadaaaa!!

Another issue you might encounter, if you are trying the following:

irb(main):019:0> print 42 + " is the answer to the universe"
TypeError: String can't be coerced into Fixnum
    from (irb):19:in `+'
    from (irb):19
    from /usr/bin/irb:11:in `<main>'

OR:

irb(main):020:0> print "The answer to the universe is " + 6*7
TypeError: no implicit conversion of Fixnum into String
    from (irb):20:in `+'
    from (irb):20
    from /usr/bin/irb:11:in `<main>'

Strings and Numbers can’t be associated this way. To solve this, you can do:

irb(main):021:0> print "The answer to the universe is ",  6*7
The answer to the universe is 42=> nil

irb(main):022:0> print 42, " is the answer to the universe"
42 is the answer to the universe=> nil

We added a comma instead of a +, and it works as expected!

Objects!! Objects everywheeeere!!

Ruby is an object-oriented programming language. Any concept you can think of can be represented as an object in Ruby. If you’ve used another object-oriented language, this may look familiar. Let’s see how Ruby does it.

Let’s create a concept called Book:

irb(main):023:0> class Book
irb(main):024:1> attr_accessor :title, :author, :year
irb(main):025:1> end
=> nil

So, in Ruby, we call a concept a class. So we create a Book class. Always starts with a capital letter. Then, we define three attributes to our Book class: title, author and year. Finally, the end keyword tells Ruby we are done defining our concept.

Book is the concept, an object is a thing based on that concept. The book 1984 written by George Orwell could be an object based on the Book concept for example.

Using our concept

Let’s create a variable to store an instance of our Book concept.

irb(main):028:0> book_instance = Book.new
=> #<Book:0x007fdc17898208>

We created a new Book instance by called the new method on the Book class. We stored that instance inside a variable called book_instance. Now, as long as your REPL lives, book_instance is an instance of the Book class. Let’s change a few things about our book instance:

irb(main):029:0> book_instance.title = "1984"
=> "1984"
irb(main):034:0> book_instance.author = "George Orwell"
=> "George Orwell"
irb(main):035:0> book_instance.year = 1948
=> 1948

Here, we gave the book_instance attributes a value. As you can see, there are no restrictions on the type of data you give to those attributes. I could have written 1984 instead of “1984” and no errors would have appeared.

Retrieving data

To print the attributes:

irb(main):036:0> puts book_instance.year
1948
=> nil
irb(main):037:0> puts book_instance.title
1984
=> nil

puts is like print. The difference is that puts adds a newline character at the end ( and starts a new line ).

Inheritance

Having a Book concept is fine, but there are a lot of different books available. We can make concepts inherit from other concepts.

irb(main):038:0> class Novel < Book
irb(main):039:1> attr_accessor :genre
irb(main):040:1> end
=> nil

The Novel concept inherits from the Book concept. This means that the Novel will have access to the Book attributes. Let’s create a Novel instance:

irb(main):041:0> novel_instance = Novel.new
=> #<Novel:0x007fdc17818aa8>
irb(main):043:0> novel_instance.title = "Notre Dame de Paris"
=> "Notre Dame de Paris"
irb(main):044:0> novel_instance.genre = "Romance"
=> "Romance"

Our novel_instance has access to the Book attributes ( such as title ), and has its own attributes ( here genre ). BUT, the Book concept doesn’t have access to the Novel attributes:

irb(main):045:0> newbook = Book.new
=> #<Book:0x007fdc17013650>
irb(main):046:0> Book.genre = "Romance"
NoMethodError: undefined method `genre=' for Book:Class
    from (irb):46
    from /usr/bin/irb:11:in `<main>'

And, if we create another concept, inheriting from Book, that concept will only have access to its attributes, and the Book attributes, not the Novel attributes.

irb(main):007:0> class Magazine < Book
irb(main):008:1> attr_accessor :type
irb(main):009:1> end
=> nil

irb(main):017:0> mag_instance = Magazine.new
=> #<Magazine:0x007fcabc05db90>
irb(main):018:0> mag_instance.type = "Periodical"
=> "Periodical"
irb(main):019:0> mag_instance.title = "GQ"
=> "GQ"
irb(main):020:0> mag_instance.genre = "ERROOOOR"
NoMethodError: undefined method `genre=' for #<Magazine:0x007fcabc05db90 @type="Periodical", @title="GQ">
    from (irb):20
    from /usr/bin/irb:11:in `<main>'

We created a Magazine concept which inherits from Book. Magazine doesn’t have access to the Novel attributes, only to its attributes and the one of its parent.

Methods

Classes can have methods, instructions you tell your classes to perform. You need to define them inside the class, like so:

irb(main):021:0> class Kindle < Book
irb(main):022:1> def sayMotto
irb(main):023:2> puts "No more paper!!!"
irb(main):024:2> end
irb(main):025:1> end
=> :sayMotto

irb(main):026:0> new_kindle = Kindle.new
=> #<Kindle:0x007fcabc1630d0>
irb(main):027:0> new_kindle.sayMotto
No more paper!!!
=> nil

Look, we create a Kindle concept. Inside we use the def keyword to define a method. This method is called sayMotto. The body of this method tells it to print No more paper!!!. Notice that there are two end keywords. The first one to indicate we are done defining the method, the second is for the end of the class definition. Then, we can call our method by using its name on our newly created Kindle instance!

Okay, that’s enough for one article. I feel like I’ve covered enough stuff for one article. I’ll see you in the next one.

Have fun!

Your email address will not be published. Required fields are marked *

*