- Conditionally execute code with
if/else
andcase/when
statements - Use statement modifiers to write cleaner Ruby code
In the last lesson, we saw how to use comparison methods and logical operators
in Ruby. In this lesson, we'll see more examples of how to use those tools to
perform control flow using conditional statements with the if/else
and
case/when
keywords.
Make sure to code along with the Ruby examples in IRB to help get a feel for the syntax.
Ruby has slightly different syntax for writing conditional statements using
if/else
than JavaScript. Here's a relatively complex if/else
statement in
JavaScript:
// JavaScript
let dog = "cuddly";
let owner;
if (dog === "hungry") {
owner = "Refilling food bowl.";
} else if (dog === "thirsty") {
owner = "Refilling water bowl.";
} else if (dog === "playful") {
owner = "Playing tug-of-war.";
} else if (dog === "cuddly") {
owner = "Snuggling.";
} else {
owner = "Reading newspaper.";
}
Here's how we can write the equivalent statement in Ruby:
# Ruby
dog = "cuddly"
if dog == "hungry"
owner = "Refilling food bowl."
elsif dog == "thirsty"
owner = "Refilling water bowl."
elsif dog == "playful"
owner = "Playing tug-of-war."
elsif dog == "cuddly"
owner = "Snuggling."
else
owner = "Reading newspaper."
end
In Ruby, unlike JavaScript, if/else
statements
have a return value, which means we could refactor the code
above as follows:
dog = "cuddly"
owner = if dog == "hungry"
"Refilling food bowl."
elsif dog == "thirsty"
"Refilling water bowl."
elsif dog == "playful"
"Playing tug-of-war."
elsif dog == "cuddly"
"Snuggling."
else
"Reading newspaper."
end
In addition to the if
keyword, Ruby also has the unless
keyword, which acts
as the opposite of if
:
timer = 15
unless timer == 0
puts "Still cooking"
end
You could write the equivalent with an if
statement and a negative condition:
timer = 15
if timer != 0
puts "Still cooking"
end
But you'll find that the first example is a bit nicer to read.
In order to use control flow effectively, it's important to know what values Ruby treats as "truthy" and "falsy".
As we saw in the lesson on data types, there are only two values Ruby considers
falsy: false
and nil
. Using those values in control flow means the condition
will be false:
def control_flow(value)
if value
# if the value is truthy
puts "yep!"
else
# if the value is falsy
puts "nope!"
end
end
control_flow(false)
# => "nope!"
control_flow(nil)
# => "nope!"
control_flow(true)
# => "yep!"
control_flow("")
# => "yep!"
control_flow(0)
# => "yep!"
One more nice feature of the Ruby language is the ability to use statement modifiers and write conditions at the end of a line of code. For short, one-line conditions, it can improve the readability of your code. For example, you could rewrite this example:
this_year = Time.now.year
if this_year == 2046
puts "Hey, it's 2046!"
end
Using a statement modifier:
this_year = Time.now.year
puts "Hey, it's 2046!" if this_year == 2046
unless
can also be used as a statement modifier:
fav_cookie = "Chocolate Chip"
puts "Your opinion is invalid" unless fav_cookie == "Chocolate Chip"
Last but not least, Ruby also has case
statements, which are used to run
multiple conditions against one value. As a reminder, case
statements can be
useful as a replacement for if/else
statements,
when all the conditions use the same comparison. Here's a
side-by-side example with Ruby and JavaScript:
// JavaScript
let dog = "cuddly";
let owner;
switch (dog) {
case "hungry":
owner = "Refilling food bowl.";
break;
case "thirsty":
owner = "Refilling water bowl.";
break;
case "playful":
owner = "Playing tug-of-war.";
break;
case "cuddly":
owner = "Snuggling.";
break;
default:
owner = "Reading newspaper.";
break;
}
And in Ruby:
# Ruby
dog = "cuddly"
case dog
when "hungry"
owner = "Refilling food bowl."
when "thirsty"
owner = "Refilling water bowl."
when "playful"
owner = "Playing tug-of-war."
when "cuddly"
owner = "Snuggling."
else
owner = "Reading newspaper."
end
case
statements, like if
statements, also produce a return value, so again,
we could refactor this Ruby example:
dog = "cuddly"
owner = case dog
when "hungry"
"Refilling food bowl."
when "thirsty"
"Refilling water bowl."
when "playful"
"Playing tug-of-war."
when "cuddly"
"Snuggling."
else
"Reading newspaper."
end
You can also use then
with when
to shorten up each condition to a single line:
dog = "cuddly"
owner = case dog
when "hungry" then "Refilling food bowl."
when "thirsty" then "Refilling water bowl."
when "playful" then "Playing tug-of-war."
when "cuddly" then "Snuggling."
else "Reading newspaper."
end
Time to get some practice! Write your code in the control_flow.rb
file. Run
learn test
to check your work. Your goal is to practice using control flow in
Ruby to familiarize yourself with the syntax. There is a JavaScript version of
the solution for each of these deliverables in the js/index.js
file you can
look at (but if you want an extra challenge, try solving them in Ruby without
looking at the JavaScript solution).
Write a method #admin_login
that takes two arguments, a username and a
password. If the username is "admin" or "ADMIN" and the password is "12345",
return "Access granted". Otherwise, return "Access denied".
admin_login("sudo", "12345")
# => "Access denied"
admin_login("admin", "12345")
# => "Access granted"
admin_login("ADMIN", "12345")
# => "Access granted"
Write a method #hows_the_weather
that takes in one argument, a temperature.
If the temperature is below 40, return "It's brisk out there!". If the
temperature is between 40 and 65, return "It's a little chilly out there!".
If the temperature is above 85, return "It's too dang hot out there!".
Otherwise, return "It's perfect out there!"
hows_the_weather(33)
# => "Brisk!"
hows_the_weather(99)
# => "Too dang hot"
hows_the_weather(75)
# => "Perfect!"
Write a method #fizzbuzz
takes in a number. For multiples of three, return
"Fizz" instead of the number. For the multiples of five, return "Buzz". For
numbers which are multiples of both three and five, return "FizzBuzz". For
all other numbers, just return the number itself.
fizzbuzz(1)
# 1
fizzbuzz(2)
# 2
fizzbuzz(3)
# Fizz
fizzbuzz(4)
# 4
fizzbuzz(5)
# Buzz
fizzbuzz(15)
Write a method #calculator
that takes three arguments: an operation and two
numbers. If the operation is one of the following: +
, -
, *
, or /
,
return the value of calling the operation on the two numbers. Otherwise,
output a message saying "Invalid operation!" and return nil
.
calculator("+", 1, 1)
# => 2
calculator("-", 3, 1)
# => 2
calculator("*", 3, 2)
# => 6
calculator("/", 4, 2)
# => 2
calculator("nope", 4, 2)
# "Invalid operation!"
# => nil
Since you're already familiar with these control flow structures from
JavaScript, you should have a good intuition of when it's appropriate to use
these different tools. Try and develop familiarity with the differences in
syntax between JavaScript and Ruby first, so that you'll be able to take
advantage of some of Ruby's unique features like statement modifiers and the
unless
keyword in your own code.
One excellent resource for familiarizing yourself with the syntax and the preferred conventions of some Rubyists is the Ruby style guide. Make sure to bookmark this resource and refer to it if you're ever unsure how to format a particular block of code.