Variables

We are going to start with variables. Variable is a storage location with an associated name. For example x = 10 means that we allocated some memory, put something in it (in our case we put number 10 inside), and called it `X`, to make it easier to use this object in the future.

Different programming languages have different variable types (e.g., string, number, arrays, etc.). Some languages want you to specify variable's type (e.g. string x = "Hello"), and some don't.

Since Ruby is a dynamic language, you can change variable's type later. It can be a number in the beginning, and in the future, it can become a string. Here is an entirely correct code:

        x = 10
        x = "Now I'm a string!"
      

Let's start programming. Ruby has an interactive shell that allows us to execute commands on it. It is an excellent tool for learning and testing. Just open your terminal, and type irb:

Ruby knows how to do primary arithmetic operations. Try to do some simple operations. Each command will return a value, which will be printed below your command. Try them in irb:

        1 + 100
        100 / 20
        (5 + 6) - 1 + (4515 / 5)
        "String 1" + "String 2"
        "A" + "B" + "2"
        "A" + "B" + 2
      

The last command has returned an error - it says it could not figure out how to add a number to a string. Before doing something like this, you need to be sure that command is logically correct. Otherwise, it will return an error, or will crash an app.

So why did "A" + "B" + "2" work, and "A" + "B" + 2 did not? The difference between both expressions is that the first one has quotes around number 2, which means that it is not a number, but a string. You can add string to the string, but Ruby does not know how to add a number to a string. To make it work, you will need to convert a number into a string. We will come back to it later.

So, let's make our first variable. To make a variable, give it a name first, then add `=` sign, and tell Ruby what to you want to assign to your new variable. Variable names can contain alphabet letters, numbers, and symbols like - or _. Variable names can't start with a digit, though. Let's make three variables that will represent John's age, Ann's age, and Steve's age. John is 28, Ann is 26, and Steve is 31. How would you calculate their average age with Ruby?

        john_age = 28
        ann_age = 26
        steve_age = 31
        average_age = (john_age + ann_age + steve_age) / 3
      

Ruby thinks the average age is 28, that is correct if we want to get a rounded, or integer value. However, the real average is slightly higher. So, where is the problem? We were using all integers, and Ruby decided that result should also be an integer. But what if we want to have an exact answer, with decimals? Let's make one value in our expression a decimal value. In this case, Ruby returns a correct value:

        average_age = (john_age + ann_age + steve_age) / 3.0
      

Data types

There are Booleans, Symbols, Numbers, Strings, Arrays and Hashes in Ruby.

Boolean

The boolean data type is very straightforward. Boolean variables can be `true` or `false`. We will use it a lot with conditional statements, for example:

        john_likes_pizza = true

        if john_likes_pizza
          # some code to get a pizza
        else
          # some code to get a burger
        end
      

Boolean is also used as a result of some expressions, like

        # one equals one:
        1 == 1

        # five less than six:
        5 < 6

        # five less or equals six:
        5 >= 6
      

(in this example, == can be read as "is equal". Single `=` is used to assign value to a variable, and double `=` sign is used to compare variables).

Strings

Strings are sets of characters. To create a string, you can use single quotes ', or double quotes ":

        name = "John"
        name = 'John'
      

The difference is that double-quoted strings can be interpolated, which means that you can put a variable inside, and it will be converted to its value. Make sure to use #{} for your variable - this expression will tell Ruby that variable has to be interpolated. For example:

        name = "John"
        "Hi, my name is #{name}"
        'Hi, my name is #{name}'
        'Hi, my name is ' + name
      

As you can see, Ruby successfuly converted a variable name to its value in a first example, with double quotes. The second example did not change our string; it just returned whatever we entered. The third example shows that strings can be added to each other, just like numbers - this action called concatenation.

You can also multiply strings:

        "Hey! " * 3

Sometimes you may need to get a substring of a string. For example, we have a string "ABCDEFG", and we need to get "ABC" substring:

        str = "ABCDEFG"
      
This is pretty easy in Ruby. To get a substring, we need to specify a range of characters inside the main string. To do it, you also need to know that all indexes start from 0 in Ruby. It means that first character has index 0, second - 1, and so on. To get the first character, we would use:
        first_character = str[0]
        # => "A"
      
To get first three characters, we would use:
        abc = str[0..2]
        # => "ABC"
      
We can also use negative indexes: index of a last element would be -1, element before it would be -2, etc:
        new_str = str[3..-2]
        # => "DEF"
      

You can always find all available info about Strings on ruby-doc. For example, how to reverse your string, or to make all characters capitalized, how to search for a substrings index and much more.

Symbols

Symbols may look like a string, but they are different. To create a symbol, you need to use : instead of quotes. For example:

        order_status = :new
      
Second, you can't change or update symbols. They can't be added to each other, subtracted, multiplied or divided. Usually we use symbols to represent some kind of state:
        order_status = :new
        order_status = :active
        order_status = :shipped

Interesting thing about symbols: same symbols, even if they are assigned to different variables, will be a same object. It means that unlike strings, all same symbols are one exact object, and all variables that use it actually point to one location in memory. You can use `object_id` method to check it:

        str = "String!"
        sym = :symb
        str2 = "String!"
        sym2 = :symb
        str.object_id == str2.object_id
        sym.object_id  == sym2.object_id
      

Please also visit ruby-doc for more info on Symbols.

Numbers

There are different Number types in Ruby:

All numbers can be positive or negative, and you can do all kind of arithmetic operations with them, such as subtractions, multiplications, etc.

You can convert integers to floats and vice-versa with `to_i` or `to_f` methods. For example:

        0.95.to_i
        5.to_f
      

More info on integers (Fixnum class) and floats can be found in docs.

Rational numbers represent exact numbers, without rounding errors, for example, 3/4, 15/124, etc. You can also think of rational numbers as a fraction of two integers: a/b, where b can't be zero. To create a rational number, we can use `to_r` method.

        1.to_r
        0.23.to_r
        0.25.to_r
      

You can always find more info on rational numbers in docs.

Arrays

Arrays are collections of objects. You can add whatever you want to it: strings, numbers, other arrays, hashes, etc. To create an array, following syntax:

        my_array = [ 1, "two", 3.0, [ 4, 5 ] ]
      

To access an object in the array, you need to specify object's index in the array in square brackets. Remember that indexes start from zero, so if you want to get the first element, use my_array[0], to get third - my_array[2]. You can also use indexes to get objects from the end of the array. Th last object has index -1, object before it has an index -2, and so on. If we want to create a new variable with value of the last object in our array, we will use next:

        last_object = my_array[-1]
      

There are also lots of useful methods to find an object in an array by its value, get an index of some object with given value, etc. Try to play with next commands:

        # find object in array that is less than three:
        my_array.find { |obj| obj.to_i < 3 }

        # get index of object "two":
        my_array.index("two")

        # check if array includes object 3.0:
        my_array.include? 3.0

        # add new object to the end of array:
        my_array.push :new

        # get number of objects in array:
        my_array.count

        # get array with reverse objects positions:
        my_array.reverse
      

You can always find more info on arrays by visiting ruby-doc.

Hashes

Hashes are collections of objects, just like Arrays. But they are dictionary-like collections. It means we will use a key instead of an index to access some element inside of it. The key can be a string, symbol or a number.

To create a new hash, you will need to use another type of brackets - {}. To assign a value to a key, you will need to use =>. If you use Symbol as a key, you can just transform it from :key to key:, and Ruby will understand that this is a Symbol used as a key.

Let's create our first hash:

        hash = { "first" => 1, second: 2, 3 => "third" }
      

As with arrays or strings, to get an element inside of a hash, just use square brackets, and specify a key. For example: hash[:second]. Same with assigning new values for existing or new keys:

        hash[:fourth] = "4"
        hash["first"] = [ 1, 2, 3 ]
      

As usual, more info on Hashes can be found ruby-doc.org

Additional

All Ruby objects have lots of important methods that will help you to work with different data types.

As you already know, all data types are different - they have different properties, different purposes, some actions that you can apply to one data type can't be applied to another one, etc.

This adds some layer of complexity: you need to be sure that variable has the exact data type as you expect. For example, you can add some characters to the String, but you can't add them to Symbol.

Sometimes you may not be sure if a variable has the expected data type. For example, you send request to a web server, and you expect it to return Weather forecast for today, that would look like a Hash:

        forecast = { min: 10, max: 13, wind: 4 }
      
But instead, it responded with an error:
        forecast = { error: "Wrong Date" }

Inside of the code, you can't see whether the response is correct or not. You will need to check whether variable looks like you expect; for example, check if it has the proper class, the correct number of values, and more.

First, we could check if response is actually a Hash. Every Ruby object has very helpful methods is_a?() and class:

        response.class
        # => Hash
        response.is_a?(Hash)
        # => true
      

It helped us to confirm that response in both cases is a Hash, that is good. We can continue our investigation. Now we could check whether some key inside a Hash exists. There is a Nil Object in Ruby. It represents emptiness - if some variable equals nil, it means that variable has no real value. So before using our forecast data, we need to check whether it exists. We can do it in many ways:

        response[:min].is_a?(Number)
        response[:min].nil?
        response.has_key?(:min)
      

Some of these actions can be applied to Hash only, and if your response would be a String for some reason, and you would call .has_key? on it, it would crash the app. This is why we had to check that we are dealing with Hash in the first place. So let's see what error response would return for all those commands:

We just confirmed that response variable is a correct response, that we could use in the app. In the next chapter we are going to learn what is the Block, and how can we use it. You've seen them already in this chapter in methods like:

        # find object in array that is less than three:
        my_array.find { |obj| obj.to_i < 3 }
      

Book Index | Next