こんにちは、hachi8833です。BigBinaryシリーズ、今回はRails 5でdevelopmentモードのキャッシュを簡単にオンオフできる機能を紹介します。
元記事
確認に使った環境
- Railsバージョン: 5.0.2(5.0-stable)
 - Rubyバージョン: 2.4.0p0
 
Rails 5の新機能: developmentモードのキャッシュを簡単に制御できるようになった
Rails 4まで
Rails 4までは、developmentモードのキャッシュを切り替えるためにいちいちconfig/environments/development.rbを開いて以下の設定のfalse/trueを切り替え、さらにサーバーを再起動しなくてはなりませんでした。
config.action_controller.perform_caching = false
ローカルキャッシュの動作を調べたりするときに地味に面倒です。
Rails 5以降
Rails 5では、developmentモードのキャッシュを簡単に作成できる新しいコマンドが導入されました。これにより、キャッシュの動作を切り替えて振る舞いの違いを簡単に確認できます。DHHの要請で追加された機能です。
- Issue: #18875: rake dev:cache
 - Pull Request: #20961: Add dev caching toggle / server options
 
訳注: Rails 5.0.2のconfig.action_controller.perform_cachingのデフォルト設定は以下のとおりです。
- development: 
false(tmp/caching-dev.txtがある場合のみtrue) - production: 
true - test: 
false 
$ rails dev:cache
Development mode is now being cached.
上のようにrails dev:cacheコマンドを実行すると、tmp/ディレクトリにcaching-dev.txtファイルが作成されます。
キャッシュの仕組み
Rails 5で新規作成したRailsアプリでは、config/environments/development.rbに以下のコードが含まれるようになりました。以下は5.0.2で確認しました。
  # Enable/disable caching. By default caching is disabled.
  if Rails.root.join('tmp/caching-dev.txt').exist?
    config.action_controller.perform_caching = true
    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => 'public, max-age=172800'
    }
  else
    config.action_controller.perform_caching = false
    config.cache_store = :null_store
  end
このコードでは、tmp/caching-dev.txtが存在する場合にのみ:mem_cache_storeでキャッシュを有効にします。
以下は当時のdev_cacheコマンドのソースです。
def dev_cache
  if File.exist? 'tmp/caching-dev.txt'
    File.delete 'tmp/caching-dev.txt'
    puts 'Development mode is no longer being cached.'
  else
    FileUtils.touch 'tmp/caching-dev.txt'
    puts 'Development mode is now being cached.'
  end
  FileUtils.touch 'tmp/restart.txt'
end
訳注: ただしその後コードがさらに変わり、現在はモジュールとしてrailties/lib/rails/dev_caching.rbにあります。
require "fileutils"
module Rails
  module DevCaching # :nodoc:
    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"
        FileUtils.rm_f("tmp/pids/server.pid")
      end
      def enable_by_argument(caching)
        FileUtils.mkdir_p("tmp")
        if caching
          create_cache_file
        elsif caching == false && File.exist?(FILE)
          delete_cache_file
        end
      end
      private
        def create_cache_file
          FileUtils.touch FILE
        end
        def delete_cache_file
          File.delete FILE
        end
    end
  end
end
新機能のメリットと注意
キャッシュのオン/オフを切り替えるためにサーバーを再起動する必要がなくなりました。dev:cacheコマンドを実行したときに内部で実行されるdev_cacheがよしなにやってくれます。tmp/restart.txtがtouchで作成されることをソースコードで確認できます。
この機能はunicorn、thin、webrickではサポートされないのでご注意ください。この点について、DHHのチームではpowを採用しており、powはtmp/restart.txtをtouchすると再起動するようになっているからではないかと(元記事の著者が)推測しています。実際、DHHはだいぶ以前にもspringの監視リストにtmp/restart.txtを追加するissueを作成しています。
キャッシュをオフにするには
rails dev:cacheコマンドはトグルになっているので、実行のたびにオンとオフが切り替わります。
$ rails dev:cache
Development mode is no longer being cached.
訳注
Pumaについて
原文ではRails 5のデフォルトのサーバーであるPumaについて言及がありません。Rails 5.0.2の素の環境で試してみたところ、少なくとも設定レベルではPumaで正常に動作していることを確認できました。
ビューで<%= Rails.cache %>と<%= Rails.configuration.cache_store %>を追加しただけの簡素な方法です。
rails dev:cacheでオンにした場合
rails dev:cacheでオフにした場合
rails dev:cacheを実行するとRailsが再起動されるので、2、3秒待つ必要があります。
Railsの起動オプションでdevelopmentキャッシュを指定する
デフォルトではdevelopmentキャッシュはオフになります。
rails startに--no-dev-cachingを付けると、developmentキャッシュを明示的にオフにして起動できます。
rails startに--dev-cachingを付けると、developmentキャッシュを明示的にオンにして起動できます。
不要な場合はdevelopmentキャッシュをオンにしないようにしましょう。
関連記事(BigBinaryシリーズ)
- [Rails 5] コントローラの制約を受けずに任意のビューテンプレートをレンダリングする
 - [Rails 5] rakeタスクがrailsコマンドでもできるようになった
 - [Rails 5] Rails 5の新フレームワークデフォルト設定ファイルでアップグレード作業を軽減する
 - [Rails 5] マイグレーション時にデータベースのカラムにコメントを追加する
 
      

