Skip to content

Instantly share code, notes, and snippets.

@tejasbubane
Created April 6, 2025 17:27
Show Gist options
  • Save tejasbubane/365b290fdd91d21da9081d8f7b493a8b to your computer and use it in GitHub Desktop.
Save tejasbubane/365b290fdd91d21da9081d8f7b493a8b to your computer and use it in GitHub Desktop.
Pattern matching on custom objects in Ruby
require "minitest/autorun"
require "minitest/spec"
class Event
attr_reader :name, :venue
def initialize(name, venue)
@name = name
@venue = venue
end
def deconstruct
[name, venue]
end
end
class Book
attr_reader :name, :published_year
def initialize(name:, published_year:)
@name = name
@published_year = published_year
end
def deconstruct_keys(keys)
{ name:, published_year: }
end
def deconstruct
[name, published_year]
end
end
describe "Pattern matching" do
it "matches on basic objects" do
assert_pattern { 1 => Integer }
assert_pattern { "foo" => String }
assert_pattern { [1, 2, 3] => Array }
assert_pattern { [1, 2, 3] => [a, b, c] }
[1, 2, 3] => [a, b, c]
assert a == 1
assert b == 2
assert c == 3
assert_pattern { { a: 10, b: 20 } => { a:, b: } }
{ a: 10, b: 20 } => { a:, b: }
assert a == 10
assert b == 20
refute_pattern { 1 => String }
refute_pattern { [1, 2] => [x, y, z] }
refute_pattern { { a: 100, b: 200 } => { a:, x:, y: } }
end
it "matches partial hash but not array" do
refute_pattern { [1, 2, 3, 4] => [1, a] }
assert_pattern { {a: 1, b: 2, c: 3, d: 4} => { a: } }
{a: 1, b: 2, c: 3, d: 4} => { a: }
assert a == 1
end
it "matches on Data objects" do
User = Data.define(:name, :email)
u = User.new("Sam", "[email protected]")
assert_pattern { u => User(name, email) }
u => User(name, email)
assert name == "Sam"
assert email == "[email protected]"
Account = Data.define(:name, :email)
refute_pattern { u => Account(name, email) }
end
it "matches on custom classes with deconstruct method" do
e = Event.new("Music Jam", "Orchird Road")
assert_pattern { e => Event(name, venue) }
end
it "does not match on custom classes without deconstruct_keys method" do
e = Event.new("Music Jam", "Orchird Road")
refute_pattern { e => Event(name:, venue:) }
refute_pattern { e => Event[name:, venue:] }
end
it "matches on custom classes with deconstruct_keys method" do
b = Book.new(name: "Animal Farm", published_year: "1984")
assert_pattern { b => Book[name:, published_year:] }
assert_pattern { b => Book[name, published_year] }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment