Reputation: 11533
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
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
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
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
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