OdinSchool OdinSchool
Control Structures in Ruby

Control Structures in Ruby

Conditional statements are used to alter the logic of the execution of the flow based on certain conditions. Here are a few conditional statements available to developers as a part of ruby.

Ruby if statement

The block of code mentioned in the if statement is executed only when the condition mentioned in the if statement becomes true.

age = gets.chomp.to_i   
if age >= 18
puts "You are eligible to vote."
end

Flip-Flop operator

The flip-flop operator is used between two conditions in a conditional statement

(1..5).select do |e|
e if (e == 2) .. (e == 4)
end
# => [2, 3, 4]

The condition evaluates to false until the first part becomes true. Then it evaluates to true until the second part becomes true. After that it switches to false again.

This example illustrates what is being selected:

[1, 2, 2, 3, 4, 4, 5].select do |e|
e if (e == 2) .. (e == 4)
end
# => [2, 2, 3, 4]

The flip-flop operator only works inside ifs (including unless) and ternary operator. Otherwise it is being considered as the range operator.

(1..5).select do |e|
(e == 2) .. (e == 4)
end
# => ArgumentError: bad value for range

It can switch from false to true and backwards multiple times:

((1..5).to_a * 2).select do |e|
e if (e == 2) .. (e == 4)
end
# => [2, 3, 4, 2, 3, 4]

while

A while loop keeps executing the code block till the conditional statement is rendered false:

i = 0
while i < 5
puts "Iteration ##{i}"
i +=1
end

Until statement

An until loop keeps executing the code block till the conditional statement is rendered true:

i = 0
until i == 5
puts "Iteration ##{i}"
i +=1
end

Loop control with break, next, and redo

The flow of execution of a Ruby block may be controlled with the break, next, and redo statements.

A break statement terminates an ongoing iteration and stops the further iterations of the loop. It is used in conditions when we want the compiler to completely come out of the loop:

actions = %w(run jump swim exit macarena)
index = 0

while index < actions.length
action = actions[index]

break if action == "exit"

index += 1
puts "Currently doing this action: #{action}"
end

# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim

The next statement terminates the ongoing iteration and starts with the next iteration immediately:

actions = %w(run jump swim rest macarena)
index = 0

while index < actions.length
action = actions[index]
index += 1

next if action == "rest"

puts "Currently doing this action: #{action}"
end

# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim
# Currently doing this action: macarena

The redo statement terminates the ongoing statement and reiterates the terminated iteration:

actions = %w(run jump swim sleep macarena)
index = 0
repeat_count = 0

while index < actions.length
action = actions[index]
puts "Currently doing this action: #{action}"

if action == "sleep"
repeat_count += 1
redo if repeat_count < 3
end

index += 1
end

# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim
# Currently doing this action: sleep
# Currently doing this action: sleep
# Currently doing this action: sleep
# Currently doing this action: macarena

Block result values

In both the break and next statements, a value may be provided, and will be used as a block result value:

even_value = for value in [1, 2, 3]
break value if value.even?
end

puts "The first even value is: #{even_value}"

# The first even value is: 2

return vs. next: non-local return in a block

Consider this broken snippet:

def foo
bar = [1, 2, 3, 4].map do |x|
return 0 if x.even?
x
end
puts 'baz'
bar
end
foo # => 0

One might expect return to yield a value for map's array of block results. So the return value of foo would be [1, 0, 3, 0]. Instead, return returns a value from the method foo. Notice that baz isn't printed, which means execution never reached that line.

next with a value does the trick. It acts as a block-level return.

def foo
bar = [1, 2, 3, 4].map do |x|
next 0 if x.even?
x
end
puts 'baz'
bar
end
foo # baz
# => [1, 0, 3, 0]

In the absence of a return, the value returned by the block is the value of its last expression.

Ruby if else

The code in if block is executed if the conditional statement is true. The else block is executed if the condition is false.

age = gets.chomp.to_i   
if age >= 18
puts "You are eligible to vote."
else
puts "You are not eligible to vote."
end

Ruby if else if (elsif)

Ruby if else if statement tests the condition. The if block statement is executed if condition is true otherwise else block statement is executed.

age = gets.chomp.to_i
if age > 0 and age <= 2
puts "baby"
elsif age >= 3 and age <= 12
puts "child"
elsif age >=13 and age <= 19
puts "teenager"
elsif age >= 20 and age <= 60
puts "adult"
else
puts "old"
end