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.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
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.