Building an App Series Part 5: Logic and Flow Control

Launch Academy

By Launch Academy

February 1, 2022

The day was June 3, 2013, a day that will go down in social media infamy. Game of Thrones “The Rains of Castamere” episode aired the night before, where certain members of a certain family were brutally murdered. (Author’s note: If you have not read the books or watched the show, stop reading this and go do so. Now.) You check your Facebook and there’s TONS of posts from fans of the show, still in awe from the episode’s ending. There are even some noteworthy videos of people’s reactions, filled with screams, tears, and flying sofa cushions. You click “Like” on dozens of posts in a sign of solidarity because, let’s face it, it was an epic moment in television history. In a moment of unintentional, random clarity you wonder, “What happens on Facebook’s servers when I ‘Like’ someone’s Facebook post?””

When you click “Like” on Facebook posts, you are tailoring your relationships with other Facebook entities—whether they be your friends, companies, or spambots. The more you like an entity’s posts, the more visible they become on your News Feed.

Facebook makes use of conditional statements to determine what content appears on your News Feed. When developing web applications with ruby, we work with conditional statements on a regular basis, in concert with logical operators.Conditional statements guide the flow of logic within an application. Have you ever tried entering the admin section of your favorite website? You were most likely denied because a set of conditional statements prevented you from accessing it.

In this article, we will discuss how Ruby evaluates logical operators and conditional statements. We will also discuss how Ruby applications utilize flow control to guide logical directions within an application.

True or False

Ruby developers often utilize boolean values to delegate tasks within an application. It is important to become familiar with how Ruby evaluates truthiness in a given expression. Let’s look at a few examples.

number = 10
number < 15
=> true
number > 11
=> false

another_number = 12
another_number <= 12
=> true
another_number > 13
=> false

In these examples, we assign integers to variables and evaluate them against logic statements. If the variable satisfies the logic of the statement, it returns true. In the second example, 10 is obviously not greater than 11, and thus the statement returnsfalse.

Let’s breakdown a few examples pertaining to the evaluation of equality in Ruby.

number = 50

number == 50
=> true
number == 50 + 1
=> false
number != 25
=> true

Ruby uses == to determine equality. In the above examples, we assigned an integer to the variable number and provided statements to compare equality. Since the values are equal in the first example, the expression returns true. In the second example, number is clearly not equal to 51 and thus returns false. The third example utilizes the != operator, which in layman’s terms means not equal to.

In Ruby, evaluating the truth of an expression also applies to an object’s type. Let’s take a look at an example for some context.

var1 = "34"
var2 = 34
var1 == var2
=> false

The string "34" is indeed not equal to the integer 34. Keep this in mind when writing your applications. When debugging your code, you encounter scenarios where code is not evaluated because it is the wrong type.

For practice working with boolean values, check out this awesome guide from Learn Ruby The Hard Way.

For a more in depth guide to working with Ruby operators, check out this awesome guide from TutorialsPoint.

Flow Control

In order to efficiently write dynamic applications, developers control the flow of their applications by using conditional statements. A conditional statement defines a specific scenario that is only evaluated under true or false conditions. In Ruby, there are a number of types of conditional statements, which are best used in specific scenarios.

If/Else Conditional Statements

If/else conditional statements evaluate a given value against preset conditions to delegate an application’s behavior. Let’s look at an example for context.

def is_greater_than_fifty?(favorite_number)
  if favorite_number < 50
    puts "Your favorite number is less than 50."
  else
    puts "Your favorite number is 50 or greater."
  end
end

is_greater_than_fifty?(12)
=> Your favorite number is less than 50.
is_greater_than_fifty?(65)
=> Your favorite number is 50 or greater.

Here, we create a method that passes in a user’s favorite_number. When the user’s submission meets the criteria of theif statement, it displays the string “Your favorite number is less than 50.” If the user’s response does not satisfy the condition set forth in the if block, the else block of the conditional statement is evaluated.

If/else statements are often nested within one another. In the above example, we would probably need to protect against a user inputting a non-integer as a response.

def is_greater_than_fifty?(favorite_number)
  if favorite_number.integer?
    if favorite_number < 50
      puts "Your favorite number is less than 50."
    else
      puts "Your favorite number is 50 or greater."
    end
  else
    puts "Your response is not an integer."
  end
end

is_greater_than_fifty?("Liter of Cola")
=> Your response is not an integer.

Here, we have added a layer of protection to our code. If favorite_number.integer? is true, the logic within the ifblock is evaluated.

