Handling Nil, Duck Style

One of the first things you may hear an enthusiastic Rubyist say is: Ruby is pure OO! Everything is an object! Even nil!

Yes, nil is an object. How does that help? One benefit is that nil can have methods. Of interest for this post are the methods that start with to_:

nil.methods.grep /^to_.$/
#=> ["to_i", "to_f", "to_a", "to_s"]

What do those methods evaluate to?
nil.methods.grep(/^to_.$/).each do |method|
  puts "nil.#{method} #=> #{nil.send(method).inspect}"
end
nil.to_i #=> 0
nil.to_f #=> 0.0
nil.to_a #=> []
nil.to_s #=> ""

Now, here's an arbitrary method that demonstrates handling nil:
def upcase(input)
  input.to_s.upcase
end
upcase "foo" #=> "FOO"
upcase "BaR" #=> "BAR"
upcase nil   #=> ""

The .to_s allows nil to be passed in without failure. Without the .to_s you would receive this:

NoMethodError: undefined method `upcase' for nil:NilClass

Here's where the duck comes in:
# passing in a class
upcase String #=> "STRING"

# passing in an object
upcase Object.new #=> "#<OBJECT:0X2E7A8CC>"

Not only does .to_s allow you to handle nil gracefully, it allows you to pass in any object rather than only strings, which is part of what duck typing is all about.

Although calling .to_s on an argument which you are expecting to be a string may seem pointless, it allows you to handle nil and support the ducks.
Dan Manges Hi, I'm Dan Manges. I'm currently building Root. Previously I was the founding CTO of Braintree. Send me an email.
blog comments powered by Disqus