Object#nil?
obj.nil? -> true or false The nil? method is defined on Object and returns true if the object is nil, and false otherwise. In Ruby, nil represents the absence of a value—the only member of the NilClass. Every other object returns false when nil? is called.
Syntax
object.nil?
Parameters
nil? takes no parameters.
Because nil? is defined on Object, every value in Ruby inherits it. The method returns a simple boolean with no exceptions and no edge cases related to argument types. This universality is the reason it appears so often in guard clauses and conditional checks: you can call it anywhere without defensive type checking.
Examples
Basic usage
nil.nil?
# => true
"hello".nil?
# => false
42.nil?
# => false
Every object in Ruby responds to nil?, so you can call it on anything without worrying about a NoMethodError. Only the singleton nil object itself returns true — integers, strings, empty arrays, and even false all return false. This consistency makes nil? a safe and predictable way to test for absence anywhere in your code.
Checking for nil in conditionals
def find_user(id)
user = database.find_by(id: id)
if user.nil?
puts "User not found"
return nil
end
user
end
When the block argument is a potentially nil value, using a direct nil? check avoids the ambiguity that comes with truthy/falsy tests. A value like false is a legitimate return from many methods, and testing it with nil? keeps the distinction clear. The method also reads naturally in guard clauses, making it obvious to the reader that the branch handles the missing-value case specifically.
Common pattern: safe navigation with nil checks
# Before using a potentially nil value
name = params[:user]&.fetch(:name)
if name.nil?
name = "Anonymous"
end
The safe navigation operator &. works well with nil? because it short-circuits to nil when the receiver is missing. This combination keeps the code concise while still making the nil-checking intent visible. You can chain &. calls as needed, and a single nil? at the end confirms whether the whole chain resolved to a real value.
Common Patterns
The nil check pattern
Ruby developers frequently check for nil before using values:
def greet(user)
return "Hello, stranger!" if user.nil?
"Hello, #{user.name}!"
end
Returning early when a value is missing keeps the happy path flat and easy to follow. The guard clause pattern shown here is idiomatic Ruby — it puts the edge case at the top and lets the main logic sit at the method’s natural indentation level. This style is especially helpful in methods that perform several sequential steps, each of which depends on the previous step returning a real value.
Combining with logical operators
# Use || to provide a default value
name = nil_value || "default"
# Use && for conditional execution
result = value && process(value)
Ruby’s || operator provides a default when the left side is falsy, which makes it a convenient companion to nil?. But be careful: || treats false the same as nil, so it is not a direct substitute for a nil check when false is a meaningful value. The && operator works in the opposite direction — it only proceeds when the left side is truthy, which is useful for conditional chains where each step depends on the previous one succeeding.
Hash.fetch with default
Instead of checking nil?, use Hash#fetch:
config = { timeout: 30 }
# Instead of:
timeout = config[:timeout]
timeout = 60 if timeout.nil?
# Use:
timeout = config.fetch(:timeout, 60)
Hash#fetch is often a cleaner alternative to a manual nil? check followed by a default assignment. It raises a KeyError when the key is missing unless you provide a fallback, which makes the code’s expectations about required keys explicit. This pattern is common in configuration loading and request parameter handling, where missing keys usually indicate a problem rather than a routine absence.
Errors
Calling nil? never raises an error—it works on all objects.
checking for absence directly
nil? keeps nil checks simple because it asks one direct question and returns one direct answer. That makes it easy to use in conditionals and guard clauses where the code only needs to know whether a value is present. It also avoids guessing based on truthiness, which can matter when false is a valid value and should not be treated the same as nil. For clear intent, a direct nil check is often the easiest path.
The method is also a useful reminder that nil is not the same as an empty string, an empty array, or false. Those values may still be meaningful in the program even if they do not count as present. By checking specifically for nil, the code keeps that distinction explicit and avoids hiding valid data behind a broad truthy check. That small detail can make a branch more honest and a bug easier to spot.
It also helps when a method wants to distinguish “missing” from “present but empty.” That distinction comes up often in forms, configuration, and lookup code. A direct nil? check keeps the intent narrow and avoids folding several different cases into one vague condition. The code stays easier to reason about because the question being asked is so specific.
That clarity is often the difference between a branch that merely works and one that is easy to support later. When the code says exactly what it wants, the reader does not have to guess whether an empty value should be treated the same as a missing one. nil? keeps that line sharp, which is why it shows up so often in everyday Ruby code.
It is also a small but important part of writing defensive Ruby. When the program receives data from the outside world, nil? gives it a direct way to separate absent values from values that are merely empty or falsey. That distinction keeps the logic honest and reduces the chance that the wrong fallback will run.
That directness is useful in almost every part of a Ruby application, from controller code to small scripts. A reader who sees nil? knows the check is specific and not just a loose truthiness test.
# A loose truthiness check would treat false the same as nil
value = some_method
if value
# This runs for true, 1, "hello", but not for false or nil
end
# A nil? check only excludes nil itself
unless value.nil?
# This runs for false too, which may be the correct behavior
end
That makes the branch easier to read, and it gives the program a clearer contract about what counts as missing.