Skip to content

Ruby Control Flow Explained — if unless case when Ternary and Truthiness

DodaTech Updated 2026-06-28 9 min read

In this tutorial, you will learn about Ruby Control Flow Explained. We cover key concepts, practical examples, and best practices to help you master this topic.

Ruby control flow includes if/unless, case/when, and ternary operators with unique truthiness rules where only nil and false are falsy values, making conditional logic expressive and readable.

What You'll Learn

  • Using if, unless, and elsif for conditionals
  • The case/when statement with multiple conditions
  • Ternary operators for inline conditions
  • Ruby's truthiness rules and how they differ from other languages
  • Modifier forms for concise conditional code

Why It Matters

Control flow is how programs make decisions. In security tools like Durga Antivirus Pro, control flow determines whether a file is flagged as malicious based on signature matches and behavior patterns. Doda Browser uses control flow to manage user preferences, tab states, and network requests. Mastering Ruby's expressive conditionals means writing cleaner, more readable decision logic.

Real-World Use

A Rails controller might use case/when to handle different HTTP response formats, if/unless for authorization checks, and ternary for quick conditional assignments in views. Understanding Ruby's unique syntax makes your code more idiomatic and concise.

flowchart LR
    A["Control Flow"] --> B["if/unless"]
    B --> C["case/when"]
    C --> D["Ternary"]
    D --> E["Loops"]
    A:::current --> B
    style A fill:#2563eb,stroke:#2563eb,color:#fff
    style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b

If Statement

The basic conditional in Ruby:

age = 18

if age >= 18
  puts "You can vote"
end
# You can vote

If/Else

temperature = 30

if temperature > 25
  puts "It's hot outside"
else
  puts "It's cool outside"
end
# It's hot outside

If/Elsif/Else

Ruby uses elsif (no second 'e'):

score = 85

if score >= 90
  puts "Grade: A"
elsif score >= 80
  puts "Grade: B"
elsif score >= 70
  puts "Grade: C"
else
  puts "Grade: D"
end
# Grade: B

Unless

unless is the opposite of if. It executes when the condition is falsy:

age = 16

unless age >= 18
  puts "You are under 18"
end
# You are under 18

# Equivalent to:
if !(age >= 18)
  puts "You are under 18"
end

Unless/Else

is_admin = false

unless is_admin
  puts "Access denied"
else
  puts "Welcome admin"
end
# Access denied

The Modifier Forms

Ruby allows conditionals at the end of a line for concise code:

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

# Equivalent to:
if age >= 18
  puts "Adult"
end

Ternary Operator

The ternary operator is a compact if/else:

age = 20
status = age >= 18 ? "adult" : "minor"
puts status
# adult

# Same as:
if age >= 18
  status = "adult"
else
  status = "minor"
end

You can nest ternaries (but avoid for readability):

score = 85
grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "D"
puts grade
# B

Case/When

Ruby's case/when is more flexible than switch statements in other languages.

Basic Case/When

day = "Monday"

case day
when "Monday"
  puts "Start of work week"
when "Friday"
  puts "Almost weekend"
when "Saturday", "Sunday"
  puts "Weekend!"
else
  puts "Midweek"
end
# Start of work week

Case with Ranges

score = 85

case score
when 90..100
  puts "Grade A"
when 80...90
  puts "Grade B"
when 70...80
  puts "Grade C"
else
  puts "Grade D"
end
# Grade B

Note: .. includes the end value, ... excludes it.

Case with Procs and Lambdas

grade = "B"

case grade
when ->(g) { %w[A B C].include?(g) }
  puts "Passing"
when "D"
  puts "Conditional pass"
else
  puts "Failing"
end
# Passing

Case Without an Expression

You can use case without a target value for clean boolean checks:

age = 25

case
when age < 13
  puts "Child"
when age < 18
  puts "Teenager"
when age < 65
  puts "Adult"
else
  puts "Senior"
end
# Adult

Truthiness in Ruby

Ruby's truthiness is simple but different from many languages:

# Only false and nil are falsy
puts "truthy" if true        # truthy
puts "truthy" if 1           # truthy
puts "truthy" if 0           # truthy (surprising to some!)
puts "truthy" if ""          # truthy (surprising!)
puts "truthy" if []          # truthy
puts "truthy" if "false"     # truthy (non-empty string)
puts "falsy" if false        # (nothing)
puts "falsy" if nil          # (nothing)

# Checking truthiness
puts !!true   # true
puts !!0      # true
puts !!nil    # false
puts !!false  # false

Logical Operators

# && — returns first falsy value or last truthy
puts nil && 42      # nil
puts 0 && 42        # 42 (0 is truthy in Ruby!)
puts "hello" && 42  # 42

# || — returns first truthy value or last falsy
puts nil || 42      # 42
puts 0 || 42        # 0
puts "hello" || 42  # "hello"

Conditional Assignment

Ruby has several conditional assignment operators:

# ||= — assign if nil or false
name = nil
name ||= "Default"
puts name  # "Default"

# &&= — assign if truthy
status = true
status &&= "active"
puts status  # "active"

