Pattern Matching
23.1 case / in Patterns
def handle(response)
case response
in { status: 200, body: } # hash pattern + binding
"OK: #{body}"
in { status: 301 | 302, headers: { location: } } # alternative + nested
"Redirect to #{location}"
in { status: 400..499 => code } # range + bind with =>
"Client error #{code}"
in { status: Integer => code } if code >= 500 # guard clause
"Server error #{code}"
in [Symbol => type, *rest] # array pattern with splat
"Tuple #{type} with #{rest.size} items"
in String | Symbol => name
"Name: #{name}"
in nil
"Nothing"
else
"Unknown"
end
end23.2 Pattern Types
in 0, in "ok", in:admin in Integer, in 1..10, in /\A\d+\z/
in [x, y], in [first, *], in [*, last] in [*, { role::admin } => admin, *]
in { name: String => name, age: }, in { role::admin, rest }, in { nil } (no extra keys) in Integer => n
in ^expected (match an existing variable's value), in ^(1 + 1) in [x, y] if x > y
23.3 Standalone Pattern Matching
config = { db: { user: "admin", port: 5432 } }
config => { db: { user:, port: } } # rightward destructuring (raises NoMatchingPatternKeyError if no match)
puts user, port
if config in { db: { port: Integer } } # boolean check
puts "valid port"
end23.4 Custom Classes in Patterns
Struct and Data support deconstruct/deconstruct_keys automatically.
class Point
attr_reader :x, :y
def initialize(x, y) = (@x, @y = x, y)
def deconstruct = [x, y] # array patterns
def deconstruct_keys(keys) = { x:, y: } # hash patterns
end
case Point.new(0, 5)
in Point(x: 0, y:) then "On the y-axis at #{y}"
in Point[x, y] if x == y then "Diagonal"
end