Everything You Need to Know About Nil

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!