Scaling Ruby on Rails Applications: Techniques and Tools for Optimizing Performance - Part 1 (Caching)

Caching is a technique that can improve the performance of your Ruby on Rails application by storing frequently accessed data in memory or on disk. In this article, we will explore how to use caching in Ruby on Rails, and we will provide some code examples to illustrate the different types of caching available.

Page Caching

Page caching is a technique where the entire HTML output of a page is cached in memory or on disk. When the same page is requested again, the cached version is served directly, without running any code.

To enable page caching, you need to specify which actions should be cached in your controller:

1
2
3
4
5
6
7
8
9
10
11
class PagesController < ApplicationController
  caches_page :home, :about
  
  def home
    # Render home page
  end
  
  def about
    # Render about page
  end
end

In this example, the caches_page method specifies that the home and about actions should be cached. When these actions are requested, the resulting HTML will be stored in a file on disk. The next time the same action is requested, the cached HTML will be served instead of running the action code.

Action Caching

Action caching is similar to page caching, but it allows you to cache only the output of a specific action. This is useful when you have dynamic content on a page that needs to be refreshed periodically.

To enable action caching, you need to specify which actions should be cached in your controller:

1
2
3
4
5
6
7
8
9
10
11
class ProductsController < ApplicationController
  caches_action :index, :show
  
  def index
    @products = Product.all
  end
  
  def show
    @product = Product.find(params[:id])
  end
end

In this example, the caches_action method specifies that the index and show actions should be cached. When these actions are requested, the resulting HTML will be stored in memory or on disk. The next time the same action is requested with the same parameters, the cached HTML will be served instead of running the action code.

Fragment Caching

Fragment caching is a technique where only a specific part of a page is cached. This is useful when you have a complex page with dynamic content, and you want to cache only the parts that are slow to generate.

To enable fragment caching, you need to wrap the dynamic content with a cache block:

1
2
3
4
5
6
<% cache('recent_posts', expires_in: 1.hour) do %>
  <h2>Recent Posts</h2>
  <% @posts.each do |post| %>
    <p><%= link_to post.title, post %></p>
  <% end %>
<% end %>

In this example, the cache method specifies that the content inside the block should be cached with the key recent_posts, and it should expire in 1 hour. The next time the same block is rendered, the cached content will be served instead of running the block code.

Low-Level Caching

Low-level caching allows you to cache arbitrary data, such as the result of a database query or a complex computation.

To enable low-level caching, you can use the Rails.cache.fetch method:

1
2
3
4
5
def get_products
  Rails.cache.fetch('products', expires_in: 1.hour) do
    Product.all
  end
end

In this example, the Rails.cache.fetch method specifies that the data with the key products should be cached for 1 hour. The Product.all code inside the block will be executed only if the data is not already cached.

Conclusion

Caching is an important technique for improving the performance of your Ruby on Rails applications. By using the caching mechanisms provided by Rails, you can reduce the amount of time it takes to retrieve data from a data source, reduce the load on your servers, and improve the user experience. Whether you’re building a small website or a large-scale web application, caching is an essential tool to have in your performance optimization toolkit.