It forces a truthy-value to true and a falsy-value to false. In Ruby the only falsy-values are nil and false and everything other value is a truthy-value.
!falsyExpr # given -> true
!true # and -> false
!!falsyExpr # then -> true -> false
!truthyExpr # given -> false
!false # and -> true
!!truthyExpr # then -> false -> true
The reason to use !!expr over expr, when returned from a method like this, is that the !!expr form only yields true or false. This avoids leaking details, avoids accidental strong-references, reduces confusion when debugging, prevents cases of false/nil confusion, etc. It is also shorter than expr ? true : false, which has identical semantics.
The forms expr == nil and expr.nil? only evaluate to true when expr evaluates to nil. They are both false if expr evaluates to any other value, including false. This sets them apart from the !expr which evaluates to true for both false and nil values.
Of course the all of the above is expected behavior. Due to the open nature of Ruby and operator overloading it is possible (and very misguided) to create new methods that change this expected behavior (barring some implementation optimization quirks).