# ||= is commonly used for memoization
def cached_data
  @data ||= expensive_calculation
end

Inline If/Unless Modifier Best Practices

Use modifier form for simple, single-line conditions:

# Good — simple and clear
puts "Over limit" if count > 100
raise "Invalid" unless valid?

# Bad — too complex for modifier form
puts "Processing completed successfully after #{duration} seconds with #{errors} errors" if count > 100 && duration > 0 && errors == 0

Common Mistakes

1. Using = Instead of == in Conditions

# Wrong — assigns, doesn't compare
if x = 5
  puts "x is 5"  # This always runs!
end

# Right
if x == 5
  puts "x is 5"
end

2. Forgetting nil and false Are the Only Falsy Values

# This works in many languages but not Ruby
if 0
  puts "This WILL run in Ruby"  # 0 is truthy!
end

3. Using Unless with Complex Conditions

# Hard to read
unless !user.nil? && user.active? && user.admin?
  puts "Access denied"
end

# Better
if user.nil? || !user.active? || !user.admin?
  puts "Access denied"
end

4. Forgetting elsif Spelling

# Wrong
if x > 0
  puts "positive"
else if x < 0  # This creates nested if, not elsif
  puts "negative"
end

# Right
if x > 0
  puts "positive"
elsif x < 0
  puts "negative"
end

5. Overusing Ternary for Complex Logic

# Bad — impossible to read
result = a > b ? (c > d ? x : y) : (e > f ? z : w)

# Better
if a > b
  result = c > d ? x : y
else
  result = e > f ? z : w
end

Practice Questions

1. What's the difference between if and unless?

if executes when the condition is truthy. unless executes when the condition is falsy. unless age >= 18 is equivalent to if !(age >= 18).

2. What values are truthy in Ruby?

Everything except false and nil. This includes 0, "", [], {}, and "false".

3. How do you write a one-line conditional in Ruby?

Using the modifier form: puts "Adult" if age >= 18 or raise "Error" unless valid?.

4. What does ||= do?

It assigns a value only if the variable is nil or false. Commonly used for memoization: @cache ||= compute_value.

Challenge: Write a Ruby program that asks for a score (0-100) and prints the letter grade using case/when. Include edge case handling for scores outside the valid range.

Solution
print "Enter your score (0-100): "
score = gets.chomp.to_i

grade = case score
when 90..100 then "A"
when 80...90 then "B"
when 70...80 then "C"
when 60...70 then "D"
when 0...60  then "F"
else "Invalid score"
end

puts "Grade: #{grade}"

# Additional feedback
case grade
when "A"
  puts "Excellent work!"
when "B"
  puts "Good job!"
when "C"
  puts "Fair effort"
when "D"
  puts "Needs improvement"
when "F"
  puts "Please try again"
end

FAQ

{{< faq question="Why does Ruby use elsif instead of else if or elif?" >}} Ruby's creator Matz wanted to minimize punctuation. elsif is a single word without extra braces or keywords. It's consistent with Ruby's philosophy of reducing visual noise in code. {{< /faq >}}

{{< faq question="Can I use case/when with any object type?" >}} Yes. Case/when uses === (the case equality operator) for comparison. Each class can define its own === behavior. Ranges use inclusion, classes use is_a?, and procs use call semantics. {{< /faq >}}

{{< faq question="Should I use unless/else or rewrite as if/else?" >> Use unless when the condition is negative and simple. Avoid unless with else — it becomes confusing. unless x is clear; unless x ... else ... should be rewritten as if x ... else .... `{{< /faq >}}

{{< faq question="What's the difference between .. and ... in ranges?" >}} .. includes the end value (1..5 = 1,2,3,4,5). ... excludes the end value (1...5 = 1,2,3,4). This matters in case/when with ranges. {{< /faq >}}

{{< faq question="Can I use and/or instead of &&/ ?" >}}

{{< /faq >}}

Try It Yourself

Run this comprehensive control flow demo:

# control_flow_demo.rb

def check_access(user, resource)
  if user.nil?
    return "No user provided"
  end

  unless user[:active]
    return "User account is inactive"
  end

  case resource[:level]
  when :admin
    user[:role] == :admin ? "Access granted" : "Access denied — admin only"
  when :user
    "Access granted"
  else
    "Unknown resource level"
  end
end

admin = { name: "Alice", role: :admin, active: true }
regular = { name: "Bob", role: :user, active: true }
inactive = { name: "Charlie", role: :user, active: false }

puts check_access(admin, { level: :admin })
puts check_access(regular, { level: :admin })
puts check_access(inactive, { level: :user })
puts check_access(nil, { level: :user })

Expected output:

Access granted
Access denied — admin only
User account is inactive
No user provided

What's Next

Now that you can control program flow, learn about loops and iteration to repeat actions efficiently.

Topic Description Link
Ruby Loops each, while, until, times {{< ref "05-loops" >}}
Ruby Arrays Array methods and iteration {{< ref "06-arrays" >}}
Python Control Flow Compare with Python conditionals Python

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro