I’ve seen this question pop up more than a few times in #ruby-lang. For sooth, I hit this wall once myself: why is my case statement broken?
Here’s two seemingly equivalent pieces of code:
the_what = :sealab if the_what.class == Symbol puts "The what is a symbol." elsif the_what.class == String puts "The what is a string." else puts "I don't know what the what is." end
the_what = :sealab case the_what.class when Symbol puts "The what is a symbol." when String puts "The what is a string." else puts "I don't know what the what is." end
Running the if statement gives The what is a symbol. Running the case statement gives I don’t know what the what is. So, is case broken?
No. We just made an faulty assumption. Listen: case != if.
We all know if conditions work by checking for the truthiness of a statement. Is it true or is it false? Simple.
case works differently. Rather than checking for true or false using ==, case uses === to test expressions. How is this different?
Unlike, say, PHP, Ruby’s === can be overridden by classes to provide “meaningful semantics in case statements.” So says the Ruby core documentation. In fact, the docs call === “Case Equality.”
Back to our examples and trusty irb:
>> the_what = :sealab => :sealab >> the_what.class == Symbol => true >> the_what.class === Symbol => false
We’re on the right track. Checking the === docs for Module, we see === returns true if the passed object is an instance of the receiver. Since the_what.class gives us Symbol and a Symbol is not an instance of Symbol, we get false. In other words:
>> the_what = :sealab => :sealab >> Symbol === Symbol => false >> Symbol === the_what => true
Since the_what is a Symbol, we get true. This explains why our previous case statement is falling through to the final else. Let’s rewrite it with our newfound Ruby powers:
the_what = :sealab case the_what when Symbol puts "The what is a symbol." when String puts "The what is a string." else puts "I don't know what the what is." end
Running this new code gives us The what is a symbol. That feels much better.
For further case magic, check out _why’s Wonder of the When-Be-Splat.