Railsのbelongs_toのdestroyとdeleteとdelete_allの違いを調べました
先日railsのモデルを追加していた時に,belongs_to
のオプション:dependent
について調べました.
特にdestroy
とdelete_all
とdelete
の違いがわからなくなったのでまとめておきます.
結論
has_many
の時に使うのがdestroy
とdelete_all
has_one
の時に使うのがdestroy
とdelete
delete
とdelete_all
はそれだけを消すdestroy
は子クラスの:dependent
も処理する関連を消す必要がないなら,
delete_all
のほうが効率がいい
ちなみに
destroy_all
はActiveRecordのメソッドとしてはありますが,:dependent
には指定できません.
destroy_all (ActiveRecord::Relation) - APIdock
以下実際にrails console
で試してみた
テストに使ったクラス
# 親クラス class Parent < ActiveRecord::Base has_many :children, dependent: :destroy or delete_all or delete # <- ここを変えてます end # 子クラス class Child < ActiveRecord::Base belongs_to :parent has_many :grandchild, dependent: :destroy end # 孫クラス class Grandchild < ActiveRecord::Base belongs_to :child end
親クラスのデータを1件,小クラスを2件,孫クラスを2件×2 作成してテストしました.
dependent: :delete
のとき
has_many
なので,エラーが出ます.
ArgumentError: The :dependent option must be one of [:destroy, :delete_all, :nullify, :restrict_with_error, :restrict_with_exception], but is :delete
dependent: :delete_all
のとき
[2] pry(main)> Parent.first.destroy Parent Load (0.1ms) SELECT "parents".* FROM "parents" ORDER BY "parents"."id" ASC LIMIT 1 (0.0ms) begin transaction SQL (0.2ms) DELETE FROM "children" WHERE "children"."parent_id" = ? [["parent_id", 1]] SQL (0.1ms) DELETE FROM "parents" WHERE "parents"."id" = ? [["id", 1]] (1.2ms) commit transaction => #<Parent:0x007f1c583b6b60 id: 1, created_at: Wed, 20 Apr 2016 13:20:16 UTC +00:00, updated_at: Wed, 20 Apr 2016 13:20:16 UTC +00:00>
SQLを見ると,関連するクラスについて,一致するデータをまとめて消しています.
dependent: :destroy
のとき
[14] pry(main)> Parent.first.destroy Parent Load (0.1ms) SELECT "parents".* FROM "parents" ORDER BY "parents"."id" ASC LIMIT 1 (0.0ms) begin transaction Child Load (0.0ms) SELECT "children".* FROM "children" WHERE "children"."parent_id" = ? [["parent_id", 1]] Grandchild Load (0.0ms) SELECT "grandchildren".* FROM "grandchildren" WHERE "grandchildren"."child_id" = ? [["child_id", 1]] SQL (0.1ms) DELETE FROM "grandchildren" WHERE "grandchildren"."id" = ? [["id", 1]] SQL (0.0ms) DELETE FROM "grandchildren" WHERE "grandchildren"."id" = ? [["id", 2]] SQL (0.0ms) DELETE FROM "children" WHERE "children"."id" = ? [["id", 1]] Grandchild Load (0.0ms) SELECT "grandchildren".* FROM "grandchildren" WHERE "grandchildren"."child_id" = ? [["child_id", 2]] SQL (0.0ms) DELETE FROM "grandchildren" WHERE "grandchildren"."id" = ? [["id", 3]] SQL (0.0ms) DELETE FROM "grandchildren" WHERE "grandchildren"."id" = ? [["id", 4]] SQL (0.0ms) DELETE FROM "children" WHERE "children"."id" = ? [["id", 2]] SQL (0.1ms) DELETE FROM "parents" WHERE "parents"."id" = ? [["id", 1]] (0.7ms) commit transaction => #<Parent:0x007f1c57edd558 id: 1, created_at: Wed, 20 Apr 2016 15:06:31 UTC +00:00, updated_at: Wed, 20 Apr 2016 15:06:31 UTC +00:00>
検索をかけた後,一番深い関連から1件ずつ消しています.