If/else conditional statements are best used in very specific scenarios. Throughout this series, we will see a number of scenarios where these statements will come in very handy.

While Loops

While loops—or wild loops as Launch Academy favorite Whitney likes to call them—are conditional statements that are repeatedly evaluated until the while statement’s condition is no longer true. As always, deciphering an example will give us some better context.

counter = 5
while counter <= 11
  counter = counter + 1
  puts "I've wanted to drive since the age of #{counter}."
end

I've wanted to drive since the age of 6.
I've wanted to drive since the age of 7.
I've wanted to drive since the age of 8.
I've wanted to drive since the age of 9.
I've wanted to drive since the age of 10.
I've wanted to drive since the age of 11.

Here, we initialize a counter variable. Each time the loop is executed, the value of counter increases by one and a string is evaluated with the iterated value.

Think about while loops in the context of an IndyCar race. There are a set amount of laps for every race. The drivers must go around the track the required number of laps in order to finish the race.

When building applications in Ruby, beware the infinite loop. Infinite loops occur when we write while conditional statements that are perpetually satisfied.

infinite_counter = 25
while infinite_counter < 26
  infinite_counter = infinite_counter - 1
  puts "This is the song that never ends…"
end

This is the song that never ends…
This is the song that never ends…
This is the song that never ends…
This is the song that never ends…
This is the song that never ends…
This is the song that never ends…
#and so on and so on

In theory, the above while loop would run forever. Here’s a very obvious, yet necessary pro tip: as a Ruby developer, you will never write an application that will need to run infinitely. Period.

If you are ever stuck in a while loop, hit CTRL + C on your keyboard to escape it.

Each Loops

In Ruby, we use each loops to apply methods and changes to elements of data structures. each loops are very important if you want to adjust multiple elements without repeating yourself. Let’s look at an example of using an each loop to iterate through an array of numbers.

numbers_array = [1, 3, 5, 7, 9]
numbers_array.each do |x|
  puts  x * 4
end
4
12
20
28
36

Above, we have taken each element—represented by x—of the numbers_array and multiplied them by four. It starts at the beginning of the data structure and applies the code that is between the do and end components of the loop. The loop stops itself after the last element has been retrieved and applied to the code block.

In the last article, we talked about how hashes are used to maintain key-value pairs. How would we iterate over a hash?

favorite_movie = {
  "Mikey" => "Troll 2",
  "Tommy" => "Trollhunter",
  "Adam" => "The Devil Wears Prada"
}
favorite_movie.each do |person, movie|
  puts "#{person}'s favorite movie is #{movie}."
end

Mikey's favorite movie is Troll 2.
Tommy's favorite movie is Trollhunter.
Adam's favorite movie is The Devil Wears Prada.

We can isolate elements of a hash, either keys or values, when we iterate through them with each loops. In the example above, Ruby allows us to access and manipulate the keys and values independent of one another. This is helpful for accessing and manipulating heavily nested data structures.

For practice working with complex data structures, check out this awesome gem called Rubies. Follow the instructions in the README to get started.

In Summary

Logical operators and flow control are foundational components of web applications, regardless of language. Good developers know how to use these functions to write dynamic applications without having to repeat themselves.

In the next article, we’ll introduce the Sinatra framework, discussing how it interacts with HTTP protocol. We’ll also discuss how we use HTML to render dynamic views.

Take a look at Sinatra’s official online documentation for a primer.

Challenge

Since I love The Wire so much, we’re going to use the example from Part 4.

characters = {
  "Omar Little" => {
    "friends" => ["Butchie", "Jimmy McNulty"],
    "enemies" => ["Avon Barksdale", "Stringer Bell", "Marlo Stanfield", "Chris Partlow", "Snoop Pearson"],
  },
  "Lester Freamon" => {
    "friends" => ["Roland Pryzbylewski", "Jimmy McNulty", "Bunk Moreland", "Cedric Daniels"],
    "hobbies" => ["crafting model furniture", "solving crimes", "putting drug dealers in jail"]
  }
}

Given the above data structure, write a program that outputs all of Lester Freamon’s friends and hobbies. Your program should output:

  • Lester Freamon loves Roland Pryzbylewski.
  • Lester Freamon loves Jimmy McNulty.
  • Lester Freamon loves Bunk Moreland.
  • Lester Freamon loves Cedric Daniels.
  • Lester Freamon loves crafting model furniture.
  • Lester Freamon loves solving crimes.
  • Lester Freamon loves putting drug dealers in jail.

Hint: You will have to utilize nested conditional statements.