ActiveSupport::Cache

RubyRailsCache LibraryWeb DevelopmentBackendORM

GitHub Overview

rails/rails

Ruby on Rails

Stars57,276
Watchers2,311
Forks21,912
Created:April 11, 2008
Language:Ruby
License:MIT License

Topics

activejobactiverecordframeworkhtmlmvcrailsruby

Star History

rails/rails Star History
Data as of: 8/13/2025, 01:43 AM

Library

ActiveSupport::Cache

Overview

ActiveSupport::Cache is a comprehensive caching framework built into Ruby on Rails.

Details

ActiveSupport::Cache is a sophisticated caching system provided as part of the Ruby on Rails framework. It supports multiple cache stores (memory, file, Redis, database, etc.) and offers a unified API for cache operations. The framework provides essential methods like read, write, delete, exist?, and fetch, along with advanced features such as automatic cache key generation, expiration management, and hierarchical cache invalidation. Starting with Rails 7, database-backed Solid Cache is available by default, enabling stable caching in distributed environments. The system comprehensively provides functionality necessary for web application performance improvement, including fragment caching, SQL query caching, and page caching.

Pros and Cons

Pros

  • Unified API: Operate multiple cache stores through the same interface
  • Rich Store Options: Diverse choices including memory, file, Redis, and database
  • Rails Integration: Seamless usage through deep framework integration
  • Automatic Key Management: Automatic cache key generation and collision avoidance
  • Hierarchical Invalidation: Cache clearing functionality based on dependencies
  • Encryption Support: Secure data caching capabilities
  • Distributed Support: Horizontal scaling through sharding functionality

Cons

  • Rails Dependency: Limited usage outside Rails projects
  • Learning Curve: Need to master configuration options and optimization techniques
  • Memory Usage: Important memory management when caching large amounts of data
  • Debug Complexity: Identifying cache-related issues can be challenging
  • Performance Dependency: Improper usage may actually degrade performance

Key Links

Code Examples

Basic Cache Operations

# Writing to cache
Rails.cache.write("user:123", user_data, expires_in: 1.hour)

# Reading from cache
cached_user = Rails.cache.read("user:123")

# Existence check
if Rails.cache.exist?("user:123")
  puts "Cache exists"
end

# Deleting cache
Rails.cache.delete("user:123")

Utilizing the fetch Method

# Retrieve from cache if exists, otherwise execute block and save to cache
user = Rails.cache.fetch("user:#{id}", expires_in: 12.hours) do
  User.find(id)
end

# Conditional caching
expensive_data = Rails.cache.fetch("calculation:#{params}", expires_in: 1.day) do
  # Heavy computation process
  perform_expensive_calculation(params)
end

# Nested cache keys
Rails.cache.fetch(["user", user.id, "profile", user.updated_at]) do
  user.profile_data
end

Bulk Operations with Multiple Keys

# Read multiple caches at once
user_ids = [1, 2, 3, 4, 5]
cache_keys = user_ids.map { |id| "user:#{id}" }
cached_users = Rails.cache.read_multi(*cache_keys)

# Write multiple caches at once
users_data = {
  "user:1" => user1_data,
  "user:2" => user2_data,
  "user:3" => user3_data
}
Rails.cache.write_multi(users_data, expires_in: 2.hours)

# Delete multiple caches at once
Rails.cache.delete_multi("user:1", "user:2", "user:3")

Fragment Caching

<!-- Fragment caching in ERB templates -->
<% cache ["user_profile", @user, @user.updated_at] do %>
  <div class="user-profile">
    <h2><%= @user.name %></h2>
    <p><%= @user.bio %></p>
    <!-- Heavy rendering process -->
  </div>
<% end %>

<!-- Conditional fragment caching -->
<% cache_if @user.cache_enabled?, ["user_data", @user] do %>
  <div class="user-data">
    <%= render 'expensive_partial' %>
  </div>
<% end %>

Custom Cache Store Configuration

# config/environments/production.rb
# Redis cache store configuration
config.cache_store = :redis_cache_store, {
  url: ENV['REDIS_URL'],
  connect_timeout: 30,
  read_timeout: 0.2,
  write_timeout: 0.2,
  reconnect_attempts: 1,
  namespace: 'cache'
}

# File cache store configuration
config.cache_store = :file_store, '/var/cache/rails', {
  namespace: 'app_cache',
  expires_in: 1.hour
}

# Memory cache store configuration (development environment)
config.cache_store = :memory_store, {
  size: 64.megabytes,
  namespace: 'development_cache'
}

Solid Cache Configuration and Usage

# config/cache.yml
production:
  database: cache_production
  store_options:
    max_age: <%= 2.weeks.to_i %>
    max_entries: 1_000_000
    namespace: <%= Rails.env %>
    encrypt: true

development:
  database: cache_development
  store_options:
    max_size: <%= 256.megabytes %>
    namespace: development
# config/environments/production.rb
config.cache_store = :solid_cache_store

# Solid Cache specific configuration
config.solid_cache.size_estimate_samples = 1000
config.solid_cache.encrypt = true
config.solid_cache.key_hash_stage = :indexed

Advanced Caching Patterns

class UserService
  def self.fetch_user_with_associations(user_id)
    Rails.cache.fetch("user_full:#{user_id}", expires_in: 1.hour) do
      User.includes(:profile, :posts, :followers)
          .find(user_id)
          .as_json(include: [:profile, :posts, :followers])
    end
  end

  def self.invalidate_user_cache(user_id)
    # Bulk delete related caches
    Rails.cache.delete_matched("user*:#{user_id}*")
    Rails.cache.delete("user_count")
    Rails.cache.delete("recent_users")
  end

  def self.warm_cache(user_id)
    # Cache preloading
    fetch_user_with_associations(user_id)
    Rails.cache.fetch("user_stats:#{user_id}", expires_in: 6.hours) do
      calculate_user_statistics(user_id)
    end
  end
end

# Cache integration in models
class User < ApplicationRecord
  after_update :expire_cache
  after_destroy :expire_cache

  def cached_profile
    Rails.cache.fetch(cache_key_with_version) do
      profile.as_json
    end
  end

  private

  def expire_cache
    Rails.cache.delete(cache_key_with_version)
    Rails.cache.delete_matched("user*:#{id}*")
  end
end