skip to content

Nil & Truthiness

Only nil and false are falsy in Ruby, so 0, an empty string and an empty array are all true. Interviewers probe NilClass, NoMethodError on nil and how to write code that avoids it.

on this pageshow

explore

questions

5

In Ruby, which values are falsy, and does a condition treat 0, an empty string or an empty array as true?

level: juniorimportance: must knowfreq 82%

answer

  1. a very short falsy list
  2. numbers and empties are plain objects
  3. empty?, zero?, nil? ask explicitly
  4. nil == false is false
  5. gets returns nil only at end of input

basics

~10 s

Only nil and false are falsy in Ruby. Every other object, including 0, 0.0, "", [], {} and the string "false", is truthy, so test emptiness or zero explicitly with empty?, zero? or nil?.

solid answer

~40 s

Ruby conditions (`if`, `unless`, `while`, the ternary, `&&` and `||`) treat exactly two values as false: `nil` and `false`. Everything else is truthy, because `0`, `""` and `[]` are ordinary objects rather than special empty markers. So `if count` passes when `count` is `0`, and `if middle_name` passes when a form sent `""`. When you mean zero or empty, say so: `count.zero?`, `middle_name.empty?`, `list.empty?`, or `value.nil?` when only a missing value matters. `nil` and `false` are also distinct objects: `nil == false` returns `false`, although both fail a condition. Python and JavaScript treat `0` and the empty string as falsy, which is where this rule trips people moving to Ruby.

code

ruby · 12 lines
ruby
[nil, false, 0, 0.0, "", [], {}, "false"].each do |value|
  verdict = value ? "truthy" : "falsy"
  puts "#{value.inspect.ljust(7)} #{verdict}"
end
# nil     falsy
# false   falsy
# 0       truthy
# 0.0     truthy
# ""      truthy
# []      truthy
# {}      truthy
# "false" truthy

go deeper

for a junior

Recall the two-item falsy list, nil and false, and name 0, "" and [] as truthy. Show empty?, zero? and nil? as the explicit checks.

for a middle

Explain that the rule is uniform across if, while, the ternary and the logical operators, and that nil and false remain different objects with different to_s and nil? answers.

for a senior

Point out where truthiness hides bugs in real code: blank form fields arriving as "", counts of 0 passing guards, and nil versus false carrying different meanings in stored records.

for a principal

Frame the trade-off: a tiny falsy set makes presence checks cheap and predictable, but pushes teams to write explicit emptiness predicates, which reviewers should expect rather than bare truthiness tests.

