DEV Community

loading...
Cover image for Ruby Basics

Ruby Basics

Vinicius Cerqueira Bonifácio
JavaScript developer, technology passionate, Ubuntu evangelist, ex mountain guide, active football player, inactive surfer, professional backpacker and hitchhiker.
・13 min read

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

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

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

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

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:

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:

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

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

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

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

Installing Ruby

Just kidding, you can use the Ruby Online Compiler & Interpreter - Replit. 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

Starts here

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.

=begin
   Dale a tu cuerpo alegria Macarena
   Eeeh Macarena .... 
   Aaahe!
=end
Enter fullscreen mode Exit fullscreen mode

You can also have an one-line comment using the #.

# Never gonna give you up, never gonna let you down ...
Enter fullscreen mode Exit fullscreen mode

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.

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 
Enter fullscreen mode Exit fullscreen mode

Variables 📦

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

    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!"
Enter fullscreen mode Exit fullscreen mode

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! 😜)

$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 
Enter fullscreen mode Exit fullscreen mode

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

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

puts TrueClass.superclass        # Object
puts Integer.superclass          # Object
puts String.superclass           # Object
puts Object.superclass           # BasicObject
# so on and so forth
Enter fullscreen mode Exit fullscreen mode

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? 😃

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
Enter fullscreen mode Exit fullscreen mode

It is also possible to create both interpolation and concatenation of strings.

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"
Enter fullscreen mode Exit fullscreen mode

Some Math Methods 🔢🔣


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
Enter fullscreen mode Exit fullscreen mode

Arrays 📚

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

# 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"
Enter fullscreen mode Exit fullscreen mode

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 is a really good resource to do so.

Hashes #️⃣

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

random_hash = {
    :sao_paulo => "SP",
    "rio_de_janeiro" => "RJ",
    1 => "NY",
}
Enter fullscreen mode Exit fullscreen mode

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". (Symbolx String)

This is São Paulo, by the way! 🏙️
Sao Paulo City

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
Enter fullscreen mode Exit fullscreen mode

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

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

Matz

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

# 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!"
Enter fullscreen mode Exit fullscreen mode

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:

say_tadaima("Mr.")           # prints "ただいま, Mr. Unknown!"
Enter fullscreen mode Exit fullscreen mode

We can also return values from inside of our methods both explicitly or implicitly.

- Explicit return:

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]
Enter fullscreen mode Exit fullscreen mode

- Implicit return:

def always_return
    "I am always returned"
end

# Variable created for the sake of demonstration
result = always_return

puts result   # "I am always returned"
Enter fullscreen mode Exit fullscreen mode

In other words, methods are most likely those relatives we don't like. They always return. (🥁 Tu dum tsss)

Conditionals (if, else and elsif)

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
Enter fullscreen mode Exit fullscreen mode

We can also use comparisons inside of if / else statements.

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)
Enter fullscreen mode Exit fullscreen mode

Case Expressions 💼

There is no mystery here. I am sure you can read this masterpiece of code and guess what it does.

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ä!
Enter fullscreen mode Exit fullscreen mode

While Loops ↪️

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
Enter fullscreen mode Exit fullscreen mode

Loops ↩️

# 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
Enter fullscreen mode Exit fullscreen mode

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

## 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
Enter fullscreen mode Exit fullscreen mode

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;

# 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! 👍)
Enter fullscreen mode Exit fullscreen mode

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.

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
Enter fullscreen mode Exit fullscreen mode

Object / Class Methods

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
Enter fullscreen mode Exit fullscreen mode

Class Inheritance (Shallow Explanation)

Allows classes to inherit characteristics of other classes.

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!
Enter fullscreen mode Exit fullscreen mode

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.

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

    def say_bye_bye(name="dear")
        puts "Bye bye #{name}."
    end
end
Enter fullscreen mode Exit fullscreen mode

In order to access modules you must include its relative path as the example shows:

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

Greeting.say_hello("Bowser")   # Hi Bowser.
Enter fullscreen mode Exit fullscreen mode

Error Handling ⛔

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

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
Enter fullscreen mode Exit fullscreen mode

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

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 Youtube channel.
He doesn't publish videos very often but it really worth checking it out!

You can also check Web Crunch, Codemy, FreeCodeCamp and of course the Ruby Docs and Rails Guides.

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! 👋

Discussion (4)

Collapse
juanvqz profile image
Juan Vasquez • Edited

Hi! Great post, you won a follower.

In Japan gift, I was thinking to put a Pikachu gift but I'm not sure.

The irb online link doesn't redirect me to that it redirects me to the same post.

In the Object / Class methods you said the has_enough_hp method is a class method but it is an instance method.

Keep posting, thanks! ✌️

Collapse
vinicius77 profile image
Vinicius Cerqueira Bonifácio Author • Edited

Thanks again, Juan! 🙏🏻

It is a pleasure having you aboard!!

  • In your honor I have upload the Pikachu gift! 🥳 🎉
  • I have just correct the links. I hope they work properly now! :)
  • Good catch about the class method error. I have got too excited to talk about classes that not even see it coming! 🤣 🤣 🤣

Again, thanks a ton for your collaboration and have a nice weekend! 🌞

Collapse
juanvqz profile image
Juan Vasquez

I just noticed any link works as expected I just click the zayne’s YouTube channel didn't work.

Collapse
vinicius77 profile image
Vinicius Cerqueira Bonifácio Author

Thanks, Juan!

I have just fixed all the links. I was using a wrong one as example and I end up replicating the error in all of them. Jeje 😅