A Quick Guide to Basic Caching in Ruby on Rails

Caching is a useful method that can improve the performance of web applications. By caching frequently accessed data and pages it can make the application faster, can serve content more quickly resulting in a better user experience, and improve the scalability of the application by reducing the number of requests made to the database. In this blog post, we will discuss some commonly used caching methods in Ruby on Rails.

cache_if: caches the result of a block of code only if a condition is true. This is helpful when the block is difficult to compute, but you only want to save it under certain circumstances. For example, if a user is not logged in, you might not want to save some parts of a web page that are personalized to the user, but if the user is logged in, caching these portions can improve the application’s performance.

1
2
3
4
5
<% cache_if(current_user.present?, "user_sidebar") do %>
  <div class="sidebar">
    <!-- sidebar content for logged-in users here -->
  </div>
<% end %>

Caching a partial view only if the user is logged in

1
2
3
4
5
6
7
@products = if params[:category_id].present?
  cache_if(params[:category_id].present?, tag: "products_by_category_#{params[:category_id]}") do
    Product.where(category_id: params[:category_id]).all
  end
else
  Product.all
end

Caching the result of a database query only if a specific parameter is present in the request

cache_unless: allows you to specify the condition that must be false in order for the block of code to be cached. For example, if a user is not an admin, you might not want to keep certain parts of a webpage that only admins can see in the memory. But if the person is an admin, storing those parts in the memory can make the application work faster.

1
2
3
4
5
6
7
@products = if current_user.guest?
  Product.all
else
  cache_unless(current_user.admin?, tag: "products_by_user_#{current_user.id}") do
    current_user.products.all
  end
end

Caching a frequently-accessed database query result only if the user is not a guest

1
2
3
@weather = cache_unless(current_user.admin?, tag: "weather_for_#{params[:location]}") do
  WeatherAPI.get_weather(params[:location])
end

Caching the result of a remote API call only if the user is not an admin

cached: true: is an option that can be added to Rails’ render method, and when used, it instructs Rails to cache the output of the rendered template. This means that instead of generating the same template from scratch each time it is requested, Rails will reuse the cached output from previous renders, which helps to speed up rendering times.

1
<%= render partial: "product", object: @product, cached: true, cache: "product/#{params[:id]}" %>

Caching a partial view with a dynamic key

1
2
3
4
5
<% cache("products_index", expires_in: 1.hour) do %>
  <% @products.each do |product| %>
    <%= render partial: "product", object: product, cached: true, cache: "product/#{product.id}" %>
  <% end %>
<% end %>

Caching an entire view for an hour

cache_store: this is a configuration option in Ruby on Rails that allows you to specify where Rails should store cached data. This could be a file system cache, a memory cache, or an external caching service such as Redis or Memcached.

1
2
# config/environments/production.rb
config.cache_store = :file_store, "tmp/cache"

Using the file system cache store

1
2
# config/environments/production.rb
config.cache_store = :redis_cache_store, { url: ENV["REDIS_URL"], namespace: "cache" }

Using Redis as the cache store