A quick dive into Low-Level Caching in Ruby on Rails

cache

Caching is a vital and yet often forgotten part of our application that can significantly improve our application’s performance. The simple definition of caching is the act of storing data so that future requests for that data can be served faster. In this article, we are going through low-level caching or model caching that you can apply immediately in your Rails application right away.

Low-Level Caching is by far the simplest caching method which also works best if you only want to cache a particular value instead of the whole view fragment. In fact, Rails already provided built-in methods to perform this type of caching i.e., Rails.cache.fetch, Rails.cache.read and Rails.cache.write. Below are examples of how you can use these methods:-

#read and write method
> Rails.cache.write("cache_key", 999)
> Rails.cache.read("cache_key")
=> 999
> Rails.cache.read("key-not-written")
=> nil

#fetch method
Rails.cache.fetch("cache_key") do
 999
end

> Rails.cache.fetch("cache_key")
=> 999

#alternatively, you can also add an cache expiry duration using expires_in attribute
Rails.cache.fetch "cache_key", expires_in: 60.minutes do
  999
end

To have a better understanding on how we can apply low-level caching in our application, let’s go through a real live example. Let’s assume that we are running a grocery store and we have an Item table in our database with model like the following:-

# app/models/item.rb
class Item < ApplicationRecord
  def index
    @items = Item.all
  end
end

If we want to display the list of items for our customer, we might do the following:-

# app/views/item/index.html.erb

<% @items.each do |item| %>
  <%= item.name %>: <%= item.price %> <br/>
<% end %>

However, there is a problem with the code above. Every time a user makes a request to the page above, we will need to query and load all the items and in our database. This will clearly be a performance issue when our application grow i.e., when we have more users or when our we have more items row in our database.

To alleviate this issue, we can simply apply model caching like below:-

# app/models/item.rb

class Item < ApplicationRecord
  def index
    Rails.cache.fetch "item", expires_in: 24.hours do
      @items = Item.all    
    end 
  end
end

With the changes above, when user make request to the index page, our application will be looking for the cache key “items”. If the cache key is found, the cache value i.e., @items will be return, otherwise, a database query will be made to fetch the value of @items and this value will then be store as the new cache. Noted that we have set expires_in value to 24.hours here which stand for the duration until the cache is expired and when the cache is expired, a new request will be made to the database to get the value of @items.

Conclusion

Low-Level caching can significantly improve the performance and speed of you Rails application and should not be taken for granted. However, it is important to take note that this caching technique is only useful when used at the right situation. We should focus on caching static content that will not be updated frequently. Alternatively, we can also take advantage of time-base expiration feature by setting expires_in duration to closely match the duration in which the cache value will expire.

Share on twitter
Twitter
Share on telegram
Telegram
Share on facebook
Facebook
Share on linkedin
LinkedIn
Share on email
Email

Leave a Comment

Your email address will not be published. Required fields are marked *