A Clever Way to Use default_proc in a Hash
Let’s explore an interesting way to use the default_proc
feature in a Ruby Hash. Suppose we have a RANKS
hash to determine the badge a player receives in a game based on their points. If the points don’t match any of the defined ranges, the result should be :none
. We’ll create a rank method to receive the points and iterate through the hash to find the appropriate badge.
RANKS = {
1..10 => :rabbit,
11..50 => :falcon,
51..100 => :dog,
101.. => :tiger
}
RANKS.default = :none
def rank(points)
_, badge = RANKS.find { |range, _| range.include?(points) }
badge || RANKS.default
end
Here’s what we get when we use the rank
method:
puts rank(0) # none
puts rank(20) # falcon
puts rank(100) # dog
puts rank(5000) # tiger
It would be convenient to retrieve the badge directly from the hash, for example, using RANKS[20]
to get :falcon
. However, since the keys are ranges, we can’t directly use a number as a key. This is where default_proc
comes in handy.
The default_proc
is called whenever we try to access an element in the hash using a non-existent key. Since the keys of RANKS
are ranges, default_proc
will be triggered when we attempt to use the number of points as the key, like RANKS[20]
.
RANKS = {
1..10 => :rabbit,
11..50 => :falcon,
51..100 => :dog,
101.. => :tiger
}
RANKS.default_proc = proc do |hash, key|
_, badge = hash.find { |range, _| range.include?(key) }
badge || :none
end
Now, we can retrieve the badge directly from the hash, using the points as a key, and let the hash handle the heavy lifting:
puts RANKS[0] # none
puts RANKS[20] # falcon
puts RANKS[100] # dog
puts RANKS[5000] # tiger
Cheers!
Banner photo by Muriel Liu on Unsplash