How to Use Pattern Matching to Locate Elements in a Hash Array

Having the following structure of a Hash that includes an Array of Hashes, for example, and you want the email of a moderator:
system = {
users: [
{ username: 'alice', role: 'admin', email: 'alice@example.com' },
{ username: 'bob', role: 'user', email: 'bob@example.com' },
{ username: 'charlie', role: 'moderator', email: 'charlie@example.com' }
]
}
moderator = system[:users].find { |u| u[:role] == 'moderator' }
email = moderator[:email]
puts email # charlie@example.com
Now here is doing the same thing in Ruby using pattern matching:
system = {
users: [
{ username: 'alice', role: 'admin', email: 'alice@example.com' },
{ username: 'bob', role: 'user', email: 'bob@example.com' },
{ username: 'charlie', role: 'moderator', email: 'charlie@example.com' }
]
}
system => {users: [*, { role: 'moderator', email: }, *]}
puts email # charlie@example.com
Let’s put the two lines one above the other:
# Using Enumerator#find
moderator = system[:users].find { |u| u[:role] == 'moderator' }
email = moderator[:email]
# Using Pattern Matching
system => {users: [*, { role: 'moderator', email: }, *]}
There is another difference between them: in case of Pattern Matching it will throw a NoMatchingPatternError when not found, while the two lines that use Enumerator#find will throw a NoMethodError:
moderator = system[:users].find { |u| u[:role] == 'THIS_ROLE_DOES_NOT_EXISTS' }
email = moderator[:email]
# undefined method '[]' for nil (NoMethodError)
system => {users: [*, { role: 'THIS_ROLE_DOES_NOT_EXISTS', email: }, *]}
# {users: [{username: "alice", role: "admin", email: "alice@example.com"},
# {username: "bob", role: "user", email: "bob@example.com"},
# {username: "charlie", role: "moderator", email: "charlie@example.com"}]}:
# [{username: "alice", role: "admin", email: "alice@example.com"},
# {username: "bob", role: "user", email: "bob@example.com"},
# {username: "charlie", role: "moderator", email: "charlie@example.com"}]
# does not match to find pattern (NoMatchingPatternError)does not match
# to find pattern (NoMatchingPatternError)
How does pattern matching work in this example
If email does not exist either as a variable or method, matching it will create a local variable with the value from the matched row's key.
system = {
users: [
{ username: 'charlie', role: 'moderator', email: 'charlie@example.com' }
]
}
system => {users: [*, { role: 'moderator', email: }, *]}
puts binding.local_variables
# => [:system, :email]
If a variable of method labeled email does exists, it will just try to match it against its value:
system = {
users: [
{ username: 'charlie', role: 'moderator', email: 'charlie@example.com' }
]
}
email = 'charlie@example.com'
system => {users: [*, { role: 'moderator', email: }, *]}
puts email # charlie@example.com
If the variable already has a value, it will be overriden if the matching is succesful:
system = {
users: [
{ username: 'charlie', role: 'moderator', email: 'charlie@example.com' }
]
}
email = 'bob@example.com'
system => {users: [*, { role: 'moderator', email: }, *]}
puts email # charlie@example.com
You can force if you want to search for the content of that variable with the ^ operator:
system = {
users: [
{ username: 'charlie', role: 'moderator', email: 'charlie@example.com' }
]
}
email = 'bob@example.com'
system => {users: [*, { role: 'moderator', email: ^email}, *]}
# {users: [{username: "charlie", role: "moderator", email: "charlie@example.com"}]}: [{username: "charlie", role: "moderator", email: "charlie@example.com"}] does not match to find pattern (NoMatchingPatternError)
👉 If you like this article and want it in your inbox each week, subscribe to my newsletter. You’ll find ideas on Ruby, software development, software testing, building products and workshops, plus notes on creativity, tech trends, and whatever else sparks my curiosity.
👐 Want to improve your developer testing skills? Visit goodenoughtesting.com/articles to discover resources on testing for developers.
👉 Join my Short Ruby Newsletter for weekly Ruby updates and visit rubyandrails.info, a directory of Ruby learning content.
🤝 Connect with me on Linkedin, Bluesky, Ruby.social, , and Twitter, where I mostly post about Ruby and Ruby on Rails.
🎥 Follow my YouTube channel for short videos about Ruby and Rails.




