Ruby Case Statement comparison ... a feature, not a bug :)

By: Johnathon Wright on: November 26, 2008

I accidentally discovered an unintuitive aspect of Ruby case statements. I can't decide whether it's a bug or a feature, or both.

This code results in 'failure'

---ruby case Integer when Integer   'success' else   'failure'

end

whereas this code results in 'success'

---ruby case 3 when Integer   'success' else   'failure'

end

Ruby uses the === operator for  "case-statement equality":http://www.pluitsolutions.com/2006/10/09/comparing-equality-eql-equal-and-case-equality-in-ruby/ . When the left-hand is an instance, then it operates as ==. When the left-hand is an object, then the operator returns true if the right-hand.class.ancestors.include?(left_hand). Here are a few examples of the behavior. The value being tested (3, above) is on the right. The values that cause you to fall in to the case (Integer, above) are on the left.

---ruby

These two instances are equal

'hello' === 'hello' => true

When the left-hand operand is a Class, then we test whether the right side

is an instance of this class or one of its ancestors, rather than for equality.

String === 'hello' => true

String is an instance of Object.

Object === String true

however, String is not an instance of a String or any of its ancestors.

String === String => false

That operand also handles other magical behaviors of case statements, such as ranges:

(1..10) === 4 => true (1..10) === 20

=> false

UPDATE: An "exception to this rule":http://blog.mustmodify.com/2009/05/1day-rubys-case-operator-behaved-badly.html :

---rbuy

Fixnum === 3.days=> false



Back