Also known as triple equals.
This operator does not test equality, but rather tests if the right operand has an IS A relationship with the left operand. As such, the popular name case equality operator is misleading.
This SO answer describes it thus: the best way to describe a === b
is "if I have a drawer labeled a
, does it make sense to put b
in it?" In other words, does the set a
include the member b
?
Examples (source)
(1..5) === 3 # => true
(1..5) === 6 # => false
Integer === 42 # => true
Integer === 'fourtytwo' # => false
/ell/ === 'Hello' # => true
/ell/ === 'Foobar' # => false
Classes that override ===
Many classes override ===
to provide meaningful semantics in case statements. Some of them are:
╔═════════════════╦════════════════════╗
║ Class ║ Synonym for ║
╠═════════════════╬════════════════════╣
║ Array ║ == ║
║ ║ ║
║ Date ║ == ║
║ ║ ║
║ Module ║ is_a? ║
║ ║ ║
║ Object ║ == ║
║ ║ ║
║ Range ║ include? ║
║ ║ ║
║ Regexp ║ =~ ║
║ ║ ║
║ String ║ == ║
╚═════════════════╩════════════════════╝
Recommended practice
Explicit use of the case equality operator ===
should be avoided. It doesn't test equality but rather subsumption, and its use can be confusing. Code is clearer and easier to understand when the synonym method is used instead.
# Bad
Integer === 42
(1..5) === 3
/ell/ === 'Hello'
# Good, uses synonym method
42.is_a?(Integer)
(1..5).include?(3)
/ell/ =~ 'Hello'