Skip to content

Conditionals

if / elsif / else

The basic conditional. The first branch whose condition is truthy runs; the rest are skipped.

score = 85

if score >= 90
  puts "A"
elsif score >= 80
  puts "B"
elsif score >= 70
  puts "C"
else
  puts "F"
end

elsif and else are optional:

if logged_in
  puts "Welcome back!"
end

unless

unless is if not — runs the block when the condition is false. Use it when the negative reads more naturally.

unless logged_in
  puts "Please log in."
end

# Equivalent to:
if not logged_in
  puts "Please log in."
end

unless supports else but not elsif:

unless admin
  puts "Access denied."
else
  puts "Welcome, admin."
end

Postfix if and unless

For single-statement conditionals, put the condition at the end. Reads like natural English.

puts "Adult!" if age >= 18
puts "Minor!" unless age >= 18

x = 0 unless x > 0
log(event) if debug_mode

Inline if Expression

if can produce a value. Assign it, return it, or use it inline.

grade = if score >= 90 then "A" elsif score >= 80 then "B" else "C" end
puts grade

# Without 'then' — newline works too
label = if x > 0
  "positive"
elsif x < 0
  "negative"
else
  "zero"
end
puts label

# Assign to a variable before using in an expression
status = if active then "on" else "off" end
puts "System is #{status}"

A missing else clause evaluates to nil:

title = if admin then "Admin" end
puts title   # nil if admin is false

case / when

Match a value against a series of alternatives. Cleaner than a long if/elsif chain when testing one variable.

day = "Monday"

case day
when "Saturday", "Sunday"
  puts "Weekend!"
when "Monday"
  puts "Start of the week."
when "Friday"
  puts "Almost there."
else
  puts "Midweek."
end

Multiple values in a single when are separated by commas — any of them triggers the branch.

Bare case — condition-based

case without a subject works like if/elsif but reads more cleanly when all branches test different conditions:

case
when x < 0
  puts "negative"
when x == 0
  puts "zero"
when x < 100
  puts "small positive"
else
  puts "large positive"
end

case with ranges

case score
when 90..100
  puts "A"
when 80..89
  puts "B"
when 70..79
  puts "C"
else
  puts "F"
end

Ternary-style with Inline if

Frankie does not have a ? : ternary operator. Use inline if instead:

# Instead of: label = x > 0 ? "positive" : "non-positive"
label = if x > 0 then "positive" else "non-positive" end

# Or assign first, then use
status = if active then "on" else "off" end
puts "System: #{status}"

Truthiness

Only false and nil are falsy. Everything else is truthy:

if 0     then puts "0 is truthy" end      # prints
if ""    then puts "empty str truthy" end  # prints
if []    then puts "empty vec truthy" end  # prints
if nil   then puts "nil is truthy" end     # does not print
if false then puts "false is truthy" end   # does not print

This means nil checks should always be explicit:

result = find_user(id)

# Wrong — empty vector or 0 would also be treated as "missing"
if not result
  puts "not found"
end

# Right — test for nil specifically
if result == nil
  puts "not found"
end

# Or use .nil?
if result.nil?
  puts "not found"
end

Shape pattern matching

user = {name: "Alice", role: "admin", active: true}

case user
when {role: "admin"}
  puts "Admin: #{user["name"]}"
when {role: "moderator"}
  puts "Moderator: #{user["name"]}"
when {active: false}
  puts "Suspended user"
else
  puts "Regular user: #{user["name"]}"
end

 Admin: Alice

Combining Conditions

if age >= 18 and active
  puts "eligible"
end

if role == "admin" or role == "moderator"
  puts "elevated access"
end

if not banned
  puts "allowed"
end

# Parentheses for clarity
if (score > 50 and attempts < 3) or override
  puts "access granted"
end