1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rails の cache ストレージで Active Record のオブジェクトを入れると事故りやすいと思う件

Posted at

やったこと

今回、Rails のキャッシュ機構で、Active Record のオブジェクトを保存すると "色々、大変なことがあるぞ" ということについて書いていきたいと思います。

ちなみにここでいうキャッシュ機構は、cache_store のことを指します。

それでは始めます。

確認環境

$ bundle exec rails --version
Rails 5.2.4.3

$ mysql --version
mysql  Ver 14.14 Distrib 5.6.43, for osx10.13 (x86_64) using  EditLine wrapper

検証

準備

テーブル作成

CREATE TABLE `pencils` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `maker_name` varchar(50) NOT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC

データ登録

INSERT INTO pencils VALUES (NULL, 'maker1', NOW(), NOW());

app/models/pencil.rb

class Pencil < ApplicationRecord
end

config/environments/development.rb (抜粋)

config.cache_store = :memory_store

cache に保存する

$ bundle exec rails c
Running via Spring preloader in process 65049
Loading development environment (Rails 5.2.4.3)
irb(main):001:0> p = Pencil.last
   (1.3ms)  SET NAMES utf8mb4,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  Pencil Load (0.9ms)  SELECT  `pencils`.* FROM `pencils` ORDER BY `pencils`.`id` DESC LIMIT 1
=> #<Pencil id: 1, maker_name: "maker1", created_at: "2020-11-08 22:45:49", updated_at: "2020-11-08 22:45:49">
irb(main):002:0> Rails.cache.write('pencil1', p)
=> true
irb(main):003:0> Rails.cache.read('pencil1')
=> #<Pencil id: 1, maker_name: "maker1", created_at: "2020-11-08 22:45:49", updated_at: "2020-11-08 22:45:49">
irb(main):004:0> Rails.cache.read('pencil2')
=> nil

クラス名を変更する (そろそろ来るぞ!)

app/models/pencil.rb を下記のように変更します。

app/models/pencil2.rb


class Pencil2 < ApplicationRecord
end

保存してある cache を読み込む

irb(main):004:0> reload!
Reloading...
=> true
irb(main):005:0> Rails.cache.read('pencil1')
Traceback (most recent call last):
        1: from (irb):5
NameError (uninitialized constant Pencil)

はい。Pencil クラスがなくなってしまったので、ロードで失敗してしまいました。

これは、"色々、大変なことがあるぞ" の1つです。

対応方針

cacheストレージ使うときは、"安心なデータ" を入れる必要があります。

データ構造じゃない、value を入れるのが安心です。

例えば以下が "安心なデータ" と考えます。

  • 数値 例: 123
  • 文字列 例: あいう

配列、json、ハッシュもデータ構造が変わるときに対応を忘れないようにすれば、使って良いと思います。

Active Record のオブジェクトは、cacheストレージに保存しない方が安心です。

なぜかといえば、例えば、Railsのバージョンが変わったとき、ApplicationRecord の内部の構造も変わり

読み込めなくなる可能性があるからです。

はい。実際にありました。

ApplicationRecord は rails の本体に入っているため、この事態に気が付きにくいです。

また、システムが大きくなればなるほど、対応範囲の調査が大変になります(経験談)

まとめ

cacheストレージ使うときは、構造が変更される可能性が低いデータを入れましょう!!!

"安心なデータ" は、構造が変更される可能性が低いデータになります。

  • 数値 例: 123
  • 文字列 例: あいう

もちろん、配列、json、ハッシュなどを使ったほうがいいケースもあり、その場合は構造を変更するときに注意してください。

構造が変更される可能性があって、検知しづらいのが Active Record のオブジェクト だと思います。

Active Record のオブジェクト をcacheストレージに入れた方が良い場合があるかもしれませんが、

いまのところ、私は、Active Record のオブジェクト をcacheストレージに使わないほうが良いと思っています。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?