Reason #65 •
March 6th, 2026
Custom equality for custom classes
Yesterday we looked at how many of Ruby's built-in data structures consider two objects with the same content to be equal by default.
Instances of custom classes, on the other hand, are not considered equal by default:
Ruby
class Person
attr_reader :name
def initialize(name)
@name = name
end
end
Person.new("Alice") == Person.new("Alice")
# => false
However, we can define our own equality logic by overriding the #== method in our class:
Ruby
class Person
attr_reader :name
attr_reader :social_security_number
def initialize(name, social_security_number)
@name = name
@social_security_number = social_security_number
end
def ==(other)
other.is_a?(Person) && social_security_number == other.social_security_number
end
end
Person.new("Alice Bacon", 1337) == Person.new("Alice Bacon", 1337)
# => true
# Alice got married and changed surname, but it's still the same person:
Person.new("Alice Bacon", 1337) == Person.new("Alice Pickles", 1337)
# => true
# No luck impersonating Alice with a different social security number:
Person.new("Alice Pickles", 1337) == Person.new("Alice Pickles", 1312)
# => false
This can be handy when equality has a specific meaning in the domain we're modeling. For example, in Rails's ORM, ActiveRecord, two records are considered equal if they have the same class and the same primary key because they represent the same row in the database.