Learning Ruby: From Zero to Hero

TK
The Renaissance Developer
10 min readJun 15, 2017

Introduction / History

Ruby is a “dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write.” created by Matz.

He has often said that he is “trying to make Ruby natural, not simple” in a way that mirrors life.

Ruby is simple in appearance, but is very complex inside, just like our human body — Matz

For me the first reason to learn Ruby was that it is, in fact, a beautiful programming language. It is really natural to code it and always express my thoughts.

The second main reason was Rails. The well known framework that Twitter, Basecamp, Airbnb, Github, and so many companies use.

Variables

You can think about variables as a word that stores a value. Simple as that.

In Ruby it is really easy to define a variable and set a value to it. Imagine you want to store number 1 in a variable called “one”. Let’s do it!

Wow! How simple was that? You just assigned the value 1 to “one” variable

And you can assign some value for whatever variable you want. “two” variable stores 2 integer and “some_number” stores 10000.

Besides integers, we can also use booleans (true / false), strings, symbols, float and so many other data types.

Control Flow: conditional statements

If” uses an expression to evaluate to true or false. If it is true, it executes what it is inside the if statement. For example:

2 is greater than 1, so the “puts” code is executed.

The “else” statement will be executed if “if” expression is false.

1 is not greater than 2, so the code inside “else” will be executed.

You can also use “elsif” statement. Like that:

One way I really really like to write ruby is using “if” statement after the code to be executed:

It is so beautiful and natural as Matz says. It is idiomatic Ruby.

Looping / Iterator

In Ruby we can iterate in some many different forms. I’ll talk about 3: while, for and each iterator.

While Looping: while the statement is true, the code inside the block will be executed. So this code will print the number from 1 to 10.

For Looping: you pass the variable “num” to the block and the “for” statement will iterate it for you. This code will print the same as “while” code: from 1 to 10.

Each Iterator: I really like “each” iterator. It is simple and expressive. For an array of values, it’ll iterate 1 by 1, passing the variable to the block.

You are maybe asking what is the difference of “each” iterator and so well known “for” looping. The main difference is that “each” iterator maintain the variable only inside of scope. “for” looping keeps the variable live outside the block. Let’s do a test:

The variable “num” in the “for” looping will keep alive after iteration block. “num” variable from “each” iterator block will not.

Array: Collection | List | Data Structure

Imagine you want to store the integer 1 in a variable. But maybe now you want to store 2. And 3, 4, 5 …

Do I have another way to store all integers that I want, but not in millions variables? If I asked this question, it probably has another way to store it.

Array is a collection that can be used to store a list of values (Like these integers that you want). So let’s use it!

It is really simple. We created an array and stored it on my_integer.

But maybe you are asking: “How can I get a value from this array?”

Great question. Arrays has a concept called index. The first element gets the index 0 (zero). The second gets 1, and so on. You got the idea!

For better understand, we can represent the array and each element with its index. Should I draw it?

Using the Ruby syntax, it’s also simple to understand:

Imagine that you don’t want to store integers. You just want to store strings. Like a list of your relatives names. Mine would be something like that:

Works the same way as integers. Nice! :)

We just learnt how Array indices works, but I need to show you about how we can add an element to the Array data structure (an item to a list).

The most common methods to add a new value to an Array is push and <<. Let see how it works:

Push is super simple! You just need to pass the element (eg. “The Effective Engineer”) as the push parameter.

<< method is also super simple! You also need to pass the element as a parameter. You may ask “But it doesn’t use the dot notation as other methods. How it could be a method as well?” Wow, nice question! :)

Writing this:

..is similar to writing this:

Ruby is so great, huh?! ❤

Well, enough of Arrays. Let’s talk about another data structure.

Hash: Key-Value Data Structure | Dictionary Collection

Now we know that Arrays are indexed with integer numbers. But what if we don’t want to use integer numbers as indices? Some data structure that we can use numeric, string, or other types of indices.

Let’s learn about the Hash data structure. Hash is a collection of key-value pairs. Something that looks like it:

The key is the index pointing to the value. How do we access the Hash value? Yes, you are right. Using the key! Let’s try it.

I created a Hash about me. My name, nickname & nationality, and those attributes are the Hash’s keys.

As we learnt how to access the Array using index, we also use indices (keys in Hash context) to access the value store in the Hash.

In the example I printed a phrase about me using all the values stored in the Hash. Pretty simple!

Hmm, another cool thing about Hashes is that we can use anything as the value. In the Hash I created, I want to add a key “age” and my real integer age in it.

A key (“age”) value (24) pair using string as the key and integer as the value.

As we did with Arrays, let’s learn how to add elements to a Hash. The key pointing to a value is a big part of what Hash is, and so it is when we are talking about adding elements to the it.

We just need to assign a value to a hash key. Nothing complicated here, right?

Iteration: Looping Through Data Structures

The array iteration is very simple. We, Ruby developers, commonly use the each iterator! Let’s do it:

So the each iterator works passing each array element as a parameter in the block. For each element, we (can do everything with it) print it.

For hash data structure, we can also use the each iterator but passing two parameters to the block: the key & the value.

This is an example on how to use. We did name the two parameters as key and value, but it is not necessary. We can name it with “anything”. Let’s see it:

We can see we used attribute as a parameter for the Hash key, and it works properly! Great!

Classes & Objects

Objects are a representation of the real world objects like cars, dogs, bike, etc. The objects share two main characteristics: data and behavior.

Cars have data like number of wheels, number of doors, seating capacity and also have behavior: accelerate, stop, show how much fuel is missing and so many other.

