Bang bang object returns true?

Okay, so going through the https://www.railstutorial.org book, I’m on chapter 6, section 6.3.4 and I come across this “gem” (not the ruby gem).

!!user.authenticate("foobar") # returns true

Okay, so I get !false = true, and !!true = true, but what’s going on here?

Is it because the authenticate method can return false (when it fails to authenticate), so !user.authenticate("wrong pass") returns true, and !user.authenticate("right pass") would return false?

So you have to double the bang operators to get the desired boolean values? (that seems to be the case)

!! negates an object twice, thereby coercing it to its boolean value.

irb(main):001:0> false => false irb(main):002:0> !false => true irb(main):003:0> !!false => false irb(main):004:0> !true => false irb(main):005:0> !!true => true irb(main):006:0>

2 Likes

Good. I did understand it correctly. Thanks. I’m not sure I’d personally use my prior example all that often as it feels like you ask for an object but then you refuse to use it…

There is likely a better way of expressing intent here that the book hasn’t fully shown/suggested yet.

A common use of the double bang operator is to have your predicate methods return true or false, rather than truthy or falsy values. E.g.

class String
  def contains?(val)
    self.downcase.match(val)
  end
end

p "Sitepoint".contains?("point") # => #<MatchData "point"> 
p "Sitepoint".contains?("overflow") # => nil

Compared with:

class String
  def contains?(val)
    !!self.downcase.match(val)
  end
end

p "Sitepoint".contains?("point") # => true
p "Sitepoint".contains?("overflow") # => false

Check out the TrueClass which provides operators allowing true to be used in logical expressions.

You can also write the above as:

class String
  def contains?(val)
    true & self.downcase.match(val)
  end
end

p "Sitepoint".contains?("point") # => true
p "Sitepoint".contains?("overflow") # => false

Which seems a little more readable.

Reference: http://www.techfreak.net/programming,/ruby/2011/07/27/notnot-alternative.html

1 Like

Instead of a double bang you can check that your expression is not equal to nil or to false.

For example:

user.authenticate("foobar") != nil

If “authenticate” returns nil, when authentication fails.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.