13

I'm new to Ruby and I was surprised when I found out that all objects are true apart from nil and false. Even 0 is true.

A nice thing about that property of the language is that you can write:

if !variable
 # do stuff when variable is nil
end

My colleagues, who are more seasoned Ruby developers, insist I should choose that instead of using .nil? like so:

if variable.nil?
 # do stuff when variable is nil
end

However I believe that the latter is a better option for two reasons: 1. I think it's more object oriented, especially in a language like Ruby where everything is an object and message exchange. 2. It is more readable, in my subject opinion, even if it is less compact.

Am I making a "newbie" mistake here?

asked Nov 13, 2015 at 19:15
4
  • 5
    Are you testing for nil? or a false value? Commented Nov 13, 2015 at 19:20
  • I'm testing for nil. Basically if the variable is nil, I do something (or not) Commented Nov 13, 2015 at 19:26
  • 4
    If you are testing for nil, why do you want the test for false to also enter that block? Commented Nov 13, 2015 at 19:26
  • Agree, I pointed that out as another reason to prefer .nil? But they insisted that "if variable do x" is more idiomatic than "if variable.nil? do x" and preferable when you know that variable is not boolean Commented Nov 13, 2015 at 19:28

4 Answers 4

21

Write what you mean. Mean what you write.

Lets take a different test. .vowel?

if char == 'a'
 # do stuff
end

vs

if char.vowel?
 # do stuff
end

Now, its obvious that these do not do the same thing. But if you're only expecting char to be a or b it will work. But it will confuse the next developer - the second block will be entered into for the conditions where char is [eiou] also. But for a, it will work correctly.

Yes, it is the case that nil and false are the only falsy values in Ruby. However, if you are testing for nil by testing for nil || false, this isn't what you mean.

It means that the next developer (who happens to be a crazy axe murder who knows your home address) will read the code, and wonder why false should go in there too.

Write the code that conveys exactly what you mean.

answered Nov 13, 2015 at 19:30
0
4

Consider the following:

response = responses.to_a.first

This will return the first element of responses, or nil. Then because conditional statements treat nil as false we can write:

response = responses.to_a.first
if response
 # do something ('happy path')
else
 # do something else
end

Which is more readable than:

if response.nil?
 # do something else
else
 # do something ('happy path')
end

The if (object) pattern is very common in Ruby code. It also leads nicely to refactoring, e.g.:

if response = responses.to_a.first
 do_something_with(response)
else
 # response is equal to nil
end

Remember also that a Ruby method returns nil by default. So:

def initial_response
 if @condition
 @responses.to_a.first
 else
 nil
 end
end

can be simplified to:

def initial_response
 if @condition
 @responses.to_a.first
 end
end

So we can further refactor:

if response = initial_response
 do_something_with(response)
else
 # response is equal to nil
end

Now you can argue that returning nil is not always the best idea, since it means checking for nil everywhere. But that is another kettle of fish. Given that testing for object "presence or absence" is such a frequent requirement, the truthiness of objects is a useful aspect of Ruby, albeit surprising for newcomers to the language.

answered Nov 20, 2015 at 23:13
2

Not only is if variable.nil? read more like natural language, it also guards against a programmer accidentally assigning it a false value and falling into your if statement, since Ruby is a loosely typed language.

answered Nov 15, 2015 at 1:31
2
  • 1
    So the initial comment in the original question was wrong? Should have been "do stuff when variable is nil or false"? And since code not matching comment is a bug, there's a bug straight away? Commented Nov 15, 2015 at 17:46
  • 1
    Correct. A simple truthiness test could introduce logic errors. Commented Nov 15, 2015 at 18:09
1

Idiomatically, unless variable is preferable to if !variable. Negated if statements are often considered a code smell as it's easier to miss the negation when skimming.

The bigger picture here is that doing nil checks like this is also a bit of a code smell. For proper OO, aim to use the null object pattern so that this sort of check is never needed.

Tell objects what to do, don't ask them what they are. This is sometimes known as tell don't ask

answered Nov 23, 2015 at 12:34

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.