It might help to understand that:
"foo" === /foo/
is actually another way to write:
"foo".===(/foo/)
So it's actually a method call to the instance method String#===
on "foo"
(which is an instance of class String
), passing it /foo/
as the argument. Therefore what will happen is totally defined by String#===
.
In your code, what actually happens is this:
if /\A([a-z][a-z\d\-+\.]*:|\/\/).*/i === options
# ...
elsif String === options
# ...
elsif :back === options
# ...
elsif Proc === options
# ...
else
# ...
end.delete("\0\r\n")
Therefore your case
statements are actually method calls to (in order of appearance):
Regex#===
Module#===
Symbol#===
- and then again
Module#===
Regarding the second example in your question:
'string' === /string/ # => false
This above is calling String#===
which, according to the documentation:
Returns whether str == obj, similar to Object#==.
If obj is not an instance of String but responds to to_str, then the
two strings are compared using case equality Object#===.
Otherwise, returns similarly to #eql?, comparing length and content.
That's why it doesn't match, because it actually calls Object#==
.
Similarly:
# this calls `Proc#===`, not `Module#===`
(Proc.new {}) === Proc # => false
# however, if you want to test for class equality you should do:
Proc === (Proc.new {}) # => true, calls `Module#===`
Same goes for Hash.new === Hash
.