Does your predicate return what you think it does?

def has_query?
  self.param_search_query && self.param_search_query != "Eventname"

I found this in some code I was working on today. This is a pretty standard “predicate method”, which, by convention, should always return either true or false. Strangely, as I was exploring the code with Pry, I noticed the method return nil.

It turned out that param_search_query was actually nil, which, when mixed with the logical AND (&&) operator returns something the author clearly did not expect:

mike@sleepycat:~☺  irb
irb(main):001:> nil && true
=> nil

This was actually surprising to me too. I would have thought that nil would have been falsey and that the expression would return false. Definitely something I am going to remember next time I am using the && operator.

So the next question is, what to do about it.
One way to ensure a boolean return value that I have seen is to use the bang operator twice. This works because !nil is true and !!nil is false:

irb(main):003:0> !!nil
=> false

So we could use that to fix the method like so:

def has_query?
  !!(self.param_search_query && self.param_search_query != "Eventname")

I’m not a fan of this because I think it obscures the intention of the author.
In the end, since this was in a Rails app I went with the present? method:

def has_query?
  self.param_search_query.present? && self.param_search_query != "Eventname"

The tests pass and I’m back to hunting bigger game…


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s