Tech Racho エンジニアの「?」を「!」に。
  • 開発

[Rails 5] rails dev:cacheコマンドでdevelopmentモードでのキャッシュを簡単にオン・オフできる

こんにちは、hachi8833です。BigBinaryシリーズ、今回はRails 5でdevelopmentモードのキャッシュを簡単にオンオフできる機能を紹介します。

元記事

確認に使った環境

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の要請で追加された機能です。

訳注: 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シリーズ)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。