Unless, The Abused Ruby Conditional

Some people hate unless in Ruby. I personally do not, but I try to abide by a few rules. I’ll explain with some examples below. The uses that I label as “ok” below could just be personal preference, so I will not refer to them as “good”, but I would definitely avoid using the ones I label as “bad”.

Statement Modifier…Ok

I think unless actually reads better than if ! when used as a statement modifier. For example, I think this…

raise InvalidFormat unless AllowedFormats.include?(format)

…reads better than this…

raise InvalidFormat if !AllowedFormats.include?(format)

I think the reason I like the former incarnation is because it would read like a sentence to almost anyone, even those unfamiliar with Ruby (like my mom and we all know it is important for moms to be able to read code).

Without Else…Ok

I also don’t mind using unless when you are just checking one condition and not using else like so…

unless foo? # bar that thing end

With an Else…Bad

What I dislike is when unless is used with an else like so…

unless foo? # bar that thing else # foo that thing end

If you have code like this, just swap the code doing the work and use if . Trust me, it reads a lot better.

if foo? # foo that thing else # bar that thing end

The if version just feels easier to process than the version with unless . I think using unless with else is like speaking with double negatives. It slows down the next programmer in the code, as they have to think instead of just flowing through the conditional, if that makes sense.

When testing nil?…Bad

As Ryan Bates pointed out in the comments below, testing nil like this…

unless foo.nil? # do some foo end

…is a bit more readable like this…

if foo # do some foo end

unless foo.nil? and if foo equate to the same thing but is kind of a double negative issue, like I just mentioned about using unless with else . Thanks for the another bad unless tip Ryan!

With Multiple Conditions…Bad

The reason I hate (and it is hate, not just dislike as above) unless with multiple conditions is that I always forget whether the “not” applies to only the first conditional or to all of them. If you are wondering, the “not” does apply to all conditionals, but just talking about it has me feeling confused again, so please do not do this…

unless foo? && baz? # bar that thing end

Instead, I would probably do something like this…

if !foo? || !baz? # bar that thing end

Final Thoughts