Rails: dependent =>: destroy VS: depend =>: delete_all

192

Dalam panduan rel dijelaskan seperti ini:

Selain itu objek akan dihancurkan jika dikaitkan :dependent => :destroy, dan dihapus jika dikaitkan:dependent => :delete_all

Benar, keren. Tetapi apa perbedaan antara dihancurkan dan dihapus? Saya mencoba keduanya dan tampaknya melakukan hal yang sama.

Sergey
sumber

Jawaban:

200

Perbedaannya adalah dengan callback.

The :delete_alldibuat langsung dalam aplikasi Anda dan menghapus dengan SQL:

DELETE * FROM users where compagny_id = XXXX

Dengan itu :destroy, ada instantiasi dari semua anak Anda. Jadi, jika Anda tidak dapat menghancurkannya atau jika masing-masing memiliki sendiri :dependent, panggilan baliknya dapat dipanggil.

shingara
sumber
83
Instansiasi dan panggilan hancurkan pada masing-masing objek anak-anak akan lambat jika Anda memiliki banyak anak (dan n ^ 2 jika Anda memiliki cucu, dan sebagainya). delete_all adalah jenis solusi "nuke it from orbit" di mana Anda tidak peduli / tidak memilikinya sebelum / sesudah menghancurkan callback pada model.
Ryan Bigg
131

Pada asosiasi model Rails, Anda dapat menentukan :dependentopsi, yang dapat mengambil salah satu dari tiga bentuk berikut:

  • :destroy/:destroy_allObjek terkait dihancurkan bersama objek ini dengan memanggil destroymetode mereka
  • :delete/:delete_allSemua objek yang terkait dihancurkan segera tanpa memanggil :destroymetode mereka
  • :nullifyKunci asing semua objek terkait diatur ke NULLtanpa memanggil savepanggilan baliknya
John Topley
sumber
2
Lihat api.rubyonrails.org/classes/ActiveRecord/Associations/… (cari "nullify") untuk rdocs yang resmi.
mrm
21
Karena Rails 3.0 juga dapat ditentukan :restrict. Jika diatur ke: batasi objek ini tidak dapat dihapus jika memiliki objek terkait.
RocketR
17
tidak ada :deleteatau :destroy_allpilihan oleh tampilannya? Opsi: dependen mengharapkan: menghancurkan,: delete_all,: nullify atau: membatasi (: delete)
Mike Campbell
2
@ MikeCampbell, :deletedan :destroy_allopsi tidak ada. Namun, ada metode kelas pada model yang dipanggil deletedan destroy_allmungkin itu menjadi alasan kebingungan.
berezovskyi
@MikeCampbell Anda kehilangan beberapa opsi lagi, Lihat: Opsi tergantung harus salah satu dari [: menghancurkan,: delete_all,: nullify,: membatasi_with_error,: membatasi_with_exception]
Pravin Mishra
30

Lihat menghancurkan menghapus elemen yang terkait di mana delete_all dapat menghapus beberapa data dari tabel diri sebagaiDELETE * FROM table where field = 'xyz'

: Opsi tergantung yang mungkin:

Mengontrol apa yang terjadi pada objek terkait ketika pemiliknya dihancurkan. Perhatikan bahwa ini diimplementasikan sebagai callback, dan Rails mengeksekusi callback secara berurutan. Oleh karena itu, panggilan balik serupa lainnya dapat memengaruhi: perilaku dependen, dan :dependentperilaku tersebut dapat memengaruhi panggilan balik lain.

:destroy menyebabkan semua benda terkait juga hancur.

:delete_all menyebabkan semua objek terkait dihapus langsung dari database (jadi panggilan balik tidak akan dieksekusi).

:nullifymenyebabkan kunci asing diatur ke NULL. Panggilan balik tidak dilakukan.

:restrict_with_exception menyebabkan pengecualian untuk dimunculkan jika ada catatan terkait.

:restrict_with_error menyebabkan kesalahan ditambahkan ke pemilik jika ada objek terkait.

Jika menggunakan dengan :throughopsi, asosiasi pada model bergabung haruslah menjadi milik_ untuk, dan catatan yang bisa dihapus adalah catatan bergabung, bukan catatan terkait.

Manish Shrivastava
sumber
3

Sebenarnya perbedaan utama adalah bahwa setiap panggilan balik tidak akan dipanggil ketika :delete_alldigunakan. Tetapi ketika digunakan :destroytumpukan callback ( :after_destroy,:after_commit ...) akan dipecat.

Akibatnya, jika Anda memiliki touch:deklarasi dalam model yang dihapus maka lebih baik menggunakan dependent: :delete_all'depend:: destroy'.

atlascoder
sumber