Readable booleans in Ruby

I was going through the source code of Ryan Bates' gem called mustard when I stumbled upon this code:

module Mustard
  module ObjectExtension
    def must
      Must.new(self)
    end

    def must_not
      Must.new(self, true)
    end
  end
end

Notice anything?

Must.new(self, true)

This true tells us nothing, we have to go the Must class definition to find out its responsibility:

module Mustard
  class Must
    def initialize(subject, negate = false)
      @subject = subject
      @negate = negate
    end
  end
end

Ok, now we know it is used for negating.

We can improve the first piece of code by passing a speaking for itself symbol :negate instead of just passing true:

Must.new(self, :negate)

Since symbols in Ruby are always true, passing :negate is equialent to passing true. But in case of :negate, the intent is right in front of you, no need to jump to the method's definition.

There is one gotcha though - it won't work in cases where you directly compare your assigned variable to true/false. An example from the same gem:

def _assert(matcher)
  if @negate == !!matcher.match?
    message = @negate ? matcher.negative_failure_message : matcher.failure_message
    Mustard.fail(message)
  end
end

Here our @negate variable (which has a value of :negate) is being compared directly to true/false. This code won't work as expected, because :negate == true returns false. You only can use this trick if you do comparisons this way:

if @negate
# ...
end

Now that I'm thinking about it, maybe that's why the trick is not so popular :)

You're the 9861st person to read this article.