Ruby Null Objects in 60 Seconds

2014-12-08 00:00:00 UTC

A Simple Application

def current_user
  @user ||= User.first
end

def user_name
  current_user.name
end

Tragedy Strikes

# Somewhere in your application. . .
puts(user_name)

This returns the following exception:

NoMethodError: undefined method `blogs' for nil:NilClass

Your application crashed. Your Web 2.0 wonder app is left in shambles.

What Happened?

You either forgot to set @user, or there is no @user. Perhaps the the person using the application is not logged in?

An Ounce of Prevention

Instead of relying on nil, avoid passing it and avoid accepting it. Here’s a refactor using a new class that we will define on our own to prevent these nil exceptions from happening in the future.

class NilUser
  def name
    "Guest User"
  end
end

Then, we patch the old current_user method to never return nil.

def current_user
  @user ||= (User.first or NilUser.new)
end

Wow!

Let’s try the same method call again.

puts(user_name)
# => "Guest User"

No nil exceptions here. If we ever need to write logic to handle missing users, we have it all in one neat place.

That’s all there is to it. This is what languages like Ruby mean when they say “Duck Typing”. If it quacks like a duck (or in this case, a user), it must be a duck!

Ruby allows you to pass any method to any object as a message, but it does so under the assumption that the receiver will know how to handle it.