Ruby Basics
Tags: ruby, programming, webdev, beginners
Published: 2021-07-17 13:23:17

Hello, dear devs. 👋

I am back, bringing to you (again) the weirdest articles on the internet. I am sure you were waiting for that, right? (Please don't answer!)

![No No No](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idpah2su7f06f5t3kczs.gif)

Today, as the title points out, I will be briefly ~~talking~~ writing about the **Ruby** language and some of its features. 😉

If you have read my previous posts (something I don't recommend) I usually write about **JavaScript** related stuff and I love doing so.

![banana JS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/odcecwgec1w1zu9b7vi6.jpg)
 
But today I have decided to vary a little bit and talk about **Ruby** that is an extremely powerful language and, long story short, thanks to it I am a developer today. (Am I? 🤔)

Before start and given my ability to read minds I know it is time to `Q & A`:
![Reading minds](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txznng4kd39eg7w9k6zk.gif)

### Is Ruby A Dying Language?

**Short answer:** no. Indeed, it has been losing "popularity" along the years I cannot deny that but it is way far from death. 

**The Clash** is my favorite band ever, it also has been losing its popularity but can you tell they are dying? 🎸 Yeah, you just cannot! (In musical terms, I meant.) 
I am losing focus here, sorry. 😅

**Ruby** just got a recent minor update to `3.0.2` on	July 7th but it is beyond the current scope of this article.

## Is it worth learning Ruby in 2021? 💎

Paraphrasing someone I have no idea: 
> "... Knowledge does not occupy space!"

There are many discussions about this specific subject out there but honestly, I am here to bring you the basics of **Ruby** so let's get started because life is short.

### ⚠️ Disclaimer ⚠️

Given the language vastness it is impossible to include  here, in a mere 10 minutes reading post, either all its features, different ways of doing the same thing or even best practices. I hope you understand that.

The examples are based in both my mental disorders, personal delirium and confused state of mind caused by unknown reasons, according to my psychologist.

![Insane](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kmqtym5uvvv37wa59qr.gif)

If you are **OK** with that, __welcome aboard !__, otherwise you are free to go. There are tons of normal people waiting for you somewhere else. 😂 🤣

### Ruby in a nutshell 💎 👉 🌰 🐚

🚨 The next three paragraphs I didn't write myself. They are, in my vision, plausible to explain what I have in mind. I am not a huge fan of __"reinvent the wheel"__. 🚨

**Ruby** is a dynamic, interpreted, high-level and general-purpose programming language. [Wikipedia:](https://en.wikipedia.org/wiki/Ruby_(programming_language))
 
It was was created by **Yukihiro Matsumoto (Matz)**, in Japan in the mid 1990's and was designed for programmer productivity with the idea that **programming should be fun for programmers**.
 
It emphasizes the necessity for software to be understood by humans first and computers second. [Launch School:](https://launchschool.com/books/ruby/read/introduction)

Please pay special attention for those three sentences:

> "... necessity for software to be understood by humans first (🙋🥇) and computers second (🗣️ losers!)."

> " ... It was was created by Yukihiro Matsumoto (Matz), in Japan."

> " ... with the idea that programming should be fun for programmers."
 
**Quote 1:** Most of the time, **Ruby** statements are very similar to plain English and it turns out a language very easy to read and understand by us, mere mortals.

![Mark Zuckerbot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k89f2h3xvt33gqlwtb0k.gif)

**Quote 2:** Try to convince me about something bad that is originally from Japan and fail miserably. 

👉 [ ~~Suggest a gif (about Japan) in the comments section and I will upload the best here.~~ ]. 👈

Thanks for participating, **Juan**. The `gif` below is in your honor!  🤜🤛

![Pikachu](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ivas7rordbgqjcohwnfv.gif)

**Quote 3:** The 'having fun' part you are going to discover very soon. If you stick with me until the end, of course. 😊

![Jim Carrey Complaining](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gfyhnku2hijhhehqtouy.gif)

If you would like to follow along and don't have **Ruby** installed in your machine, don't worry. Install it! 🤣 😆 😂

[Installing Ruby](https://www.ruby-lang.org/en/documentation/installation/)

Just kidding, you can use the [Ruby Online Compiler & Interpreter - Replit](https://replit.com/languages/ruby). It is a mixing of the `irb` console and an `IDE` in the same page.

> IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby expressions ...
[Module: IRB](https://ruby-doc.org/stdlib-2.4.0/libdoc/irb/rdoc/IRB.html")

![Starts here](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/94555f2iq2awnhw9llqb.gif)

### Commenting ✍️

You can comment a block of code, for example, using both the  `=begin` and `=end` keywords and placing the block to be comment between them.

```ruby
=begin
   Dale a tu cuerpo alegria Macarena
   Eeeh Macarena .... 
   Aaahe!
=end
```
You can also have an one-line comment using the `#`.

```ruby
# Never gonna give you up, never gonna let you down ...
```

## `print` / `puts` methods 🖥️

Both functions are used to display output on the screen. The major difference between them is that `puts` inserts a newline at the end. 
```ruby
print "Hello, "
print "darkness my old friend."

# Result: 
# Hello, darkness my old friend

puts "Hark, hark! I hear"
puts "The strain of strutting chanticleer"
puts "Cry, Cock-a-diddle-dow!"

# Result:
=begin
   Hark, hark! I hear
   The strain of strutting chanticleer
   Cry, Cock-a-diddle-dow! 
=end 
```
### Variables 📦

**Ruby** has four different kinds of `variables` where which one is declared in its specific way:

```ruby
    local = "Hey, I am a local variable."
    _other_local_var = "Never mess up with a local!"
    
    @instance = "For instance, I am an instance variable."
    @@class = "I am 'classy'."
    $global = "Globalization rules!"
```

### Data Types 😎 😍 😈 👻 💩
**Ruby** has several data types: `String`, `Integer`, `Float`, `Boolean` (`TrueClass`, `FalseClass`), `Symbol` and `Nil` (`NilClass`). 

I wouldn't classify them as primitive data types because everything is **Ruby** is an object. (or almost everything. Keep reading! 😜)

```ruby
$my_name = "Clancy Gilroy"
puts $my_name.class        # String

name = "X Æ A-12"
puts name.class            # String

age = 35
puts age.class             # Integer

gpa = 3.22                 
puts gpa.class             # Float 

had_fun = true
puts had_fun.class         # TrueClass

is_hot = false
puts is_hot.class          # FalseClass

week_points = nil
puts week_points.class     # NilClass (absence of value)

symbol = :hello
puts symbol.class          # Symbol 
```

Did you notice the `.class` method ? Since **Ruby is a Fully Object Oriented language** everything is an `object`, a `property of` or a `method call on` an object.

By the way and being shallow, **an object is the instance of a given class**. 

Think of a `class` like a **blueprint for creating objects**, which determines initial values, attributes, behavior etc.

![Class and Object](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dcnusiig06fo0nr653za.gif)

You can confirm the "almost everything is an object" theory using the `.superclass` method.

```ruby
puts TrueClass.superclass        # Object
puts Integer.superclass          # Object
puts String.superclass           # Object
puts Object.superclass           # BasicObject
# so on and so forth
```

#### Some (Useful) String Methods 💪

**Ruby** has many built-in methods to manipulate strings. 

Do you remember when I had mentioned that in **Ruby** things are similar to plain English? I bet you can guess what most of these methods below do, am I right? 😃

```ruby
phrase = "   Sometimes I’m confused by what I think is really obvious. But what I think is really obvious obviously isn’t obvious.   "

puts phrase.upcase
puts phrase.downcase

# hint: .strip removes the empty spaces from both beginning and ending.
puts phrase.strip    

puts phrase.length
puts phrase.include? "Some"
puts phrase.include? "Sure"
puts phrase.index("confused")

puts "auckland".capitalize
```
It is also possible to create both **interpolation** and **concatenation** of `strings`.

```ruby
character_age = "17"
character_name = "Link"

# Interpolation
puts "There once was a young man named #{character_name}"

# Concatenation ➕
# '.to_s' is the short method name for 'to string'
# There is more like '.to_i', '.to_f', '.to_a' etc
puts "he was " + character_age.to_s + " years old"
```
#### Some Math Methods 🔢🔣
```ruby

puts 5 + 9     # addition
puts 2 - 9     # subtraction
puts 6 * 9     # multiplication
puts 10 / 7.0  # division
puts 2 ** 3    # exponentiation
puts 3 % 2     # modulo or remainder

num = -163.23
num2 = 45.47

# returns the absolute number
puts num.abs                 # 163.23   

# return a value rounded to the nearest value with "n" digits decimal digits precision.
puts num2.round              # 45

# returns the ceil value
puts num2.ceil               # 46

# returns the floor value 
puts num2.floor              # 45

# returns the square root of a given number (5.0)
puts Math.sqrt(25)           # 5.0

# returns the natural logarithm (base e) or logarithm to the specified base of a given number, e.g. Math.log(x, base).
puts Math.log(100)           # 4.605170185988092
```

### Arrays 📚
 
**Ruby arrays** are collections of ordered, integer-indexed objects which can store numbers, strings, hashes, symbols, objects or even any other arrays.

```ruby
# different ways to declare an array
friends = Array["Rapha", "Alexandre", "Andre", "Bogus"]

# I prefer this one 👇
fruits_array = ["cherimoya", "durian", "lamut", "langsat" ]

# What the heck? 🤢
hello = Array.new(5, "awful").to_s 
# output: ["awful", "awful", "awful", "awful", "awful"]
puts hello 

# Remind: Ruby Arrays indexing starts at 0.
puts friends[0]      # Rapha
puts friends[-1]     # Bogus
puts friends[0,2]    # Rapha Alexandre

# Replacing items
friends[0] = "Fael"

# output: ["Fael", "Alexandre", "Andre", "Bogus"]
puts friends.to_s    

puts friends.length  # 4

# Down here the methods syntax are pretty much understandable
puts friends.include?("Fael")
puts friends.reverse
puts friends.sort
puts friends.empty?
puts fruits_array.push("rambutan")

## the example above (`push`) could also be done as shown below
fruits_array << "akebi"
```
The **Ruby arrays built-in methods** are not limited to just those ones I have mentioned above. 
If you are eager to learn more (I am sure you are 🤓), [Ruby docs](https://ruby-doc.org/core-3.0.2/Array.html) is a really good resource to do so.

### Hashes  #️⃣

**Ruby hashes** are collections of key-value pairs, for example: 

```ruby
random_hash = {
    :sao_paulo => "SP",
    "rio_de_janeiro" => "RJ",
    1 => "NY",
}
```
Remember that the way you declare the `key` is the same you will use in order to successfully access its `value` in a hash.

For example, trying to access `random_hash["sao_paulo"]` would return nothing because `:sao_paulo` is not the same as `"sao_paulo"`. (`Symbol`x `String`)

This is São Paulo, by the way! 🏙️
![Sao Paulo City](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kitrmfl9wultpa4xelep.jpg)

```ruby
puts random_hash
puts random_hash[:sao_paulo]       # SP
puts random_hash["rio_de_janeiro"] # RJ
puts random_hash[1]                # NY
puts random_hash.nil?              # false
puts random_hash.length            # 3
```

### Methods 📐📏

**Ruby methods** are used to tie or wrap together one or more repeatable statements into a single unit.

Along the article we have already used many methods, for example, `length`, `sqrt`, `to_s` etc. 

The difference here is that we have only invoked them. 
![Invoking](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00mml7h93ovj024wt99o.gif)

Someone, probably _Matz_, have already written them for us and for this reason they are the so called *built-in*.

![Matz](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ak497reug91gzqtnwgo6.jpg)

Even **Ruby** being an amazing language it is practically impossible to include every single method that we would use in our daily life. We are free to implement them by our own.

**Hint:** Method names should begin with a *lowercase letter*.

> "... If you begin a method name with an uppercase letter, Ruby might think that it is a constant and hence can parse the call incorrectly. "
[Source: Tutorials Point](http://www.tutorialspoint.com/ruby/ruby_methods.htm)

```ruby
# Method without parameter(s)

# This is how you declare a method
def say_konnichiwa
    puts "こんにちは"
end

# This is how you invoke it
say_konnichiwa

# Method with parameter(s)
def say_tadaima(title, name="Unknown")
    puts "ただいま, #{title} #{name}!"
end

say_tadaima("Mr.", "Toguro") # prints "ただいま, Mr. Toguro!"
```
Note that the second parameter `name` holds the **default value** `Unknown`. In other words, if we call the same method without providing the second argument, the default value will be put in place. Example below:

```ruby
say_tadaima("Mr.")           # prints "ただいま, Mr. Unknown!"
```
We can also `return` values from inside of our methods both explicitly or implicitly.

**- Explicit `return`:**
```ruby
def cube(num)
   return num * num * num, 70, "return", true, "?????"

   # Never reached
   puts "No value after the return statement is reached"
end

# IT will console the result of "num * num * num"
puts cube(3)

# Prints the number "70"
puts cube(3)[1]

# Prints the string "return" and so on
puts cube(3)[2]
```
**- Implicit `return`:**

```ruby
def always_return
    "I am always returned"
end

# Variable created for the sake of demonstration
result = always_return

puts result   # "I am always returned"
```
In other words, methods are most likely those relatives we don't like. They always return. (🥁 Tu dum tsss)


### Conditionals (`if`, `else` and `elsif`)

```ruby
is_dev = true
language = "Cobol"

if(is_dev && language == "Cobol")
    puts "DISPLAY 'Hello, Cobol'."
elsif (is_dev && language == "Pascal")
    puts "writeln('Hello, Pascal!');"
elsif (is_dev && language == "Delphi")
    puts "ShowMessage('Hello Delphi');"
else 
    puts "👋"
end
```
We can also use **comparisons** inside of `if / else` statements.

```ruby
def max_number(num1, num2, num3)
    if (num1 >= num2 and num1 >= num3)
        return num1
    elsif (num2 >= num1 and num2 >= num3)
        return num2
    else
        return num3
    end    
end

puts max_number(9, 53, 77)
```

### Case Expressions 💼

There is no mystery here. I am sure you can read this ~~master~~piece of code and guess what it does.
```ruby
def get_day_name(day_abbreviaton)
    day_name = ""

     case day_abbreviaton.downcase
    when "ma"
        day_name = "Maanantai"
    when "ti"
        day_name = "Tiistai"
    when "ke"
        day_name = "Keskiviikko"
    when "to"
        day_name = "Torstai"
    when "pe"
        day_name = "Perjantai"
    when "la"
        day_name = "Lauantai"
    when "sun"
        day_name = "Sunnuntai"
    else
        day_name = "En tiedä!"
    end

    # Implicit returns the value
    day_name

end

puts get_day_name("ma")      # Maanantai
puts get_day_name("koira")   # En tiedä!
```

### While Loops ↪️

```ruby
lucky_num = 70

# Note that the 'not' keyword is similar to '!=' (negation)
while not lucky_num == 77
    puts "No Lucky #{lucky_num}"

    lucky_num +=1
end
```

### Loops ↩️ 

```ruby
# You already know what is an array :)
people = ["C. Falcon", "Fox", "DK", "Ness", "Samus"]

# It will display all names in a different line
for person in people
    puts person
end

# Same same but ... same
people.each do |person|
    puts person
end

# Display numbers from range 0 to 5 (inclusive ..)
for inclusive in 0..5
    puts inclusive
end

# Display number from range 0 to 4 (exclusive ...)
for exclusive in 0...5
    puts exclusive
end   

# Let's agree: This is plain English
# PS.: counting starts from 0
6.times do |phrase|
    puts "Counting: #{phrase}"   
end
```

### Classes And Objects 📝 🛋️

This is my favorite part. Why? Because I remember when I have had my first contact with **OOP** (back in 2000's [btw, old are your ancestors 😠]) in `Java`. 
I was like: "What the heck is going on here?".
I got to understand it better because of the **Ruby** way of doing things.

![Raquer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbhnq5d4dff5lilgs72y.gif)

```ruby
## This is a very simple class
class Character
    attr_accessor :name, :role, :home
end

## This is a very simple way to create a new object
character = Character.new()
character.name = "Rygar"
character.role = "Searcher"
character.home = "Black Mountains"

puts character.name
```
Good that you asked (🔮), under the hood the `attr_...` creates the so famous `getters` and `setters` for you, for instance:

-`attr_accessor`: creates the `getter` and `setter` methods.
-`attr_reader`: creates only the `getter` method.
-`attr_writer`: creates only the `setter` method.

**TLDR;**
```ruby
# In other words this
attr_acessor :name

# Is the equivalent of
def name
    @name
end

def name=(value)
    @name = value
end

# Note: The equals sign is a Ruby convention when creating setters. 
# Omitting it is considering a bad practice but still works.
# (if it is working don't touch! 👍)
```

Cool, right? We have achieved so much just writing very few lines of code. I have to confess, when writing code using **Ruby** sometimes I feel like cheating. 
But, in my opinion, **Ruby** saves our time so we can worry about stuff that really matters.

Let's check an other manner to create a `class` in Ruby.

```ruby
class Shoes
    attr_accessor :brand, :size, :color

    # Allows you to set the initial values for a given object
    # Does 'constructor' sound familiar to you?
    def initialize(brand, size, color)
        @brand = brand
        @size = size
        @color = color        
    end

end

trainers = Shoes.new("Kichute", 47, "Heliotrope")
puts trainers.brand  # Kichute
```

### Object / Class Methods

```ruby
class Hero
    attr_accessor :name, :animal, :hp

    def initialize(name, animal, hp)
        @name = name
        @animal = animal
        @hp = hp
    end
    
    # It is a instance method (Good catch, Juan! 🏆)
    def has_enough_hp
        @hp > 5.5 ? "Able to play" : "Consider resting, #{@name}"
    end
end

hero1 = Hero.new("Nakoruru", "eagle", 80)
hero2 = Hero.new("Galford", "husky", 2.9)

# Here we have invoked the object(s) method
puts hero1.has_enough_hp      # Able to play
puts hero2.has_enough_hp      # Consider resting, Galford
```

### Class Inheritance (Shallow Explanation)

Allows classes to inherit characteristics of other classes.
 
```ruby
class Fighter
    def make_special_attack
        puts "Hadouken"
    end

    def make_uppercut_punch
        puts "Makes the uppercut move"
    end
end

ryu = Fighter.new()
ryu.make_special_attack          # Hadouken
ryu.make_uppercut_punch          # Makes the uppercut move

# Subclass - "<" means inherits from
class SpecialFighter < Fighter 
    
    # Overwrites 'make_special_attack' method
    def make_special_attack
        puts "Shun Goku Satsu"
    end

    # Creates a new method for this class
    def celebrate
        puts "Is that all? You must be joking!"
    end
end

gouki = SpecialFighter.new()
gouki.make_special_attack  # Shun Goku Satsu
gouki.make_uppercut_punch  # Makes the uppercut move
gouki.celebrate            # Is that all? You must be joking!
```
**Note:** as the `make_uppercut_punch` move is used by both characters there is no need to re-declare it in our `subclass`.

### Modules 🛒
Modules are nothing more nothing less than a container where you can store methods.

```ruby
module Greeting
    def say_hello(name="there")
        puts "Hi #{name}."
    end

    def say_bye_bye(name="dear")
        puts "Bye bye #{name}."
    end
end
```
In order to access modules you must include its relative path as the example shows:

```ruby
require_relative "./folder/the_name_of_your_file.rb"
include Greeting

Greeting.say_hello("Bowser")   # Hi Bowser.
```

### Error Handling ⛔

Error handlers are methods defined in the Exception class to deal with errors.  

```ruby
begin
    # we have never defined the 'fav_character' variable
    # so it will fire the second 'rescue' block
    # and will display the customized message even
    # knowing that we also tried to make a division by 0
    # => Reference to control flow for more <=

    fav_character["Makoto Mizuhara"]
    num = 45 / 0
rescue ZeroDivisionError => e
    puts e
    puts "Division By Zero Error"
rescue NameError
    puts "undefined local variable or method 'fav_character'."
end
```
If you would like to see the other `error handling` in action, replace the statement `fav_character["Makoto Mizuhara"]` for that one `fav_character = ["Makoto Mizuhara"]`. 😉

And that's it, folks! I mean, **Ruby** cannot be resumed by any means to the features I have shown so far but it is a pretty good start.

### Happy Hour Moment 🍹🍻🥤🍷

![Happy Hour](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmt0gfw7z3h7kj94tc9m.gif)

The good news here are that if you have followed along until the end (and thank you a ton for doing that! 🙏), you can already use the acquired knowledge to start exploring other 'seas'. For example, why don't you try to play around with **Rails** (one of Ruby frameworks) a little bit?

### Skip this part 📚 📖

I can see you did not skip it so don't you dare to complain later. 😂👌

> " The curiosity killed the cat."

Well, if you allow me to recommend an excellent source to learn about **Ruby on Rails**, I would advice the [Zayne's](https://www.youtube.com/channel/UCkoEStUK7wxmZef2DcPuCAQ) Youtube channel.
He doesn't publish videos very often but it really worth checking it out!

You can also check [Web Crunch](https://www.youtube.com/user/webcrunchblog), [Codemy](https://www.youtube.com/channel/UCFB0dxMudkws1q8w5NJEAmw), [FreeCodeCamp](https://www.youtube.com/watch?v=fmyvWz5TUWg&t=8890s) and of course the [Ruby Docs](https://www.ruby-lang.org/en/documentation/) and [Rails Guides](https://guides.rubyonrails.org/).

### Conclusion and Final Thoughts 🔚 💡

**Ruby** is without any doubts a very powerful, beginner friendly and lovely language. As any language, it has your flaws but don't be influenced by the __"which one is the best language?"__ war.
 
**Ruby** has been evolving a lot in the last years and counts with a very strong and respectful community that will help you whenever you need it.

I have tried to highlight some examples I **personally** consider important when 'meeting' **Ruby** for the very first time.

As you could see, the language speaks for itself. I venture to say that it is a `self.describing` language. (Pun intended 🤦)

Thanks so much for your companion. I hope you have learned something new today. (It doesn't necessarily mean from this article! 🤣)

Cheerio! 👋