if __name__ is None
if __name__ is None

Reputation: 11533

Why do `foo == bar` and `bar == foo` return different results?

What is going on here? Why does a position of sides in == comparison change the output?

secret == BCrypt::Password.new(BCrypt::Password.create(secret)) 
# => false 
BCrypt::Password.new(BCrypt::Password.create(secret)) == secret
# => true 

Upvotes: 3

Views: 116

Answers (4)

Jörg W Mittag
Jörg W Mittag

Reputation: 369594

Ruby is an object-oriented language. In OO, the receiver of a message send gets to decide how to respond to that message. In your case, the two receivers are not only different objects, they are even different types of objects.

There are some standard double-dispatch protocols in Ruby which are intended to ensure that some operators are symmetric, but a) those protocols exist only for arithmetic operations on numbers not for equality, and b) there's no guarantee that an object follows those protocols.

In short, in OO, there is no way to ensure symmetry of operators. That's just a fundamental property of OO.

Upvotes: 0

Matt
Matt

Reputation: 10564

The simplest answer is that == is LHS#==, that is to say, that == is not a universal operator, like in C or C++ or Java, but rather a function called on the object on the left hand side.

Without knowing more about your code, it's difficult to tell you exactly what's going on.

In simple terms, secret.class#== must be behaving differently than BCrypt::Password#==. Perhaps BCrypt::Password knows how to compare an encrypted string (itself) and an unencrypted string (the argument), whereas secret, if it's a string, has no knowledge of how to compare BCrypt::Password to itself.

Upvotes: 1

Jeff Storey
Jeff Storey

Reputation: 57212

This is because the return value of BCrypt::Password.new is of BCrypt::Password which overrides ==

http://bcrypt-ruby.rubyforge.org/classes/BCrypt/Password.html#M000009

Compares a potential secret against the hash. Returns true if the secret is the original secret, false otherwise.

So when secret is on the left, its equals method is being used (which is doing string comparison), whereas when the hash is on the left, it is actually comparing against the original secret

Upvotes: 3

Pascal Belloncle
Pascal Belloncle

Reputation: 11389

BCrypt::Password has a == method to compare to secret.

BCrypt::Password.new(BCrypt::Password.create(secret)).class
 => BCrypt::Password 

So

BCrypt::Password.new(BCrypt::Password.create(secret)) == secret
 => true

The other expression doesn't call the method == on BCrypt::Password, but the one on string.

http://bcrypt-ruby.rubyforge.org/classes/BCrypt/Password.html#M000009

Upvotes: 1

Related Questions