One of the coolest features of Ruby’s Hash class is that you can customize how it behaves when it can’t find a key. Stupid example:
# Everybody knows that you can communicate with foreigners by # speaking loudly and slowly english_to_french = Hash.new{|hash, key| hash[key] = key.upcase.split(//).join(" ") + "?!" } english_to_french["restroom"] # => "R E S T R O O M?!"
One particularly useful application of this feature is to use a Hash as a cache for some slow operation. Here’s a snippet from Firetower, where a Hash is being used as a table of user accounts. If an unknown user ID is requested, the Hash makes a web service call to retrieve the requested data, stores it away, and returns it.
@users = Hash.new do |cache, user_id| data = session.get(subdomain, "/users/#{user_id}.json") cache[user_id] = data['user'] end