Pattern Matching (case/in)
Pattern matching with case/in is a Ruby 3 feature that deconstructs arrays and hashes by shape and binds their inner values to variables in a single, readable expression.
Learn Pattern Matching (case/in) in our free Ruby course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Ruby course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You'll learn array and hash patterns, variable binding, guards, the find pattern, and the one-line => and in forms.
What You'll Learn in This Lesson
1️⃣ Array & Hash Patterns with Binding
A case/in branch matches the structure of a value and binds its parts to new variables. Array patterns match position and length; hash patterns match by key. Add an if guard to refine a match further. A trailing bare key like name: binds the value of :name .
2️⃣ Find Patterns, Types & Alternatives
The find pattern [*, x, *] locates a single element anywhere in an array. You can match by class ( Integer => x binds only if the value is an Integer), and combine choices with | . These compose to express surprisingly rich conditions concisely.
3️⃣ One-Line Patterns: => and in
For quick work you don't need a full case . The rightward-assignment form value => pattern destructures and binds, raising if it doesn't match. The boolean form value in pattern returns true or false — handy in conditions.
Your turn. A shape hash is matched on its :type . Fill in the ___ so the square branch binds the :side value.
Mini-Challenge: Event Router
Write a method that routes UI events by their shape using case/in . This is a common real-world use of pattern matching — dispatching on the structure of incoming data. Run with ruby events.rb .
Common Errors (and the fix)
- "NoMatchingPatternError" — ❌ No branch matched and there's no fallback. ✅ Add in _ or else .
- Confusing == with binding — ❌ in { name: } binds name; it doesn't compare. ✅ To require a value, write in { name: "Ada" } .
- One-line in without parens — ❌ puts x in Pattern is a syntax error. ✅ Wrap it: puts((x in Pattern)) .
- Pinning a variable — ❌ in [x, x] binds twice. ✅ To match an existing value use the pin: in [x, ^x] .
Pro Tips
- 💡 Pin operator: use ^variable to match against an existing value instead of binding a new one.
- 💡 Pairs with Struct/Data: these objects support deconstruct , so you can pattern-match domain objects directly.
- 💡 Great for parsing: JSON-shaped hashes and API responses match cleanly with hash patterns.
📋 Quick Reference — Pattern Matching
Pattern
Example
Array
in [a, b, c]
Hash
in { name:, age: }
Guard
in [n] if n > 0
Type
in Integer => n
Find
in [*, x, *]
Alternatives
in 1 | 2 | 3
One-line bind
val => pattern
Frequently Asked Questions
🎉 Lesson Complete!
- ✅ case/in matches by structure and binds inner values
- ✅ Array and hash patterns, with if guards
- ✅ Find pattern [*, x, *] and alternatives with |
- ✅ Type patterns like Integer => n
- ✅ One-line => (must match) and in (boolean)
- ✅ Next lesson: Custom Exception Classes
Practice quiz
Which keyword introduces structural pattern matching in Ruby 3?
- case/when
- match/with
- case/in
- switch/case
Answer: case/in. case/in is Ruby 3's structural pattern matching; case/when does value matching with ===.
What happens if no in pattern matches and there is no else clause?
- It raises NoMatchingPatternError
- It returns nil
- It returns false
- It skips silently
Answer: It raises NoMatchingPatternError. case/in with no matching branch and no else raises NoMatchingPatternError.
In a hash pattern, what does a bare key like name: do?
- Requires name to equal a string
- Deletes the key
- Compares with ===
- Binds the value of :name to a variable
Answer: Binds the value of :name to a variable. A bare key binds the value of that key to a new local variable of the same name.
What does the find pattern [*, x, *] do?
- Matches only 3-element arrays
- Finds a single element anywhere in the array
- Reverses the array
- Matches an empty array
Answer: Finds a single element anywhere in the array. The find pattern with two splats locates one element anywhere inside the array.
What does ({ name: "Ada" } in { name: String }) return?
- true
- false
- nil
- an error
Answer: true. The one-line in form returns true when the value matches the pattern.
What does ([1, "x"] in [Integer, Integer]) return?
- true
- nil
- false
- an error
Answer: false. "x" is not an Integer, so the structural match fails and in returns false.
What does the one-line form value => pattern do when it does NOT match?
- Returns false
- Raises NoMatchingPatternError
- Returns nil
- Returns the value
Answer: Raises NoMatchingPatternError. The => rightward-assignment form must match or it raises NoMatchingPatternError.
How do you combine alternative patterns in a single in branch?
- With &&
- With or
- With commas
- With the | operator
Answer: With the | operator. Alternatives are combined with |, as in: in "warn" | "error".
What does Integer => x do in a pattern?
- Always binds x
- Binds x only if the value is an Integer
- Converts x to an Integer
- Compares x with ==
Answer: Binds x only if the value is an Integer. A type pattern matches the class first, binding x only when the value is an Integer.
Which methods let your own objects support pattern matching?
- to_a and to_h
- match and scan
- deconstruct and deconstruct_keys
- each and map
Answer: deconstruct and deconstruct_keys. deconstruct enables array patterns and deconstruct_keys enables hash patterns.
Continue this course
- Previous: Constants & Freezing
- Next: Custom Exception Classes