ume

【Rails】dependent: :destroyとdependent: :delete_allの違い

結論

どちらもやってることは同じ
ただ処理の仕方が違うだけ.

↓処理の違い

:destroy :delete_all
処理の速さ 遅い 早い
データベースの負荷 多い 少ない
コールバックの有無 あり なし

そもそもdependent:オプションって何?

⇨親テーブルのレコードが削除されたら関連付けされた子テーブルのレコードも削除するためのもの

例えば.
2つのテーブル(UserとComment)があるとします。1(User)対多(Comment)の関係です。 上の画像ではルフィ(User)1人に対して複数のコメント(ピストル、ガトリング、ライフル)があります。もしここでルフィを削除するとコメントテーブルのid2,3,4(ゴムゴムのピストル、ガトリング、ライフル)も全て削除したいですよね。そういう時に使うオプション

もし3つテーブル(親、子、孫)があり親テーブルを削除すると子だけでなく孫も削除したい場合↓参照してください note.com

処理の速さ

:destroy場合の処理のイメージ 3つのデータを削除する場合DBに3回削除してと尋ねる。DBの負荷は多い

:delete_allの場合↓ データベースには1回しか尋ねていないので処理が早い。また1回しか尋ねていないのでDBの負荷は小さい

コールバックの有無

コールバックとは?
⇨ある処理の前に別の特定の処理を挟み込みたい時に使う。

例えばTwitterのようなアプリを作成していたとする。 運営者だけがユーザーの投稿を削除できて、 ユーザーは第三者のユーザーを削除できないみたいな仕様にしたいとする。

class User < ApplicationRecord
  has_many :posts, dependent: :destroy
end

class Post < ApplicationRecord
  belongs_to :user

  before_destroy :check_user_permission

  private

  def check_user_permission
    unless user.admin?
      errors.add(:base, "Only administrators can delete posts.")
      throw(:abort) # 削除を中止する
    end
  end
end

dependent: :destroyだとコールバック処理を削除する前に使用できるので、投稿を削除する前に運営者かユーザーかを判別する処理(check_user_permission)ができるので要件を満たせる。

まとめ

*どちらも良いところ悪いところがあるので仕様によって使い分ける必要がある。