表題の通りなのですが、テストも通ってよっしゃー!stagingにデプロイじゃー!と意気揚々としたものの、キャッシュを使っている箇所の表示がされない不具合が…。
とはいっても一部だけで全部のキャッシュが動かなくなったわけではなさそう。調べてみた。
ローカルでキャッシュを有効にする
Railsのアップデートを真面目にやっていれば、これで開発環境でキャッシュが有効になります。
bin/rails dev:cache
もう一度実行すると、無効になります。
因みにこれが何をやっているのかというと、tmp/caching-dev.txt
が作られます。config/environments/development.rb
で、このファイルがある場合はキャッシュを有効にするという記述があるはずです。
# Enable/disable caching. By default caching is disabled. # Run rails dev:cache to toggle caching. 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 = :dalli_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
frozen errorで落ちる
フラグメントキャッシュの存在確認で、fragment_exist?([@foo, Time.zone.now.beginning_of_month])
みたいなことをしていました。今月分はずっとキャッシュさせる的なやつです。ここで落ちていました。
RubyMineのデバッガを使って調べたところ、instrument_fragment_cache
メソッド内のinstrument_payload
メソッドにTimeWithZone型のデータが渡されると落ちるようです。それでは、instrument_payload
は何をやっているのでしょうか?
rails/caching.rb at master · rails/rails · GitHub
リンクを貼っておきますが、Hashを返しているだけ…。
def instrument_payload(key) { controller: controller_name, action: action_name, key: key } end
これでなぜ落ちるのが全く理解できないので、とりあえずこのままにしておきます…。できればissueを書きたいところです。
to_sすれば問題ない
fragment_exist?([@foo, Time.zone.now.beginning_of_month.to_s])
すれば問題ないことは確認したので、これで乗り切ることに。Date型でもいけるようだったので、to_date
でもいいでしょう。
余談
TimeWithZone型の値をcacheのkeyに設定すると、/
だらけの長いものになりました。別に害はないのですが、RailsガイドのCacheのところを読むと、keyにするには、cache_key
メソッドかto_param
メソッドが定義されている必要がある、とあります。
TimeWithZoneにはto_paramメソッドが定義されています。
Time.zone.now.to_param #=> "2019-01-17 11:19:10 +0900"
しかし、これが使われていません。掘り下げてみたところ、to_param
が呼ばれる前に、to_a
メソッドがある場合はto_a
メソッドを呼んだ後、再帰的に処理をしていました。
rails/cache.rb at master · rails/rails · GitHub
そして、TimeWithZoneにはto_a
メソッドが定義されており、配列に変換されて処理された結果、長い文字列になっていました。
Time.zone.now.to_a #=> [22, 26, 11, 17, 1, 2019, 4, 17, false, "JST"]
うーん、to_param
で処理してほしいような…。