# How to use "case" to match class names? (=== not so funny)

**URL:** <https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681>\
**Category:** Ruby\
**Created:** [August 14, 2011, 5:48pm UTC](https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681 "2011-08-14T17:48:40Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [August 14, 2011, 5:48pm UTC](https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681/1 "2011-08-14T17:48:40Z")

</div>

Hi, easy example of what I need:

* * *

klass = String

## case klass when String puts “I’m String class” else puts “I’m nothing…” end

It produces “I’m nothing…”. I understand why:

“case” matches the given object using “===”, and:

String === String  
=\> false

while:

String === “a new string”  
=\> true

But in my case, klass variable holds a class rather than a class  
instance. How could I use it within the above “case” statement? The  
only way I’ve found is:

* * *

klass = String

case klass.name  
when “String”  
puts “I’m String class”  
else  
puts “I’m nothing…”  
end

---

<div class="post-metadata">

**Author:** ![SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/54ee81/32.png) [@SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/u/SSISSaki_Baz_C.SS_S)\
**Post date:** [August 14, 2011, 6:04pm UTC](https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681/2 "2011-08-14T18:04:09Z")

</div>

I don’t think there’s a better solution than what you already have.  
There are different ones, of course - good ol’ if…elsif…else chain,  
a hash with classes being its keys ({String=\>“I’m String class”,  
Fixnum=\>“I’m an integer”}[klass] || “I’m nothing”) - but I wouldn’t  
say they are better.

Maybe something else could be redone? Where does that class come from?

– Matma R.

---

<div class="post-metadata">

**Author:** ![SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/54ee81/32.png) [@SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/u/SSISSaki_Baz_C.SS_S)\
**Post date:** [August 14, 2011, 6:07pm UTC](https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681/3 "2011-08-14T18:07:15Z")

</div>

2011/8/14 Bartosz Dziewoński [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> I don’t think there’s a better solution than what you already have.  
> There are different ones, of course - good ol’ if..elsif..else chain,  
> a hash with classes being its keys ({String=\>“I’m String class”,  
> Fixnum=\>“I’m an integer”}[klass] || “I’m nothing”) - but I wouldn’t  
> say they are better.
> 
> Maybe something else could be redone? Where does that class come from?

I need “klass” to hold a class name, not an instance. That cannot be  
changed.

Thanks.

---

<div class="post-metadata">

**Author:** ![SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/54ee81/32.png) [@SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/u/SSISSaki_Baz_C.SS_S)\
**Post date:** [August 14, 2011, 6:33pm UTC](https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681/4 "2011-08-14T18:33:15Z")

</div>

2011/8/14 Chris W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> end  
> You could also modify it to accept a variable number of arguments to check  
> against multiple classes in a single when statement:  
> false  
> end
> 
> This form works with a single class as well.

Really great, thanks a lot.

---

<div class="post-metadata">

**Author:** ![SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/54ee81/32.png) [@SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/u/SSISSaki_Baz_C.SS_S)\
**Post date:** [August 14, 2011, 6:27pm UTC](https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681/5 "2011-08-14T18:27:41Z")

</div>

> ## end
> 
> It produces “I’m nothing…”. I understand why:
> 
> “case” matches the given object using “===”, and:
> 
> String === String  
> =\> false

Correct, because triple equals checks to see if the value is an instance  
or subclass of a class, not if it’s the actual class itself

> while:
> 
> String === “a new string”  
> =\> true

Which is why this works. One way to potentially get around this is to  
have an object that simple holds a class and overrides the === operator  
to make case work properly:

class ClassCheck  
def initialize(klass)  
@holder = klass  
end

def ===(other)  
@holder == other  
end  
end

klass = String

case klass  
when ClassCheck.new(String)  
puts “String”  
else  
puts “Nothing”  
end

You could also modify it to accept a variable number of arguments to  
check against multiple classes in a single when statement:

class ClassCheck  
def initialize(\*klass)  
@holder = klass  
end

def ===(other)  
@holder.each { | klass |  
return true if klass == other  
}  
false  
end  
end

klass = String

case klass  
when ClassCheck.new(Object, Numeric, String)  
puts “One of these”  
else  
puts “Nothing”  
end

This form works with a single class as well.

Regards,  
Chris W.  
[http://www.twitter.com/cwgem](http://www.twitter.com/cwgem)

---

<div class="post-metadata">

**Author:** ![SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/54ee81/32.png) [@SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/u/SSISSaki_Baz_C.SS_S)\
**Post date:** [August 15, 2011, 11:08am UTC](https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681/6 "2011-08-15T11:08:03Z")

</div>

On Aug 14, 2011, at 09:26 , Chris W. wrote:

> def ===(other)  
> @holder.each { | klass |  
> return true if klass == other  
> }  
> false  
> end

def === o  
@holder.any? { |k| k == o }  
end

---

<div class="post-metadata">

**Author:** ![SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/54ee81/32.png) [@SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/u/SSISSaki_Baz_C.SS_S)\
**Post date:** [August 15, 2011, 11:09am UTC](https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681/7 "2011-08-15T11:09:17Z")

</div>

On Aug 14, 2011, at 08:47 , Iaki Baz C. wrote:

> klass = String
> 
> case klass  
> when String  
> puts “I’m String class”  
> else  
> puts “I’m nothing…”  
> end

case  
when String == klass then

# …

else

# …

end

or to do a much cleaner version of the multi-match example above:

case  
when [String, Whatever].include? klass then

# …

else

# …

end

---

<div class="post-metadata">

**Author:** ![SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/54ee81/32.png) [@SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/u/SSISSaki_Baz_C.SS_S)\
**Post date:** [August 15, 2011, 1:48pm UTC](https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681/8 "2011-08-15T13:48:24Z")

</div>

2011/8/15 Ryan D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> case  
> when [String, Whatever].include? klass then
> 
> # …
> 
> else
> 
> # …
> 
> end

The most ellegant way. Thanks.

---

<div class="post-metadata">

**Author:** ![SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/54ee81/32.png) [@SSISSaki\_Baz\_C.SS\_S](https://www.ruby-forum.com/u/SSISSaki_Baz_C.SS_S)\
**Post date:** [August 15, 2011, 2:49pm UTC](https://www.ruby-forum.com/t/how-to-use-case-to-match-class-names-not-so-funny/210681/9 "2011-08-15T14:49:10Z")

</div>

“Iñaki Baz C.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote in post #1016614:

> But in my case, klass variable holds a class rather than a class  
> instance. How could I use it within the above “case” statement? The  
> only way I’ve found is:
> 
> * * *
> 
> klass = String
> 
> case klass.name  
> when “String”  
> puts “I’m String class”  
> else  
> puts “I’m nothing…”  
> end

As you’ve found, Class#=== tells you if an object in an instance of a  
class  
(like is\_a?), and this is how it’s intended to be used.

You could in some cases _make_ an instance (as long as the initializer  
doesn’t need any arguments):

case klass.new  
when String  
puts “I’m a String”  
end

But case is really intended for ‘matches’ tests. If you want ‘equal to’,  
then maybe you’re better off with a simple Hash.

KLASS\_LOOKUP = {  
String =\> lambda { puts “I’m a String” },  
}  
KLASS\_LOOKUP.default = lambda { puts “Something else” }

klass = String  
KLASS\_LOOKUP[klass].call
