case and when
Bean Cart's receipt printer needs a label for every order size: 1 cup, 2 to 5 cups, 6 or more, or something invalid. A tower of elsif lines comparing the same variable again and again is tiring to read. case states the variable once and lists the possibilities underneath.
The rule
casenames the value once; eachwhentests it with===.
label =
case cups
when 1 then "single"
when 2..5 then "small batch"
when (6..) then "bulk"
else "invalid"
endHow it works: Ruby takes the value after case and checks each when from top to bottom. The first one that matches runs, and the rest are skipped. There is no fall-through into the next branch, so no break is needed. else handles everything that matched nothing, and without an else the whole case returns nil. Like if, case is an expression that returns a value.
The matching uses ===, the case-equality operator from the comparison lesson, called on the when value: when 2..5 really asks (2..5) === cups. What === does depends on what you put after when:
After when |
Matches when | Example |
|---|---|---|
| A plain value | equal | when "tea" |
| A Range | the value falls inside | when 2..5 |
| A class | the value is of that class | when Integer |
| A regular expression | the text matches the pattern | when /latte/ |
One when can list several options separated by commas, meaning "any of these":
case drink
when "latte", "mocha", "flat white" then "milk drink"
when "espresso" then "black"
else "ask the barista"
endYou can also write case with no value at all. Then each when holds a full condition, and it behaves like a tidy if/elsif chain.
Ruby 3 adds a second form, case ... in, for pattern matching on the shape of arrays and hashes. It is powerful and worth learning later; case ... when is the everyday tool.
The shortcut
For each when, flip the question around: ask "does this when thing accept the value?" A range accepts numbers inside it, a class accepts its instances, a list accepts any of its items.
Take the value
cupsis 4.
Drills
Answer fast — trust the rule.
With cups = 5, which label does the Bean Cart case above return?
How many branches of a case can run for one value?
How does when Integer decide whether it matches cups?
What does a case return when nothing matches and there is no else?
How do you make one when match either "latte" or "mocha"?
Remember
casenames the value once; eachwhentests it with===, and the first match wins.- Flip the question: does this
whenthing accept the value? Ranges, classes and lists all can. - Trap: expecting fall-through or
breakas in other languages; Ruby runs just one branch.
