[Ruby on Rails (RoR)] Difference between ==, eql?, equal?, === and object_id in Ruby

==, eql?, equal?, === and object_id

Ruby provide few ways to check object value equality.

Equality operators: == and !=

The == operator, also known as equality or double equal, will return true if both objects are equal and false if they are not.

1
2
3
4
5
2.6.1 :017 > "abc" == "abc"
true

2.6.1 :018 > "abc" != "abc"
false

eql?

The eql? method returns true if obj and other refer to the same hash key. This is used by Hash to test members for equality. For objects of class Object, eql? is synonymous with ==. Subclasses normally continue this tradition by aliasing eql? to their overridden ==method, but there are exceptions. Numeric types, for example, perform type conversion across ==, but not across eql?, so:

1
2
1 == 1.0     #=> true
1.eql? 1.0 #=> false

equal?

Unlike the == operator which tests if both operands are equal, the equal? method checks if the two operands refer to the same object. This is the strictest form of equality in Ruby.

Case equality operator: ===

Many of Ruby’s built-in classes, such as String, Range, and Regexp, provide their own implementations of the === operator, also known as case-equality, triple equals or threequals. Because it’s implemented differently in each class, it will behave differently depending on the type of object it was called on. Generally, it returns true if the object on the right “belongs to” or “is a member of” the object on the left. For instance, it can be used to test if an object is an instance of a class (or one of its subclasses)

1
2
3
4
String === "zen"  # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true

object_id

Returns an integer identifier for obj.

The same number will be returned on all calls to object_id for a given object, and no two active objects will share an id.

Note: that some objects of builtin classes are reused for optimization. This is the case for immediate values and frozen string literals.

Immediate values are not passed by reference but are passed by value: nil, true, false, Fixnums, Symbols, and some Floats.

1
2
3
4
Object.new.object_id  == Object.new.object_id  # => false
(21 * 2).object_id == (21 * 2).object_id # => true
"hello".object_id == "hello".object_id # => false
"hi".freeze.object_id == "hi".freeze.object_id # => true

Summary

I’d roughly summarize my approach to these methods like this:

  • If just comparing the content is eqaul or not, use eql?

  • If compare the same object, use equal? or object_id

See more exapmple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

# "" VS ""
2.6.1 :017 > "" == ""
true
2.6.1 :018 > "" === ""
true
2.6.1 :019 > "".eql? ""
true
2.6.1 :020 > "".equal? ""
false

# 1 VS 1
2.6.1 :025 > 1 == 1
true
2.6.1 :027 > 1 === 1
true
2.6.1 :028 > 1.eql? 1
true
2.6.1 :029 > 1.equal? 1
true

# 1.0 VS 1
2.6.1 :021 > 1.0 == 1
true
2.6.1 :022 > 1.0 === 1
true
2.6.1 :023 > 1.0.eql? 1
false
2.6.1 :024 > 1.0.equal? 1
false

# "".object_id
2.6.1 :033 > "".object_id
70281556450900
2.6.1 :034 > "".object_id
70281556445200

# 1.object_id
2.6.1 :035 > 1.object_id
3
2.6.1 :036 > 1.object_id
3

# 1.0.object_id
2.6.1 :040 > 1.0.object_id
-36028797018963966
2.6.1 :041 > 1.0.object_id
-36028797018963966
2.6.1 :042 > 1.00.object_id
-36028797018963966
2.6.1 :043 > 1.000.object_id
-36028797018963966

# 1.001.object_id
2.6.1 :044 > 1.001.object_id
-35992768221945006
2.6.1 :045 > 1.001.object_id
-35992768221945006

# :a.object_id, symbol#object_id always be same
2.6.1 :038 > :a.object_id
765468
2.6.1 :039 > :a.object_id
765468

References

[1] Difference Between ==, eql?, equal? in ruby | by Khalidh Sd | Medium - https://medium.com/@khalidh64/difference-between-eql-equal-in-ruby-2ffa7f073532

[2] Ruby Tip #1: Demystifying the Difference Between == and eql? · (think) - https://batsov.com/articles/2011/11/28/ruby-tip-number-1-demystifying-the-difference-between-equals-equals-and-eql/