Enable caching in development mode in Rails

What Happens When You Run Rails dev:cache Command?

You can enable caching in development mode by running the `rails dev:cache` command in terminal. Ever wondered what that command does, and how exactly does it tell Rails to start caching stuff in your application? Let's take a peek behind the curtain to see exactly what's going on.

2 min read
The rails dev:cache command toggles caching in development.

By default, Rails enables caching only in production environment. To enable it in the development mode, you can run rails dev:cache command. To disable it, re-run the command.

$ bin/rails dev:cache
Development mode is now being cached.

$ bin/rails dev:cache
Development mode is no longer being cached.

Behind the scenes, it's implemented as a Thor command that delegates to the Rails::DevCaching module.

# railties/lib/rails/commands/dev/dev_command.rb

require "rails/dev_caching"

module Rails
  module Command
    class DevCommand < Base
      desc "cache", "Toggle development mode caching on/off"
      def cache
        Rails::DevCaching.enable_by_file
      end
    end
  end
end

The DevCaching::enable_by_file method does the following:

  1. Create a tmp directory if it doesn't exist.
  2. If the caching file (named caching-dev.txt) is present inside the tmp directory, it means caching is enabled. Delete that file to disable it. Otherwise, create it to enable caching.
  3. Finally, touch the restart.txt file to instruct Rails to restart the app.
# railties/lib/rails/dev_caching.rb

require "fileutils"

module Rails
  module DevCaching
    class << self
      FILE = "tmp/caching-dev.txt"

      def enable_by_file
        FileUtils.mkdir_p("tmp")

        if File.exist?(FILE)
          delete_cache_file
          puts "Development mode is no longer being cached."
        else
          create_cache_file
          puts "Development mode is now being cached."
        end

        FileUtils.touch "tmp/restart.txt"
      end
    end
  end
end

How Rails Uses the Caching File?

When your Rails application starts, it checks for the presence of the caching file above, and if it exists, it does the following:

  1. Enable perform_caching and enable_fragment_cache_logging on the controller.
  2. Set the cache store to :memory_store.
  3. Add the Cache-Control header to public with max-age set to two days.

Otherwise, it disables caching and uses the :null_store.

# config/environments/development.rb

if Rails.root.join("tmp/caching-dev.txt").exist?
  config.action_controller.perform_caching = true
  config.action_controller.enable_fragment_cache_logging = true

  config.cache_store = :memory_store
  config.public_file_server.headers = {
    "Cache-Control" => "public, max-age=#{2.days.to_i}"
  }
else
  config.action_controller.perform_caching = false

  config.cache_store = :null_store
end
  • perform_caching configures whether the application should perform the caching features provided by Action Controller or not.
  • enable_fragment_cache_logging determines whether to log fragment cache reads and writes in a verbose format.
  • cache_store configures which cache store to use for Rails caching.

The above settings instruct Rails to perform caching. How it implements it, well, that's a topic for another blog post. Stay tuned.

💡
This post is part of the Rails Internals series that explores the internals of Ruby on Rails by reading the source code.

That's a wrap. I hope you liked this article and you learned something new.

As always, if you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. I reply to all emails I get from developers, and I look forward to hearing from you.

If you'd like to receive future articles directly in your email, please subscribe to my blog. If you're already a subscriber, thank you.