bootrails.com is now moving to saaslit.com  See you there!
bootrails moves to  saaslit.com
Post

Ruby loops overview

What is a loop?

We can explain looping as the action of repeating the same thing over and over. In programming, as in real life, we need assembly lines. Imagine a cake factory that has a defined process: mix ingredients, bake cake, unmold cake, pour frosting and pack the cake. This process takes place every day 100 times. If the factory’s activity was translated into code and the process was defined in a method called “cake_process”, we could program each day as per below:

1
2
3
4
5
6
7
# DAY 1  
cake_process()  
cake_process()  
...  
# continue 97 times  
...  
cake_process()  

Or we could do something much simpler, loop 100 times through the baking method:

1
2
3
4
# DAY 1  
100.times do  
  cake_process()  
end  

Ruby loops

Looping is a key notion in Object-Oriented Programming languages, where creating instances according to the interface data is recurrent. In other words, looping is a feature that enables iteration through objects such as loop through array or loop through hash.

Ruby-on-Rails is specially well prepared for this purpose, as it comes with a set of helper methods that make looping very straightforward. These methods provide the logic of iteration as an abstraction of the code, so that the code stays more readable.

The most useful looping methods in Ruby

Let’s analyze the syntax of the different looping options that we have in Ruby. The goal is to understand when we should use each method.

for … in

Normally, we use for...in when we know the exact number of times that the loop needs to be executed.

For example:

1
2
3
4
5
6
7
8
ingredients = "eggs, flour, sugar, milk"  
  
for ingredients in 0..99 do  
p "First step is mix ingredients: #{ingredients}"  
end  
#=> First step is mix ingredients: eggs, flour, sugar, milk  
#=> First step is mix ingredients: eggs, flour, sugar, milk  
#=> ...  

Note that the action related to the variable ingredients will be executed 100 times as per the range (0..99) that includes both values, 0 and 99.

times

We have seen this method above in the article. It is very intuitive and it can be used to execute very simple tasks (see below) or more complex ones by passing a block.

1
2
# Simple syntax:  
5.times p "Hello"  

each and each_with_index

The method each is used to iterate through elements, when the elements run out, the loop ends. Hence, there is no need to specify a range or a number of times for the iterations.

1
2
3
4
5
6
ingredients.each do |ingredient|  
p "Add the #{ingredient}"  
end  
#=> Add the eggs  
#=> Add the flour  
#=> ...  

Remember that in this example we are using arrays, but you can also loop through hash or any other object.

If preferred, and if we want to keep track of the index position of the element, we can also use each_with_index:

1
2
3
4
5
6
ingredients.each_with_index do |ingredient, index|  
p "#{ingredient} is the #{index + 1} in the list."  
end  
#=> eggs is the 1 in the list.  
#=> flour is the 2 in the list.  
#=> ...  

Very similar is the map method; and it also allows looping with index.

each_with_object

In Object-Oriented Programming languages, the each_with_object can be very useful. For example, if we want to convert an array into a hash:

1
2
3
4
5
6
cakes = ["Brownie", "Cheesecake", "Brownie", "Brownie", "Carrotcake", "Cheesecake"]  
cakes.each_with_object(Hash.new(0)) do |element, hash|  
hash[element] += 1  
end  
  
#=> { "Brownie": 3, "Cheesecake": 2, "Carrotcake": 1 }  

To understand the logic here, we must know that the object that we pass is a hash, in which each element represents a key with value 0. Then, every time the loop finds the element on the array, it increases the value by one.

while and until

These methods are used when we want to iterate a number of times through an object but we don’t know it beforehand. In this cases we always need a variable (declared before the start of the loop) and a condition:

1
2
3
4
5
6
7
8
i = 0  
while i < 3  
p i  
i += 1  
end  
#=> 0  
#=> 1  
#=> 2  

Loop control

Loops allow a certain level of control from inside the block. This help us avoid complexity in some cases and also makes the code more readable. Let’s see an example with numbers and using the next and break keyword features:

1
2
3
4
5
6
7
8
9
10
11
12
13
i = 0  
  
while i < 100  
i += 1  
if i == 10  
p "hey this is 10"  
next  
end  
p i  
if i == 20  
break  
end  
end  

This would print the numbers from 1 to 9, then enter the if statement and print “hey this is 10” and skip the rest of the loop in this particular iteration because of the next keyword. Then the loop would resume with i=11 and continue printing numbers until 19. When i reaches 20, the if statement causes to stop the loop thanks to the break.

Conclusion

Mastering loops is very important. Ruby provides powerful methods that will help you keep your code DRY, save space, write code that is easy to navigate and create efficient Rails applications.

This post is licensed under CC BY 4.0 by the author.