Nil…
What is it, really?
Well, nil
is a special Ruby object used to represent an “empty” or “default” value. It’s also a “falsy” value, meaning that it behaves like false
when used in a conditional statement.
Now:
There is ONLY one nil
object, with an object_id
of 4
(or 8
in 64-bit Ruby), this is part of why nil
is special.
nil.object_id # 4
Let’s take a deeper look!
Where Do Nil Values Come From?
Many methods can return nil
as a result.
This happens when you ask for a value but that value is not available.
Examples:
- Product not found
- Array index out of bounds
- Hash key doesn’t exist
Here’s some code to demonstrate this:
arr = [1,2,3] arr[5] # nil
This will often lead to all sorts of problems since we expect the method we called to return a valid value instead of a nil
.
Like this NoMethodError
exception:
arr[5].size # NoMethodError: undefined method 'size' for nil:NilClass
To avoid this error, you will need to check if you have a nil
value before you call a method on it.
Testing For Nil In Ruby
If you don’t want to get the “undefined method for nil:NilClass” error try this…
Only call method if not nil:
if array[5] && array[5].size # do something... end
This is why Ruby 2.3 introduced the “safe navigator” operator (&.
).
Example:
if arr[5]&.size # do something... end
Another way to test for nil is to use the nil?
method:
if @bacon.nil? # ... end
Another option is to use the blank?
method (Rails only).
Depending on what object you are working with there are a few techniques you can use to avoid checking for nil
values entirely.
For example, you can use the fetch
method on Hash & Array objects.
Or you can use the “Null Object Pattern” in your own classes if you want to return a default value instead of nil
.
Other Places Where Nil Is Lurking
You should be aware that undefined instance variables will return nil
.
@foo # nil
So watch out for that, it might just happen that you misspelt the name of your instance variable or you forgot to initialize it!
Another place where you can find nil
is with the puts
& print
methods.
These two methods always return nil
.
I mention this because I have seen some of my students try something like this:
numbers = [1,2,3].map { |n| puts n * 2 }
Which results in numbers
being [nil, nil, nil]
. The solution in this case is to simply remove the puts
from inside the block.
Understanding NilClass
Just like any other Ruby object nil
has a set of methods.
Here’s the class definition from Rubinius:
class NilClass def to_s "" end def inspect "nil" end def nil? true end def to_a [] end def to_f 0.0 end def to_i 0 end def to_c Complex(0) end def to_h {} end end
Notice how all these to_something
methods return an empty value (0
for numbers).
Empty hash, empty string, empty array…
The reason for this is that nil
is used to represent “nothing”.
Null Object Pattern
No discussion about nil
is complete without mentioning the Null Object Pattern.
In her excellent talk, “Nothing is Something“, Sandi Metz makes the point that while nil
means “nothing” it can have a more specific meaning.
For example, if we write a method that finds products & we want to return a default product…
We can return a null product like this one:
class MissingProduct def name "Product not found" end end
Now if we have an array with a mix of real product objects & null products then all of these products will have the name
method. This means that you will not get a NoMethodError
exception.
Tip: If you can treat all your objects the same way, without having to check object type then you are taking advantage of Polymorphism.
These kind of objects are great for your presentation layer, but not so much for you controllers where you want to do something different if what you are looking for is not available, like showing an alert message, redirect, etc.
Truthiness
Another thing you need to know about nil
is that it’s the only value, besides false
(which is also an object), that is considered “falsy”.
Everything else in Ruby is considered true
in a boolean context.
Some languages consider the number 0
as a false
value, but that’s not the case in Ruby:
if 0 puts 123 end # 123
This is saying: “if 0
is true
then print 123
“.
Video
Summary
You learned that nil
is just a Ruby object that represents “nothing”.
You also learned that nil
& false
are the only two things in Ruby that are “falsy”. Everything else is “truthy”.
If you enjoyed this post don’t forget to share it on your favorite social networks!