# Problem: use case stmt on object's class in simple test

**URL:** <https://rubytalk.org/t/problem-use-case-stmt-on-objects-class-in-simple-test/61604>\
**Category:** ruby-talk\
**Created:** [26 January 2011 23:10 UTC](https://rubytalk.org/t/problem-use-case-stmt-on-objects-class-in-simple-test/61604 "2011-01-26T23:10:20Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Richard3](https://avatars.discourse-cdn.com/v4/letter/r/b5a626/32.png) [@Richard3](https://rubytalk.org/u/Richard3)\
**Post date:** [26 January 2011 23:10 UTC](https://rubytalk.org/t/problem-use-case-stmt-on-objects-class-in-simple-test/61604/1 "2011-01-26T23:10:20Z")

</div>

Hi,

The following is a toy abstract from an app I'm writing.

hash = {:Name=\>"Tom"}  
hash.each\_key { |key|  
&nbsp;&nbsp;puts "key %s (class = %s) =\> %s (class = %s)" %  
&nbsp;&nbsp;&nbsp;&nbsp;[key.inspect, key.class, hash[key], hash[key].class]  
&nbsp;&nbsp;case hash[key].class  
&nbsp;&nbsp;&nbsp;&nbsp;when String; p has[key]  
&nbsp;&nbsp;&nbsp;&nbsp;else; puts "hash[key].class not found"  
&nbsp;&nbsp;end  
}

The output is:  
key :Name (class = Symbol) =\> Tom (class = String)  
hash[key].class not found

Why isn't the "when String" statement executed?

Thanks in Advance,  
Richard

P.S. I wonder if the time will come when I won't regularly stumble  
over apparent anomalies when writing Ruby code.

---

<div class="post-metadata">

**Author:** ![Aaron\_D\_Gifford](https://avatars.discourse-cdn.com/v4/letter/a/cdc98d/32.png) [@Aaron\_D\_Gifford](https://rubytalk.org/u/Aaron_D_Gifford)\
**Post date:** [27 January 2011 00:10 UTC](https://rubytalk.org/t/problem-use-case-stmt-on-objects-class-in-simple-test/61604/2 "2011-01-27T00:10:06Z")

</div>

user@host:/path$ irb  
irb(main):001:0\> a = "Foo"  
=\> "Foo"  
irb(main):002:0\> a.class === String  
=\> false  
irb(main):003:0\> a === String  
=\> false  
irb(main):004:0\> a.class === String.class  
=\> false  
irb(main):005:0\> a  
=\> "Foo"  
irb(main):006:0\> a.inspect  
=\> "\"Foo\""  
irb(main):007:0\> String.inspect  
=\> "String"  
irb(main):008:0\> case a  
irb(main):009:1\> when String  
irb(main):010:1\> puts 'string'  
irb(main):011:1\> else  
irb(main):012:1\* puts 'not'  
irb(main):013:1\> end  
string  
=\> nil  
irb(main):014:0\> String === a  
=\> true  
irb(main):015:0\> a === String  
=\> false  
irb(main):016:0\> root@secure:/usr/ports# irb  
irb(main):001:0\> str = "a string"  
=\> "a string"  
irb(main):002:0\> str.class  
=\> String  
irb(main):003:0\> String === str.class  
=\> false  
irb(main):004:0\> String === str  
=\> true  
irb(main):005:0\> case str.class  
irb(main):006:1\> when String  
irb(main):007:1\> puts 'it is a string'  
irb(main):008:1\> else  
irb(main):009:1\* puts 'else executed'  
irb(main):010:1\> end  
else executed  
=\> nil  
irb(main):011:0\> case str  
irb(main):012:1\> when String  
irb(main):013:1\> puts 'it is a string'  
irb(main):014:1\> else  
irb(main):015:1\* puts 'else executed'  
irb(main):016:1\> end  
it is a string  
=\> nil  
irb(main):017:0\>

> Why isn't the "when String" statement executed?

I believe case/when uses the when object's === method for matching,  
and as you can see from the above irb session, String === "a  
string".class evaluates to false. Hence your code doesn't work like  
you expected.

However, if you change to hash[key] instead of hash[key].class, a  
direct comparison to the class object should work (note the String ===  
"a string" evaluates to true).

Note that "a string" === String evaluates to false even though "a  
string" === String evaluates to true. That way case String when "a  
string" won't match but case "a string" when String will. (Which  
totally makes sense in the context of case/when.)

I'm sure I read a great blog post or discussion on this very thing in  
the past on the web, one that explains the gory details about exactly  
why case/when was designed to work this way. It currently slips my  
mind.

Anyone got a good URL for an article/post like that?

Aaron out.

---

<div class="post-metadata">

**Author:** ![Richard3](https://avatars.discourse-cdn.com/v4/letter/r/b5a626/32.png) [@Richard3](https://rubytalk.org/u/Richard3)\
**Post date:** [27 January 2011 03:06 UTC](https://rubytalk.org/t/problem-use-case-stmt-on-objects-class-in-simple-test/61604/3 "2011-01-27T03:06:15Z")

</div>

Hey Aaron,

You scored a triple. I should say you scored 3 homers. In order of  
importance on my grading scale:

1. You solved my problem: Lose the ".class"

2. You showed me that using IRB for experimenting like this is far  
better than littering one's code with debugging statements.

3. You reminded me to RTFM! Actually, I rotate between books, PDFs  
and blogs on Ruby, Rails, CSS, RSpec, etc. all the time. But as I  
encountered this unfathomable situation, I didn't do what I've now  
done: Consult PickAxe (2nd ed., 2005), which confirmed your belief  
that case uses === for a comparison of the case parameter and when  
arguments.

Many thanks for your deep and insightful solution to my question.

Best wishes,  
Richard

> **···**
>
> On Jan 26, 7:10 pm, "Aaron D. Gifford" \<astound...@gmail.com\> wrote:
> 
> > user@host:/path$ irb  
> > irb(main):001:0\> a = "Foo"  
> > =\> "Foo"  
> > irb(main):002:0\> a.class === String  
> > =\> false  
> > irb(main):003:0\> a === String  
> > =\> false  
> > irb(main):004:0\> a.class === String.class  
> > =\> false  
> > irb(main):005:0\> a  
> > =\> "Foo"  
> > irb(main):006:0\> a.inspect  
> > =\> "\"Foo\""  
> > irb(main):007:0\> String.inspect  
> > =\> "String"  
> > irb(main):008:0\> case a  
> > irb(main):009:1\> when String  
> > irb(main):010:1\> puts 'string'  
> > irb(main):011:1\> else  
> > irb(main):012:1\* puts 'not'  
> > irb(main):013:1\> end  
> > string  
> > =\> nil  
> > irb(main):014:0\> String === a  
> > =\> true  
> > irb(main):015:0\> a === String  
> > =\> false  
> > irb(main):016:0\> root@secure:/usr/ports# irb  
> > irb(main):001:0\> str = "a string"  
> > =\> "a string"  
> > irb(main):002:0\> str.class  
> > =\> String  
> > irb(main):003:0\> String === str.class  
> > =\> false  
> > irb(main):004:0\> String === str  
> > =\> true  
> > irb(main):005:0\> case str.class  
> > irb(main):006:1\> when String  
> > irb(main):007:1\> puts 'it is a string'  
> > irb(main):008:1\> else  
> > irb(main):009:1\* puts 'else executed'  
> > irb(main):010:1\> end  
> > else executed  
> > =\> nil  
> > irb(main):011:0\> case str  
> > irb(main):012:1\> when String  
> > irb(main):013:1\> puts 'it is a string'  
> > irb(main):014:1\> else  
> > irb(main):015:1\* puts 'else executed'  
> > irb(main):016:1\> end  
> > it is a string  
> > =\> nil  
> > irb(main):017:0\>
> > 
> > \> Why isn't the "when String" statement executed?
> > 
> > I believe case/when uses the when object's === method for matching,  
> > and as you can see from the above irb session, String === "a  
> > string".class evaluates to false. Hence your code doesn't work like  
> > you expected.
> > 
> > However, if you change to hash[key] instead of hash[key].class, a  
> > direct comparison to the class object should work (note the String ===  
> > "a string" evaluates to true).
> > 
> > Note that "a string" === String evaluates to false even though "a  
> > string" === String evaluates to true. That way case String when "a  
> > string" won't match but case "a string" when String will. (Which  
> > totally makes sense in the context of case/when.)
> > 
> > I'm sure I read a great blog post or discussion on this very thing in  
> > the past on the web, one that explains the gory details about exactly  
> > why case/when was designed to work this way. It currently slips my  
> > mind.
> > 
> > Anyone got a good URL for an article/post like that?
> > 
> > Aaron out.
