In Ruby, which values are falsy, and does a condition treat 0, an empty string or an empty array as true?
answer
- a very short falsy list
- numbers and empties are plain objects
- empty?, zero?, nil? ask explicitly
- nil == false is false
- gets returns nil only at end of input
basics
~10 sOnly 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 sRuby 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[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" truthygo deeper
Recall the two-item falsy list, nil and false, and name 0, "" and [] as truthy. Show empty?, zero? and nil? as the explicit checks.
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.
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.
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