Yes, by #== the docs mean "the instance method == of the current object".
=== is used in case statements as such:
case obj
when x
foo
when y
bar
end
Is the same as
if x === obj
foo
elsif y === obj
bar
end
Some classes that define their own === are Range (to act like include?), Class (to act like obj.is_a?(klass)) and Regexp (to act like =~ except returning a boolean). Some classes that don't define their own === are the numeric classes and String.
So
case x
when 0
puts "Lots"
when Numeric
puts(100.0 / x)
when /^\d+$/
puts(100.0 / x.to_f)
default
raise ArgumentError, "x is not a number or numeric string"
end
is the same as
if 0 == x
puts "Lots"
elsif x.is_a? Numeric
puts(100.0 / x)
elsif x =~ /^\d+$/
puts(100.0 / x.to_f)
else
raise ArgumentError, "x is not a number or numeric string"
end
The two really have nothing to do with each other. In particular, #== is the equality operator and #=== has absolutely nothing to with equality. Personally, I find it rather unfortunate that #=== looks so similar to #==, uses the equals sign and is often called the case equality operator, triple equals operator or threequals operator when it really has nothing to do with equality.
I call #=== the case subsumption operator (it's the best I could come up with, I'm open to suggestions, especially from native English speakers).
The best way to describe a === b is "if I have a drawer labeled a, does it make sense to put b in it?"
So, for example, Module#=== tests whether b.is_a?(a). If you have Integer === 2, does it make sense to put 2 in a box labeled Integer? Yes, it does. What about Integer === 'hello'? Obviously not.
Another example is Regexp#===. It tests for a match. Does it make sense to put 'hello' in a box labeled /el+/? Yes, it does.
For collections such as ranges, Range#=== is defined as a membership test: it makes sense to put an element in a box labeled with a collection if that element is in the collection.
So, that's what #=== does: it tests whether the argument can be subsumed under the receiver.
What does that have to with case expressions? Simple:
Fun fact, === is also used to match exceptions in rescue
Here is an example
class Example
def self.===(exception)
puts "Triple equals has been called."
true
end
end
raise rescue Example
# => prints "Triple equals has been called."
# => no exception raised
This is used to match system errors.
SystemCallError.=== has been defined to return true when the two have the same errno. With this system call errors with the same error number, such as Errno::EAGAIN and Errno::EWOULDBLOCK, can both be rescued by listing just one of them.