はじめに
Rails 6 に追加された新機能を試す第127段。 今回は、memory cache
編です。
Rails 5.2.4.2 や、 Rails 6.0.0 では、 キャッシュとして、 memory cache を使っていて、 キャッシュから値を取り出したあとで、その値を破壊的メソッドなどで修正すると、 キャッシュの値も変わってしまうというバグ(?) がありました。
Rails 6.0.1 以降では修正されています。
Rails 6.0.2.2, Rails 6.0.1, Rails 6.0.0, Rails 5.2.4.2 で確認しました。
$ rails --version
Rails 6.0.2.2
今回は、 User モデルを作って cache を使って値を取り出すメソッドを作成して確認していきます。
Rails プロジェクトを作る
Rails プロジェクトを新たに作成します。
$ rails new rails_sandbox
$ cd rails_sandbox
User モデルを作成する
User モデルを作成します。
$ bin/rails g model User name
User モデルに cached_name メソッドを追加する
かなりわざとらしいですが、 User
モデルに cached_name
というメソッドを追加します。
cached_name
では、 cache から name を取り出したあと、 upcase!
で変換して、再度 cache から name を取り出します。
class User < ApplicationRecord
def cached_name
name = Rails.cache.fetch("#{cache_key_with_version}/name") do
User.find(id).name
end
name.upcase!
Rails.cache.fetch("#{cache_key_with_version}/name") do
User.find(id).name
end
end
end
スクリプトを作成する
User#cached_name を呼び出すスクリプトを作ります。
User.delete_all
User.create(name: 'John')
u = User.last
p u.cached_name
p u.cached_name
p u.name
development 環境でキャッシュを有効にする
development 環境でキャッシュを有効にします。
$ bin/rails dev:cache
Development mode is now being cached.
Rails 6.0.1 以降では
スクリプトを実行すると名前は、常に John
のままです。
$ bin/rails runner scripts/user_name.rb
Running via Spring preloader in process 675
"John"
"John"
"John"
Rails 6.0.0, Rails 5.2.4.2 では
キャッシュに保存されている値が変わってしまうため、2回目の cached_name
の呼び出しのときに JOHN
に変わってしまいます。
bash-5.0# bin/rails runner scripts/user_name.rb
Running via Spring preloader in process 747
"John"
"JOHN" # => キャッシュの値が変わっている
"John"
試したソース