In Ruby, a `case` statement tries its `when` conditions in order. The match test is a call to `===`, often called the case equality or threequal operator. For `case answer; when "yes"`, Ruby tests `"yes" === answer`. The `when` object is the receiver; the `case` object is the argument. That order matters because reversing them need not give the same result. section 6.1.3
The operator is a method, so its meaning depends on the receiver. For a string tested against another string, it checks for matching contents. A class can define `===` to supply its own matching rule. Where it has not been overridden, `===` has the same behavior as `==`. section 6.1.3 section 11.7.4
Listing 6.2 Implementing case statement behavior for the Ticket class
class Ticket
attr_accessor :venue, :date
def initialize(venue, date)
self.venue = venue
self.date = date
end
def ===(other_ticket) 1
self.venue == other_ticket.venue
end
end
ticket1 = Ticket.new("Town Hall", "07/08/25")
ticket2 = Ticket.new("Conference Center", "07/08/25")
ticket3 = Ticket.new("Town Hall", "08/09/25")
puts "ticket1 is for an event at: #{ticket1.venue}."
case ticket1
when ticket2 2
puts "Same location as ticket2!"
when ticket3 3
puts "Same location as ticket3!"
else
puts "No match."
end
The `Ticket` example defines `===` to compare venues. In `case ticket1`, each ticket after `when` tests `ticket1`, so the ticket with the same venue matches even though its date differs. section 6.1.3
The receiver also determines what a match means elsewhere:
- A regular expression tests whether a string matches its pattern. Thus `when /^y/i` can accept an answer beginning with `y`, regardless of case. Unlike `match`, which returns `nil` or a `MatchData` object, `===` gives a true-or-false test. section 11.7.4
- `Enumerable#grep(expression)` selects elements for which `expression === element` is true. A class can select strings, a range can select an included number, and a regular expression can select matching strings. An optional block transforms the selected results. section 10.3.3 section 11.7.4
>> miscellany = [75, "hello", 10...20, "goodbye"]
=> [75, "hello", 10...20, "goodbye"]
>> miscellany.grep(String) 1
=> ["hello", "goodbye"] 1
>> miscellany.grep(50..100) 2
=> [75] 2
The mixed array makes receiver behavior visible: `grep(String)` returns its strings, while `grep(50..100)` returns `75`. section 10.3.3
