Getting Started With Control Structures

Up until now we’ve only written a series of Ruby expressions that always evaluate every time we run the program. We’ll introduce control structures to give you more control over the flow of the code.

def check_health(health)
  if health < 10
    puts "Low health"
  else
    puts "Health OK"
  end
end

(irb) > check_health 10
Health OK
=> nil
(irb) > check_health 9
Low health
=> nil

You might also see if statements written at the end of an expression. The if statement is evaluated first, and the express to the left of it is only evaluated if the condition is true.

def check_health(health)
  puts "Low health" if health < 10
  puts "Health OK" if health >= 10
end

Both definitions of the method check_health will have the same output regardless of the arguments provided.

Loops are another example of a control structure. I don’t see pure loops in code as much as I thought I would when I was learning to write code years ago, but the idea of iterating over a block of code X number of times certainly does.

Here’s a simple while loop in Ruby. Notice the do keyword to start the block. Expressions between the do ... end block will be evaluated each time the loop iterates. The loop iterates until the expression i < 10 is false. In other words, while the expression i < 10 is true, do the block forever. It’s up to you to ensure that your loop will break out eventually.

i = 0
while i < 10 do
  puts i
  i += 1
end

Another common control structure is the “try catch” block. In Ruby this is written using the begin and rescue keywords. The idea is that you’ll have some questionable code inside of the begin block, and if there’s every a time when your code raises some exception, then the rescue block handles it.

begin
  remote_api_call()
rescue NetworkError => exception
  puts exception
end

If the remote_api_call method invokation does not raise a NetworkError exception, then the puts expression is never evaluated. Note that any other type of exception will not be caught in the previous example. To catch any type of exception, remove the exception type.

begin
  remote_api_call()
rescue => exception
  puts exception
end

Test the exception handler code by raising your own exception in the begin block.

puts 'before begin..end'
begin
  fail 'my code is broken'
  puts 'this is not printed because it comes after the exception is raised'
rescue => exception
  puts 'inside rescue block'
  puts exception
end
puts 'after begin..end'

Remove the fail line of code and rerun the program to find that the rescue block is not executed. We know this because of the sequence of outputs thanks to our well placed puts expressions.