Ruby Hash trick for creating an in-memory cache

bajena

Jan Bajena

Posted on May 11, 2021

Ruby Hash trick for creating an in-memory cache

In this short post I'd like to show you a smart trick for memoizing results of computations in memory. Sometimes you need to store results of multiple operations in memory for reuse and typically it's done using a Hash instance.

E.g. let's say that we have a method called for checking whether a Star Wars character is from the dark side:

def dark_side?(character_name)
  StarWars::Character.find_by(name: character_name).dark_side?      
end
Enter fullscreen mode Exit fullscreen mode

The method is heavy, because it needs to run a DB query in order to get a result for a given input, so if we know that there might be a need for calling it many times with the same character_name it might make sense to store the result for future use.

Here's one possibility of how the results can be memoized:

def dark_side?(character_name)
  @dark_side_cache ||= {}

  @dark_side_cache[character_name] = StarWars::Character.find_by(name: character_name).dark_side? unless @dark_side_cache.key?(character_name)      

  @dark_side_cache[character_name]
end
Enter fullscreen mode Exit fullscreen mode

However, Ruby's Hash has a nice constructor variant that allows passing a block.

Check this solution out, isn't it a pure Ruby beauty? 💅

def dark_side?(character_name)
  @dark_side_cache ||= Hash.new do |hash, char_name|
    hash[char_name] = StarWars::Character.find_by(name: char_name).dark_side?
  end
  @dark_side_cache[character_name]
end
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
bajena
Jan Bajena

Posted on May 11, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related