【Rails】削除したデータが残ってる!?アソシエーション経由で取得した情報はキャッシュされる

RubyOnRails

関連する子テーブルのデータを一度削除して一括で作り直す。という処理を実装した際、削除したはずのデータの情報が残ってしまっていたことがあったので、これにいついて調べた内容をまとめます。

結論

結論を先にお話しすると、アソシエーション経由で取得したデータはキャッシュされるということです。

Railsガイド 2.1.1.1 関連付けを取り出す

アソシエーション経由のデータが既に取得済みであった場合、その後削除などをしてから取得し直しても最初に取得したものがキャッシュされているため、reloadreload_〇〇 などのメソッドを使わないと反映されません。

概要

各部署の人員名簿をCSVから取得してデータを更新する機能を例にします。

テーブルは以下の通りです。

class Department < ApplicationRecord
  has_many :members
end

class Member < ApplicationRecord
  belongs_to :department
end

CSVをアップロードして内容を取得し、その情報をもとに Department に紐づくmembers を作成します。
この際既存のスタッフ情報は一旦削除し、新しく作り直す方法を採用します。

※ CSVのアップロードや情報の取得については本題ではないので割愛します。

一度削除しているのに前のIDが残っている

def update_members(department_id)
  department = Department.find(department_id)
  members = department.members

  # 確認用
  puts "before ids --------- #{members.map(&:id)}"

  # 一旦紐づくstaffを削除する
  members.each(&:destroy)

  csv_data.each do |data|
    department.members.create!(data)
  end

  # 確認用
  puts "after ids ---------- #{members.map(&:id)}"
end

アソシエーション経由でデータを取得している箇所は members = department.members この部分です。

上記のメソッドには一通りの処理の前後に確認用で members のIDを表示する箇所があります。
これを実行すると以下のように表示されるでしょう。
(※登録するmemberの数は5名分だとします)

before ids --------- [1, 2, 3, 4, 5]
after ids ---------- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

一旦削除してから作り直しているので、想定では[6, 7, 8, 9, 10]となっているはずのところ、
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]と消したはずのIDまで表示されてしまっています。

これが以前のデータのキャッシュが残っている状態です。

解決策

アソシエーション経由にしない

Member.where(department_id: department.id).destroy_all

このようにアソシエーションを経由せずに削除をすればキャッシュは残りません。

リロードする

department.members.reload.map(&:id)

上記のように reload をしてあげると情報を更新できます。
belongs_toの子テーブルの方から参照する場合は、reload_department というような reload_親テーブル メソッドが使えます。

今回は以上です。

コメント

タイトルとURLをコピーしました