nil, true, false & Truthiness
Reviewed & published by Brayan K
Truthiness is the rule Ruby uses to decide whether a value counts as "yes" in a condition — and in Ruby the only falsy values are nil (nothing) and false; literally everything else is truthy.
Part of the free Ruby course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
That means 0 and "" are truthy — a fact that trips up newcomers from other languages. You'll also learn nil?, safe navigation &., and ||=.
What You'll Learn in This Lesson
- Why only nil and false are falsy
- That 0 and "" are TRUTHY in Ruby
- Checking for nothing with .nil?
- Safe navigation with &. to dodge NoMethodError
- Memoization and defaults with ||=
- How nil converts: to_s, to_a, to_i
1️⃣ The Only Two Falsy Values
Commit this to memory: in Ruby a condition is "false" only when the value is nil or false. Every other object — including 0, "", and [] — is truthy and will run an if block.
# In Ruby, ONLY nil and false are falsy. Everything else is truthy.
zero = 0
blank = ""
empty = []
puts "0 is truthy" if zero # 0 is TRUTHY (unlike C/Python)
puts "'' is truthy" if blank # empty string is TRUTHY
puts "[] is truthy" if empty # empty array is TRUTHY
puts "nil is falsy" unless nil # nil is falsy
puts "false is falsy" unless false # false is falsy
# nil and false are the ONLY two falsy values
[0, "", [], {}, nil, false].each do |v|
puts "#{v.inspect} => #{v ? 'truthy' : 'falsy'}"
end2️⃣ Checking for nil & Safe Navigation
To ask "is this nothing?", call .nil? — it's true only for nil, distinguishing it from false. When a value might be nil and you want to call a method anyway, the safe navigation operator &. returns nil instead of raising NoMethodError.
# nil? and explicit checks
name = nil
puts name.nil? # true
puts name == nil # true (works, but .nil? is idiomatic)
found = "result"
puts found.nil? # false
# Beware: checking "if value" treats both nil AND false as missing.
flag = false
if flag.nil?
puts "flag is truly missing"
else
puts "flag is set (even though it's false)"
end# Safe navigation &. — call a method only if the receiver isn't nil
user = nil
puts user&.upcase.inspect # nil (no NoMethodError)
name = "ada"
puts name&.upcase # ADA
# Without &., calling on nil blows up:
begin
nil.upcase
rescue NoMethodError => e
puts "Error: #{e.message}"
end3️⃣ ||= Memoization & nil Conversions
x ||= y assigns only when x is currently nil or false — perfect for caching expensive results and for defaults. And nil converts politely: nil.to_s is "", nil.to_a is [], and nil.to_i is 0.
# ||= memoization: assign only if currently nil or false
@count = nil
@count ||= 0 # @count was nil, so it becomes 0
puts @count # 0
@count ||= 99 # @count is 0 (truthy), so this is IGNORED
puts @count # 0 (NOT 99)
# Common cache pattern
def expensive
@cache ||= (puts "computing..."; 42)
end
puts expensive # computes, prints "computing...", returns 42
puts expensive # cached, no recompute
# nil converts gracefully
puts nil.to_s.inspect # "" (empty string)
puts nil.to_a.inspect # [] (empty array)
puts nil.to_i # 0Your turn. Fill in each ___ blank with the right operator, then run it.
# 🎯 YOUR TURN — fill in the blanks, then run with: ruby config.rb
config = nil
port = config___fetch(:port) # 👉 safe navigation operator (two chars)
puts port.inspect # nil, no crash
timeout = config&.fetch(:timeout) ___ 30 # 👉 fallback when left side is nil
puts "Timeout: #{timeout}"
value = ""
puts(value.empty? ? "blank but not nil" : "has content")
# ✅ Expected output:
# nil
# Timeout: 30
# blank but not nilMini-Challenge: A Forgiving Greeting
Combine the falsy rules: treat an empty string as missing, then fall back to a default with ||. Run with ruby greet.rb.
# 🎯 MINI-CHALLENGE: a forgiving greeting.
# Save as greet.rb and run with: ruby greet.rb
#
# Write greeting(name) that:
# 1. Treats an empty string "" as missing (set it to nil).
# 2. Falls back to "stranger" using || when name is nil.
# 3. Returns "Hello, <who>!".
# Call it with "Ada", "", and nil.
#
# ✅ Example output:
# Hello, Ada!
# Hello, stranger!
# Hello, stranger!
# your code hereCommon Errors (and the fix)
- ❌ Assuming if 0 is false → ✅ 0 is truthy in Ruby; only nil/false are falsy.
- ❌ undefined method for nil → ✅ guard with &. or check .nil? first.
- ❌ Using if flag when false is meaningful → ✅ test flag.nil? to tell "unset" from "false".
- ❌ x ||= y overwriting a real false → ✅ use an explicit x = y if x.nil?.
- ❌ Using str == "" to test emptiness on a maybe-nil value → ✅ str.to_s.empty? handles nil too.
Pro Tips
- 💡 Memoize cleanly: @data ||= load_data computes once and caches.
- 💡 Chain safely: user&.account&.balance stops at the first nil.
- 💡 Defaults everywhere: name = input || "Guest" works because || short-circuits on the first truthy value.
📋 Quick Reference — Truthiness
| Concept | Ruby Syntax |
|---|---|
| Falsy values | nil , false |
| Is it nothing? | value.nil? |
| Safe navigation | user&.name |
| Default / memoize | x ||= y |
| Fallback | value || "default" |
| nil converts | nil.to_s / to_a / to_i |
🎉 Lesson Complete!
- ✅ Only nil and false are falsy — 0 and "" are truthy
- ✅ .nil? tells "nothing" apart from "false"
- ✅ Safe navigation &. dodges NoMethodError
- ✅ ||= assigns only when nil/false — great for caching
- ✅ nil converts to "", [], and 0
Practice quiz
Which values are the ONLY falsy values in Ruby?
- 0 and ""
- nil and false
- nil, false, and 0
- nil and ""
Answer: nil and false. In Ruby only nil and false are falsy; everything else, including 0 and "", is truthy.
What does the expression: if 0 then "yes" end evaluate to?
- nil
- "yes"
- false
- an error
Answer: "yes". 0 is truthy in Ruby, so the if block runs and returns "yes".
What does nil.to_s return?
- nil
- "nil"
- an empty string ""
- a NoMethodError
Answer: an empty string "". nil converts gracefully: nil.to_s is "", nil.to_a is [], and nil.to_i is 0.
What does nil&.upcase return?
- nil
- ""
- raises NoMethodError
- "NIL"
Answer: nil. Safe navigation &. returns nil instead of raising when the receiver is nil.
Which method tells nil apart from false?
- empty?
- nil?
- false?
- blank?
Answer: nil?. value.nil? is true only for nil, distinguishing it from false.
After @count = nil; @count ||= 0; @count ||= 99, what is @count?
- nil
- 0
- 99
- false
Answer: 0. ||= assigns only when nil/false. @count becomes 0, then since 0 is truthy the second ||= is ignored.
What does "ada"&.upcase return?
- nil
- "ada"
- "ADA"
- an error
Answer: "ADA". The receiver isn't nil, so &. simply calls upcase normally, giving "ADA".
What does x ||= y expand to?
- x = x && y
- x || (x = y)
- x = y
- x && (x = y)
Answer: x || (x = y). x ||= y means x || (x = y): assign y only if x is currently nil or false.
Is an empty array [] truthy or falsy in Ruby?
- falsy
- truthy
- nil
- it raises an error
Answer: truthy. Empty collections are still objects, so [] is truthy. Use .empty? to test emptiness.
Calling a method on nil without a guard typically raises which error?
- ArgumentError
- NameError
- NoMethodError
- TypeError
Answer: NoMethodError. nil.upcase raises NoMethodError; use &. or a .nil? check to guard against it.
Continue this course
- Previous: Operators & Expressions
- Next: Strings & Symbols — Build and interpolate strings, and learn what symbols are for
- Quick reference: Ruby cheat sheet › Common Patterns
Frequently asked questions
Are 0 and an empty string really truthy in Ruby?
Yes. In Ruby the only two falsy values are nil and false — literally nothing else. The integer 0, the float 0.0, an empty string "", an empty array [], and an empty hash {} are all truthy, so if 0 and if "" both run their blocks. This differs sharply from C, Python, and JavaScript, where 0 and "" are falsy. When you want to know whether a collection is empty, ask explicitly with .empty? rather than relying on truthiness.
What's the difference between nil and false?
false is the boolean 'no'; it's the answer to a yes/no question. nil is Ruby's way of saying 'nothing here' — an absent or undefined value, like a hash key that doesn't exist or a method that returned nothing. They're different objects (NilClass vs FalseClass) but both are falsy, so a bare if value treats them the same. When the distinction matters — for instance, a flag that is deliberately false versus one that was never set — test with value.nil? instead of if value.
When should I use the safe navigation operator &. ?
Use &. when a value might be nil and you want to call a method on it without risking a NoMethodError. user&.name returns the user's name if user exists, or nil if user is nil, short-circuiting the rest of the chain. It's perfect for optional data like user&.address&.zip. Don't overuse it, though: if a value should never be nil, a plain user.name that loudly fails on nil is a better bug-catcher than silently returning nil.
What does ||= actually do?
x ||= y means 'assign y to x only if x is currently nil or false'. It expands to x || (x = y), so if x already holds a truthy value it is left untouched. This makes ||= the standard idiom for memoization (caching an expensive result in @cache ||= compute) and for default values. The one trap: because false counts as 'unset', ||= will overwrite a legitimately false value — use an explicit nil? check if false is a meaningful state.