Checking Equality of Objects in Ruby
There are four methods for checking equality of objects in the Ruby programming language:
===
used for case comparison==
used for equality of objectseql?
used for determining object identityequal
used for comparing the hash key of two objects
Case Equality with ===
The ===
method is used for checking the case equality of two objects. When you use the case
statement, this method will be the one used to see whether or not there is a match.
Here's an example. We have a class Book
where we are storing a unique id, the isbn
. When two books are compared, they are equal if their ISBNs are the same.
class Book
attr_accessor :isbn
def initialize(isbn)
@isbn = isbn
end
def ===(other)
isbn == other.isbn
end
end
bookA = Book.new(1000)
bookB = Book.new(2000)
puts bookA === bookA # => true
puts bookA === Book.new(1000) # => false
puts bookB === bookA # => false
puts bookB === bookB # => true
puts bookB === Book.new(1000) # => false
puts bookB === Book.new(2000) # => true
puts case Book.new(2000)
when bookA
'ISBN matches book A'
when bookB
'ISBN matches book b'
else
'no match'
end # => ISBN matche book b
If we did not override the ===
equality method, the default comparison would have used the ==
method.
Let's consider another example: a user session for product analytics. The class has a field for the user id and the session start time. We can define the equality to be a comparison between both fields. Since only comparing the user ids would result in all sessions from one user to be seen as equivalent, both fields must be compared.
class UserSession
attr_accessor :user_id, :session_start_time
def ==(other)
self.user_id == other.user_id && self.session_start_time == other.session_start_time
end
end
==
equality comparison
This is similar to what we did above in the Book
code example:
class Book
attr_accessor :title
def initialize(title)
@title = title
end
def ==(other)
title.downcase == other.title.downcase
end
end
eql?
comparison
The eql?
method compares the object hash key.
For example:
value = {'a': 1}
other = {'a': 1}
puts value == other # => true
puts value.eql?(other) # => true
other = value
puts value == other # => true
puts value.eql?(other) # => true
equal?
comparison
In contrast to eql?
, the equal?
method compares the object identity.
For example:
value = {'a': 1}
other = {'a': 1}
puts value == other # => true
puts value.equal?(other) # => false
other = value
puts value == other # => true
puts value.equal?(other) # => true