Szyny: zależne =>: zniszcz VS: zależne =>: usuń_wszystkie

192

W przewodnikach po szynach opisano to następująco:

Obiekty zostaną dodatkowo zniszczone, jeśli zostaną powiązane :dependent => :destroy, i usunięte, jeśli zostaną powiązane:dependent => :delete_all

Racja, spoko. Ale jaka jest różnica między zniszczeniem a usunięciem? Próbowałem obu i wydaje się, że robi to samo.

Siergiej
źródło

Odpowiedzi:

200

Różnica polega na wywołaniu zwrotnym.

Jest :delete_allon tworzony bezpośrednio w Twojej aplikacji i jest usuwany przez SQL:

DELETE * FROM users where compagny_id = XXXX

Dzięki :destroy, tworzona jest instancja wszystkich twoich dzieci. Jeśli więc nie możesz go zniszczyć lub każdy z nich ma swoje własne :dependent, można wywołać jego wywołania zwrotne.

shingara
źródło
83
Tworzenie instancji i wzywanie niszczenia na każdym z obiektów podrzędnych będzie powolne, jeśli masz dużo dzieci (i n ^ 2, jeśli masz wnuki i tak dalej). delete_all jest rodzajem rozwiązania „nuke it from orbit”, w którym nie obchodzi Cię / nie masz żadnych przed / po zniszczeniu wywołań zwrotnych w modelach.
Ryan Bigg
131

W powiązaniu modelu z Railsami możesz określić :dependentopcję, która może przyjąć jedną z następujących trzech form:

  • :destroy/:destroy_allPowiązane obiekty są niszczone obok tego obiektu przez wywołanie ich destroymetody
  • :delete/:delete_allWszystkie powiązane obiekty są niszczone natychmiast, bez wywoływania ich :destroymetody
  • :nullifyKlucze obce wszystkich powiązanych obiektów są ustawione NULLbez wywoływania ich savewywołań zwrotnych
John Topley
źródło
2
Zobacz api.rubyonrails.org/classes/ActiveRecord/Associations/... (wyszukaj „ nullify ”), aby znaleźć autorytatywne rdocs.
mrm
21
Od Rails 3.0 można również określić :restrict. Jeśli ustawione na: ograniczenie tego obiektu nie można usunąć, jeśli ma on jakiś powiązany obiekt.
RocketR
17
tam nie jest :deleteani :destroy_allopcji przez wygląda to? : Zależny opcja oczekuje albo: zniszczyć: delete_all: unieważnić lub: Filtrowanie (: Delete)
Mike Campbell
2
@MikeCampbell, :deletea :destroy_allopcje nie istnieją. Jednak istnieją sposoby na klasy modeli, które są wywoływane deletei destroy_alltak może to być powodem nieporozumień.
berezovskyi
@MikeCampbell Brakuje kilku dodatkowych opcji, patrz: opcja: zależna musi być jedną z [: destroy,: delete_all,: nullify,: ograniczenia_z_prawą,: ograniczenia_z wyjątkiem]
Pravin Mishra
30

Zobacz zniszcz usuwa powiązane z nim elementy, w których delete_all może usunąć wiele danych z własnej tabeli jakoDELETE * FROM table where field = 'xyz'

: Zależne możliwe opcje:

Kontroluje, co dzieje się z powiązanymi obiektami, gdy ich właściciel zostanie zniszczony. Zauważ, że są one zaimplementowane jako callbacki, a Railsy wykonują je w kolejności. Dlatego inne podobne wywołania zwrotne mogą wpływać na: zachowanie zależne, a :dependentzachowanie może wpływać na inne wywołania zwrotne.

:destroy powoduje także zniszczenie wszystkich powiązanych obiektów.

:delete_all powoduje usunięcie wszystkich powiązanych obiektów bezpośrednio z bazy danych (dlatego wywołania zwrotne nie zostaną wykonane).

:nullifypowoduje, że klucze obce są ustawione na NULL. Połączenia zwrotne nie są wykonywane.

:restrict_with_exception powoduje zgłoszenie wyjątku, jeśli istnieją powiązane rekordy.

:restrict_with_error powoduje dodanie błędu do właściciela, jeśli istnieją jakieś powiązane obiekty.

W przypadku korzystania z tej :throughopcji powiązanie w modelu łączenia musi być należące do, a usuwane rekordy to rekordy łączenia, a nie powiązane rekordy.

Manish Shrivastava
źródło
3

W rzeczywistości główna różnica polega na tym, że żadne wywołania zwrotne nie będą wywoływane, gdy zostaną :delete_allużyte. Ale gdy zostanie użyty, :destroystos wywołań zwrotnych ( :after_destroy, :after_commit...) zostanie uruchomiony .

W związku z tym, jeśli touch:usuwane są deklaracje w modelach, lepiej użyć dependent: :delete_allraczej „zależnego:: zniszczyć”.

atlascoder
źródło