Skip
Arish's avatar

11. Control Flow


Control Flow in Ruby

Control flow statements let you control how your program executes based on conditions. Ruby offers elegant and readable ways to handle conditionals and loops.

If/Else Statements

The most common way to handle conditions:

ruby
1age = 25
2
3if age >= 18
4  puts "You are an adult"
5elsif age >= 13
6  puts "You are a teenager"
7else
8  puts "You are a child"
9end
10
11# Single line (for simple conditions)
12puts "Welcome!" if age >= 18
13
14# Ternary operator
15status = age >= 18 ? "adult" : "minor"

Unless Statement

unless is the opposite of if - it executes when the condition is false:

ruby
1logged_in = false
2
3unless logged_in
4  puts "Please log in"
5end
6
7# Same as:
8if !logged_in
9  puts "Please log in"
10end
11
12# Single line
13redirect_to login_path unless logged_in

Case Statement

Perfect for multiple conditions on the same variable:

ruby
1day = "Monday"
2
3case day
4when "Monday"
5  puts "Start of the work week"
6when "Friday"
7  puts "TGIF!"
8when "Saturday", "Sunday"
9  puts "Weekend!"
10else
11  puts "Regular day"
12end
13
14# Case with ranges
15age = 25
16
17case age
18when 0..12
19  "child"
20when 13..19
21  "teenager"
22when 20..64
23  "adult"
24else
25  "senior"
26end
27
28# Case with types
29value = "hello"
30
31case value
32when String
33  puts "It's a string"
34when Integer
35  puts "It's a number"
36when Array
37  puts "It's an array"
38end

Loops

While Loop

ruby
1count = 0
2
3while count < 5
4  puts count
5  count += 1
6end
7# Output: 0, 1, 2, 3, 4

Until Loop

ruby
1count = 0
2
3until count >= 5
4  puts count
5  count += 1
6end
7# Output: 0, 1, 2, 3, 4

For Loop (rarely used in Ruby)

ruby
1for i in 1..5
2  puts i
3end

Loop with Break

ruby
1count = 0
2
3loop do
4  count += 1
5  puts count
6  break if count >= 5
7end

Iterators (The Ruby Way)

Ruby developers prefer iterators over traditional loops:

Each

ruby
1# Iterating over arrays
2fruits = ["apple", "banana", "cherry"]
3
4fruits.each do |fruit|
5  puts "I love #{fruit}!"
6end
7
8# With index
9fruits.each_with_index do |fruit, index|
10  puts "#{index + 1}. #{fruit}"
11end
12
13# Iterating over hashes
14user = { name: "John", age: 30 }
15
16user.each do |key, value|
17  puts "#{key}: #{value}"
18end

Times

ruby
15.times do |i|
2  puts "Iteration #{i}"
3end
4# Output: Iteration 0, 1, 2, 3, 4
5
6# Without block variable
73.times { puts "Hello!" }

Upto and Downto

ruby
11.upto(5) { |n| puts n }    # 1, 2, 3, 4, 5
25.downto(1) { |n| puts n }  # 5, 4, 3, 2, 1

Step

ruby
1# Count by 2s
20.step(10, 2) { |n| puts n }
3# Output: 0, 2, 4, 6, 8, 10

Loop Control

Break

Exit the loop immediately:

ruby
1numbers = [1, 2, 3, 4, 5]
2
3numbers.each do |n|
4  break if n == 3
5  puts n
6end
7# Output: 1, 2

Next

Skip to the next iteration:

ruby
1numbers = [1, 2, 3, 4, 5]
2
3numbers.each do |n|
4  next if n.even?
5  puts n
6end
7# Output: 1, 3, 5

Redo

Restart the current iteration:

ruby
1count = 0
2
35.times do |i|
4  count += 1
5  puts "Attempt #{count} for iteration #{i}"
6  redo if count < 3 && i == 0
7end

Guard Clauses

Use early returns to simplify code:

ruby
1# Instead of nested ifs
2def process_order(order)
3  if order
4    if order.valid?
5      if order.items.any?
6        # Process the order
7      end
8    end
9  end
10end
11
12# Use guard clauses
13def process_order(order)
14  return unless order
15  return unless order.valid?
16  return if order.items.empty?
17  
18  # Process the order (the happy path)
19end

Truthy and Falsy Values

Remember Ruby's unique truthiness:

ruby
1# Only nil and false are falsy
2# Everything else is truthy (including 0, "", and [])
3
4if 0
5  puts "0 is truthy!"  # This prints!
6end
7
8if ""
9  puts "Empty string is truthy!"  # This prints!
10end
11
12if []
13  puts "Empty array is truthy!"  # This prints!
14end
15
16# Use .present? and .blank? in Rails for better checks
17# (from Active Support)
18"".blank?     # => true
19"hello".blank? # => false
20nil.blank?    # => true
21[].blank?     # => true
22
23"hello".present? # => true
24"".present?      # => false

Logical Operators

ruby
1# && (and) - returns first falsy value or last value
2nil && "hello"     # => nil
3false && "hello"   # => false
4"hi" && "hello"    # => "hello"
5
6# || (or) - returns first truthy value or last value
7nil || "hello"     # => "hello"
8false || "hello"   # => "hello"
9"hi" || "hello"    # => "hi"
10
11# Common pattern: default values
12name = params[:name] || "Anonymous"
13
14# Safe assignment
15@user ||= User.find(params[:id])  # Only assigns if @user is nil/false

Control flow in Ruby is designed to be readable and expressive. Use these patterns to write clean, maintainable code!