Ruby DISCUSSION

How does case/when really work in Ruby? Ranges, classes and regular expressions in one statement

Started by rahisen Ruby case whencase equality operatortriple equalsrange matchingpattern matching
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

How does case/when really work in Ruby? Ranges, classes and regular expressions in one statement

rahisen Ruby Forum
#1

I am replacing a chain of if/elsif with case in Ruby. I see examples where when is followed by a number, a range like 0...341, a class like Integer and even a regular expression, all in the same style. But my attempt case value.class when Integer never matches, even for integers.

What comparison does when actually perform, is there fall-through as in C, and why does the class check fail?

Community replies 5

Re: How does case/when really work in Ruby? Ranges, classes and regular expressions in one statement

#2

when does not use ==. For each candidate it evaluates candidate === value, with the when expression on the left, and different classes define === differently. For most objects it is the same as ==. For a Range it tests whether the value lies inside. For a Class or Module it tests whether the value is an instance, like is_a?. For a Regexp it tests whether the string matches. For a Proc it calls the proc with the value. That single rule is what lets one case mix all those forms.

Re: How does case/when really work in Ruby? Ranges, classes and regular expressions in one statement

#3

That also explains the failure. case value.class when Integer evaluates Integer === value.class, which asks whether the class object Integer is itself an instance of Integer. It is not; it is an instance of Class. Pass the value itself: case value when Integer then ... when Float then ... when String then ... end.

The operator is not symmetric. Integer === 5 is true, 5 === Integer is false, and (1..10) === 5 is true while 5 === (1..10) is false. In a case, the pattern is always the receiver.

Re: How does case/when really work in Ruby? Ranges, classes and regular expressions in one statement

#4

There is no fall-through and no break. The first when that matches runs and the statement ends. To give several alternatives to one branch, separate them with commas: when 1, 2, 3 or when "y", "yes". else is the default branch; without it an unmatched case evaluates to nil.

case is an expression, so assign its result directly: level = case adc when 0...341 then :low when 341...682 then :mid else :high end. For a 10-bit reading of 0 to 1023 those two ranges and the else split the span into three nearly equal bands, and the three-dot form excludes the upper bound so no value belongs to two bands.

Re: How does case/when really work in Ruby? Ranges, classes and regular expressions in one statement

#5

Order matters because the first match wins. Put the more specific patterns first: with overlapping ranges, or with classes where one inherits from another (when Numeric before when Integer would make the second branch unreachable), the earlier branch hides the later one.

Be careful with floats as literal patterns. when 3.3 is an exact equality test, and a value computed as 1.1 * 3 is not exactly 3.3. Use a range such as 3.25..3.35 to express a tolerance.

Re: How does case/when really work in Ruby? Ranges, classes and regular expressions in one statement

#6

Two more forms. A case with no subject is a tidy if/elsif chain, where each when takes a full boolean expression: case when temp > 80 then shutdown when temp > 60 then warn end. And a lambda can be a pattern because of Proc#===: with even = ->(n) { n.even? }, when even calls it with the value.

Ruby 3 also has pattern matching, written case value in pattern. It uses in where the classic form uses when, can destructure arrays and hashes, and raises NoMatchingPatternError if nothing matches and there is no else. It is a separate feature with its own rules, so do not mix the two keywords in one statement.

TEP COMMUNITY