Control Flow
9.1 Conditionals
if temp > 30
puts "Hot"
elsif temp > 15
puts "Pleasant"
else
puts "Cold"
end
unless logged_in? # "if not"
redirect_to_login
end
puts "Adult" if age >= 18 # modifier form
return unless valid? # guard clause idiom
status = paid ? "Paid" : "Due"9.2 case / when
when uses === (case equality): classes check is_a?, ranges check inclusion, regexes check a match, and procs call themselves.
case score
when 90..100 then "A"
when 80...90 then "B"
when Integer then "Other number"
else "Invalid"
end
case input
when "start", "run" then start
when /^\d+$/ then process_number(input)
when ->(s) { s.length > 20 } then "too long" # lambdas work via ===
end
case # no subject: if/elsif alternative
when x < 0 then "negative"
when x.zero? then "zero"
else "positive"
end9.3 Pattern Matching with case / in (Ruby 3.0+)
Covered in depth in Module 23.
case { status: "ok", data: { id: 1 } }
in { status: "ok", data: { id: Integer => id } }
puts "Found #{id}"
in { status: "error", message: }
puts message
end9.4 Loops
Loop control: break (with an optional value: result = loop { break 42 }), next (skip to the next iteration), redo (rare: repeat the iteration).
Idiomatic Ruby prefers iterators (each, times, map) over while/for.
i = 0
while i < 5
i += 1
end
until i.zero?
i -= 1
end
loop do
input = gets&.chomp
break if input.nil? || input == "quit"
next if input.empty?
process(input)
end
for n in 1..3 # works but is rarely used (the loop variable leaks into the outer scope)
puts n
end
begin # do-while equivalent
attempt += 1
end while attempt < 3
5.times { |i| puts i }
[1, 2, 3].each { |n| puts n }
1.step(10, 2) { |n| puts n }9.5 catch / throw (Non-Local Exit)
result = catch(:found) do
matrix.each do |row|
row.each { |cell| throw :found, cell if cell > 100 }
end
nil
end