We call data as attributes and behavior as methods in object oriented programming. Again:

Data → Attributes & Behavior → Methods

And a Class is the blueprint from which individual objects are created. In the real world we often find many objects with all the same type. Like cars. All the same make and model (have an engine, wheels, doors, …). Each car was built from the same set of blueprints and has the same components.

Ruby Object Oriented Programming mode: ON

Ruby as an Object Oriented programming language has these concepts: class& object.

A class is a blueprint, a model for its objects.

So again, a class it is just a model, a way to define attributes and behavior(as we talk in the theory section). As an example, a Vehicle class has its own attributes that defines what is a Vehicle object. Number of wheels, type of tank, seating capacity and maximum velocity are all attributes of a vehicle.

With this in mind, let’s understand Ruby syntax for classes:

We define classes with class statement and finish with end. Easy!

And objects are instances of a class. We create an instance by calling .newmethod.

Here vehicle is an object (or instance) of the class Vehicle.

“A vehicle is a instance of the class of objects known as vehicles.”

Remember that our Vehicle class has 4 attributes: Number of wheels, type of tank, seating capacity and maximum velocity. We set all this attributeswhen creating a vehicle object. So here we define our class to receive data when instantiates it.

We use the initialize method. We call it a constructor method. So when create the vehicle object, we can define this attributes. Imagine that we love the Tesla Model S and we want to create this kind of object. It has 4 wheels, it is an electric car so the tank’s type is electric energy, it has space for 5 seats and the maximum velocity is 250km/hour (155 mph). Let’s create this object! :)

4 wheels + Electric type of tank + 5 seats + 250km/hour maximum speed.

All attributes set. But how can we access this attributes values? We send a message to the object asking about them. We call it a method. It’s the object’s behavior. Let’s implement it!

This is an implementation of two methods: number_of_wheels and set_number_of_wheels. We call it getter & setter. Because the first get the attribute value, and the second set a new value for the attribute.

In Ruby, we can do that without this methods. It is the attr_reader, attr_writer and attr_accessor. Let’s see it with code!

  • attr_reader: implements the getter method
  • attr_writer: implements the setter method
  • attr_accessor: implements both methods

So for now we learnt how to get attributes values, implement getter and setter methods & use attr (reader, writer and accessor).

But we can also use methods to other things like “make_noise” method. Let’s see it!

When we call this method, it just returns a string “VRRRRUUUUM”.

Encapsulation: hiding information

Encapsulation is used as a mechanism to restrict direct access to objects’ data and methods. But the same time it facilitates operation on that data (objects’ methods).

Encapsulation can be used to hide data members and members function.Under this definition, encapsulation means that the internal representation of an object is generally hidden from view outside of the object’s definition. — Wikipedia

So all internal representation of an object is hidden from the outside, only the object can interact with its internal data.

In Ruby we use methods to direct access data. Let’s see an example:

We just implemented this Person class. And as we learnt in Ruby OOP part 1, to create the object person, we use the new method and pass the parameters.

So I created me! :) The tk object! Passing my name and my age. But how can I access this information? My first attempt is to call name or age method.

We can’t do it! We didn’t implement the name (and the age) method. Remember when I said that “In Ruby we use methods to direct access data”? To access the tk name and age we need to implement those methods on our Person class.

Now we can direct access this information. With encapsulation we can ensure that the object (tk in this case) is the only responsible to access the data (name and age). The internal representation of the object is hidden from the outside.

Inheritance: behaviors and characteristics

Certain objects have something in common. Behavior and characteristics.

For example, I inherited some characteristics and behaviors from my father. I inherited his eyes and hair as characteristics. And impatience and introversion as behavior.

In object oriented programming, classes can inherit common characteristics (data) and behavior (methods) from another class.

Let’s see another example and implement it in Ruby!

Imagine a car. Number of wheels, seating capacity and maximum velocity are all attributes of a car. We can say that an ElectricCar class inherits these same attributes from Car class.

Our Car class implemented! :)

Instantiated and we can use all methods created! Nice!

In Ruby, we use the < operator to a class inherits from another. An ElectricCar class can inherits from our Car class.

Simple as that! We don’t need to implement the initialize method and any other method, because this class already has it (inherited from Car class). Let’s prove it!

Beautiful!

Module: a toolbox

We can think of a module as a toolbox that contains a set of constants and methods.

An example of Ruby module is Math module. We can access the constant PI:

And .sqrt method:

And we can implement our own module and use it in classes.

We have a RunnerAthlete class.

And we implement a module Skill to have the average_speed method.

How do we add this module in out classes to have this behavior (average_speed method)? We just include it!

See the “include Skill”! And now we can use this method in our instance of RunnerAthlete class

Yay!

To finish modules, we need to understand that…

  • A module can have no instances.
  • A module can have no subclasses.
  • A module is defined by module ... end.

Wrapping Up!

We learnt A LOT of things here!

  • How Ruby variables work
  • How Ruby conditional statements work
  • How Ruby looping & iterators work
  • Array: Collection | List
  • Hash: Key-Value Collection
  • How we can iterate through this data structures
  • Objects & Classes
  • Attributes as objects’ data
  • Methods as objects’ behavior
  • Using Ruby getters and setters
  • Encapsulation: hiding information
  • Inheritance: behaviors and characteristics
  • Modules: a toolbox

Congrats! You completed this dense piece of content about Ruby!

Have fun, keep learning & always coding! :)

I hope you liked this content. Support my work on Ko-Fi

My Twitter & Github. ☺

--

--