- Conditionally execute code with
if/elseandcase/whenstatements - 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."
endIn 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."
endIn 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"
endYou could write the equivalent with an if statement and a negative condition:
timer = 15
if timer != 0
puts "Still cooking"
endBut 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!"
endUsing a statement modifier:
this_year = Time.now.year
puts "Hey, it's 2046!" if this_year == 2046unless 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."
endcase 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."
endYou 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."
endTime to get some practice! Write your code in the control_flow.rb file. Run
bin/rspec 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!"
# => nilSince 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.