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