Question
I am trying to understand the difference between Ruby’s four equality-related methods: equal?, eql?, ==, and ===.
I know that, by default, == eventually relies on object identity behavior similar to equal?, which returns true when both operands refer to exactly the same object.
I also read that === often delegates to == by default. If none of these methods are overridden, does that mean ===, ==, and equal? all behave the same way?
Then there is eql?. What does eql? do by default? Does it depend on something like an object’s hash or object_id?
More broadly, why does Ruby have so many different equality methods? Are they intended to represent different meanings of equality?
Short Answer
By the end of this page, you will understand the purpose of Ruby’s four equality methods, how they differ, and when each one is used. You will see that they are not redundant: equal? checks object identity, == usually checks value equality, eql? is mainly used for Hash key equality, and === is used for case matching and pattern-like comparisons.
Concept
Ruby has multiple equality methods because equality can mean different things depending on context.
The four meanings of equality in Ruby
equal?→ Are these the exact same object in memory?==→ Do these two objects represent the same value?eql?→ Are these objects equal in a way that is strict enough for hash keys?===→ Does the left-hand object consider the right-hand object a match?
These methods are related, but they serve different purposes.
equal? — object identity
equal? comes from BasicObject and is about identity, not value.
s1 = "ruby"
s2 = "ruby"
s3 = s1
p s1.equal?(s2) # false
p s1.equal?(s3) # true
Here, s1 and s2 contain the same text, but they are different string objects. s3 points to the exact same object as s1.
In practice, is rarely overridden and is used when you truly care whether two references point to the same object.
Mental Model
Think of four ways to ask whether two things are “the same”:
equal?→ Is this the exact same physical book?==→ Do these two books have the same content?eql?→ Should a filing system treat these as the same catalog entry?===→ Does this category include this item?
Example:
- Two copies of the same novel are not
equal? - They may be
==if you compare by title and content - A library catalog may use stricter rules like
eql? - The category
Fictionmight===a particular book
This is why Ruby keeps separate methods: each answers a different question.
Syntax and Examples
Core syntax
obj1.equal?(obj2)
obj1 == obj2
obj1.eql?(obj2)
obj1 === obj2
Example 1: identity vs value
a = "hi"
b = "hi"
c = a
p a.equal?(b) # false
p a == b # true
p a.equal?(c) # true
Explanation
aandbhave the same string content, soa == bistrue- They are different objects, so
a.equal?(b)isfalse creferences the exact same object asa, soa.equal?(c)istrue
Example 2: eql? with numbers
p 1 == 1.0 # true
p 1.eql?()
Step by Step Execution
Traceable example
a = "ruby"
b = "ruby"
c = a
puts a.equal?(b)
puts a == b
puts a.equal?(c)
puts String === a
Step by step
1. a = "ruby"
Ruby creates a string object and stores its reference in a.
2. b = "ruby"
Ruby creates another string object with the same content and stores its reference in b.
3. c = a
c now points to the same object as a.
4. a.equal?(b)
Ruby checks whether a and b are the exact same object.
- They are not
- Output:
false
5. a == b
Ruby checks whether the two strings have equal value.
Real World Use Cases
Where these methods appear in real Ruby code
== for normal comparisons
Used when comparing values in everyday code:
if user.role == "admin"
puts "Allow access"
end
eql? and hash for Hash keys and sets
Used when objects are stored in hashes or sets:
scores = {}
scores["alice"] = 10
scores["alice"] = 20
Ruby needs eql? and hash to decide whether the second key is the same as the first.
=== in routing, validation, and case logic
case params[:status]
when "pending", "processing"
puts "In progress"
when
puts
Real Codebase Usage
Common patterns in real projects
Guard clauses with ==
def cancel_order(order)
return unless order.status == "pending"
order.status = "cancelled"
end
This is the most common equality style in application code.
case statements powered by ===
def label(value)
case value
when String
"text"
when Integer
"whole number"
when 1..100
"small range value"
else
"unknown"
end
end
Custom value objects implementing ==, eql?, and
Common Mistakes
1. Using equal? when you mean value equality
Broken example:
puts "ruby".equal?("ruby")
A beginner may expect true, but this usually returns false because these are different string objects.
Use this instead:
puts "ruby" == "ruby"
2. Assuming === means the same as ==
Broken assumption:
puts String === "abc" # true
puts String == "abc" # false
=== is often about matching, especially in case statements.
3. Overriding eql? without overriding hash
Broken design:
Comparisons
Equality methods compared
| Method | Main meaning | Typical use | Usually overridden? | Example |
|---|---|---|---|---|
equal? | Same object identity | Low-level identity checks | Rarely | a.equal?(b) |
== | Same value | Normal application logic | Very often | user.id == other.id |
eql? | Hash-key equality | Hash and Set behavior | Often with hash |
Cheat Sheet
Quick reference
a.equal?(b) # same object?
a == b # same value?
a.eql?(b) # same hash-key equality?
a === b # does a match b?
Rules of thumb
- Use
==for most comparisons - Use
equal?only when identity matters - Use
eql?together withhashfor custom hash keys - Use
===mainly incase-style matching
Important examples
"x" == "x" # true
"x".equal?("x") # usually false
1 == 1.0 # true
1.eql?(1.0) # false
String === "hello" # true
(1..5) === 3 # true
/ell/ ===
FAQ
What is the difference between == and equal? in Ruby?
== usually checks whether two objects have the same value. equal? checks whether they are the exact same object.
What is eql? used for in Ruby?
eql? is mainly used by Hash and Set to determine whether two keys should be treated as the same key. It should be consistent with hash.
Is === the same as == in Ruby?
Not always. === is often used for matching, especially in case statements. Classes, ranges, and regexes often give it special behavior.
Why does 1 == 1.0 return true, but 1.eql?(1.0) returns false?
== compares numeric value, while eql? is stricter and distinguishes integer and float for hash-key purposes.
Mini Project
Description
Create a small Ruby program that compares values using all four equality methods. This project helps you see the difference between object identity, value equality, hash-key equality, and case matching in one place.
Goal
Build a script that prints comparison results for strings, numbers, custom objects, and case matching.
Requirements
- Create examples that demonstrate
equal?and==with strings. - Show the difference between
==andeql?using1and1.0. - Define a custom class that implements
==,eql?, andhash. - Use a
casestatement that relies on===with a range or class. - Print clear labels so the output is easy to understand.
Keep learning
Related questions
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.
Difference Between require and include in Ruby
Learn the difference between require and include in Ruby, when to load a file, and when to mix module methods into a class.
Fixing Ruby Gem Native Extension Errors: mkmf.rb Can't Find Header Files for Ruby
Learn why Ruby gem installs fail with missing ruby.h, how native extensions work, and how to fix header file errors on Linux servers.