## The rule: two falsy values Every Ruby condition asks one question of the value it is given: is it `nil` or `false`? If so, the condition fails; for **any other object**, it passes. Ruby's own syntax reference says it directly: for the tests in control expressions, `nil` and `false` are false-values, and `true` and any other object are true-values. The words **truthy** and **falsy** describe this. A value is *truthy* when a condition treats it as true, *falsy* when a condition treats it as false. In Ruby the falsy set has exactly two members: - **`nil`**, the single instance of `NilClass`, meaning "no value". - **`false`**, the single instance of `FalseClass`. The same rule applies everywhere a truth value is tested: `if`, `unless`, `elsif`, `while`, `until`, the ternary `a ? b : c`, and the operators `&&`, `||` and `!`. ## Values that surprise newcomers In Ruby, numbers, strings and collections are ordinary objects. None of them carries a special "empty means false" meaning, so all of the following are truthy: | Value | Truthy in Ruby? | Explicit question to ask instead | |---|---|---| | `0` | yes | `count.zero?` | | `0.0` | yes | `amount.zero?` | | `""` | yes | `text.empty?` | | `[]` | yes | `list.empty?` | | `{}` | yes | `options.empty?` | | `"false"` | yes | `flag == "false"` | | `nil` | **no** | `value.nil?` | | `false` | **no** | `value == false` | The comparison with other languages is where interviews go. In Python and JavaScript, `0` and the empty string are falsy, and in Python so are empty lists and dictionaries. Code ported from those languages often writes `if items` meaning "if there are any items"; in Ruby that condition is true for `[]`. ## Asking the question you mean Because most values are truthy, a bare `if value` really means "if value is neither nil nor false". When that is not the question, name the one you mean: 1. **Missing?** Use `value.nil?`. `Kernel#nil?` returns `false` for every object, and `NilClass#nil?` returns `true`. 2. **Empty?** Use `empty?` on `String`, `Array`, `Hash` and `Set`. It returns `true` for `""`, `[]` and `{}`. 3. **Zero?** Use `zero?` on a number. 4. **Missing or empty?** Combine them, for example `value.nil? || value.empty?`, or convert first: `value.to_s.empty?` treats `nil` and `""` alike, because `nil.to_s` returns `""`. A common loop idiom leans on the rule on purpose. `while (line = gets)` keeps reading because an empty line still arrives as `"\n"`, a truthy string; `gets` returns `nil` only at the end of input, and that `nil` ends the loop. ## nil and false are not interchangeable Both fail a condition, but they are two different objects of two different classes: - `nil == false` returns `false`. Neither class redefines `==`, so the comparison is identity, and they are different objects. - `nil.nil?` is `true`; `false.nil?` is `false`. - `nil.to_s` is `""`; `false.to_s` is `"false"`. - A method that answers a yes-or-no question should return `false`; `nil` conventionally means "nothing was found" or "no value". Keep the two apart in data. A patient-intake record where `consented` is `nil` means the question was never answered; `false` means the patient said no. ## Using the rule on purpose The short falsy list is also why so many core methods report "nothing found" by returning `nil`: the caller can test the result directly, without comparing it against a sentinel. - `if (m = line.match(/\d+/))` enters the branch only when the pattern matched, because `String#match` returns a `MatchData` or `nil`. - `if (record = records.find { |r| r.id == id })` works the same way, because `find` returns the element or `nil`. - A method can return `nil` for "no answer" and any object for "here it is", and callers treat the result as a yes-or-no value. The pattern is safe precisely because only `nil` and `false` fail: a match object, a record with an id of `0` or an empty string all count as found. ## Worked example: an optional middle name A patient-intake form posts every field it has, so an untouched middle-name box usually arrives as `""`, not `nil`. A check written as `if middle_name` then treats the blank field as present: - `""` is truthy, so the branch that prints the middle name runs and prints nothing. - The fix is to ask the real question: `middle_name.nil? || middle_name.empty?` for "not provided". - When the value might be `nil` or `""`, `middle_name.to_s.empty?` covers both cases in one call. The habit worth building is simple: in Ruby, use a bare truthiness test only when you mean "not nil and not false", and write the explicit predicate otherwise.

  • In Ruby, why does nil == false return false when both fail an if?
    Truthiness and equality are separate rules. Conditions test whether a value is `nil` or `false`, while `==` compares objects. Neither `NilClass` nor `FalseClass` redefines `==`, so the comparison falls back to identity, and `nil` and `false` are two different objects of two different classes.
  • Why does while (line = gets) stop at end of input but not at a blank line?
    `gets` returns each line with its line separator, so a blank line arrives as `"\n"`, a truthy string. At end of input `gets` returns `nil`, the assignment evaluates to `nil`, and the loop condition fails. The idiom works only because `nil` is falsy and every string, even an empty one, is truthy.

A Ruby condition is a bouncer holding a list with only two names on it, nil and false. Anyone else gets in, however empty-handed: 0, an empty string and an empty array all pass because they are not on the list.

saying these in an interview costs you the question

  • 0 is falsy in Ruby, the same as in C or Python
  • An empty string or empty array fails an if check
  • nil and false are the same value, so nil == false is true
  • The string "false" is treated as false in a condition
  • if list.length checks whether the list is empty
open as a page

In Ruby 4.0, what does undefined method 'upcase' for nil (NoMethodError) tell you, and how do you trace where the nil came from?

level: middleimportance: must knowfreq 68%

basics

~20 s

It means upcase was called on nil: an expression expected to return a String returned nil. Use error_highlight's carets to find which call on the line received nil, then trace that value back to the method that produced it.

open as a page

In Ruby, what classes are nil, true and false instances of, why is there no Boolean class, and what does !!value return?

level: juniorimportance: should knowfreq 50%

basics

~20 s

nil, true and false are the only instances of NilClass, TrueClass and FalseClass, each inheriting directly from Object, so Ruby has no shared Boolean class. !!value returns true for any truthy value and false for nil or false.

open as a page

In Ruby, what do nil.to_s, nil.to_a, nil.to_i and nil.inspect return, and when does relying on them hide a bug?

level: middleimportance: should knowfreq 45%

basics

~20 s

nil.to_s returns "", nil.to_a returns [], nil.to_h returns {}, nil.to_i returns 0, nil.to_f returns 0.0 and nil.inspect returns "nil". They make blanks safe to print, but erase the difference between missing and empty or zero.

open as a page

In a Ruby service where NoMethodError on nil keeps surfacing far from its cause, how do you stop nil spreading instead of silencing the errors?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Decide at each boundary whether a missing value is legal. If not, raise there with a clear error; if so, normalise it to "" or a null object. Blanket rescues and NilClass patches only move the failure.

open as a page