2010-05-09 7 views
171

W Rails Guides to opisane tak:szyn: dependent =>: zniszczyć VS: dependent =>: delete_all

Obiekty będą dodatkowo niszczone, jeśli są powiązane z :dependent => :destroy i usunięte jeśli oni ponownie związane z :dependent => :delete_all

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

Odpowiedz

173

Różnica dotyczy wywołania zwrotnego.

The :delete_all jest wykonany bezpośrednio w aplikacji i usuwa przez SQL:

DELETE * FROM users where compagny_id = XXXX 

Z :destroy istnieje instancji wszystkim dzieci. Tak więc, jeśli nie możesz go zniszczyć lub jeśli każdy ma swój własny :dependent, jego wywołania zwrotne mogą być wywoływane.

+72

Tworzenie i wywoływanie zniszczeń 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 typu "nuke it from orbit", w którym nie interesują cię/nie mają żadnych callbacków before/after destroy na modelach. –

+4

Zobacz nowszą odpowiedź poniżej! – berezovskyi

+5

"Nuke it from orbit" sprawił, że mój dzień – Andreas

124

On Rails' stowarzyszenia modelu można określić opcję :dependent, który może przyjąć jedną z trzech form:

  • :destroy/:destroy_all Associated obiekty są niszczone obok tego obiektu poprzez wywołanie ich metoda destroy
  • :delete/:delete_all Wszystkie powiązane obiekty są niszczone natychmiast bez wywoływania ich :destroy
  • :nullify Wszystkie obce klucze obiektów są ustawione na NULL bez wywoływania ich save callbacks
+2

Zobacz http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html (szukaj "unieważnić") dla autorytatywnych rdocs. – mrm

+20

Od Rails 3.0 jest również możliwe określenie ': restrict'. _Jeśli ustawiono na: ograniczenie, ten obiekt nie może zostać usunięty, jeśli ma jakikolwiek powiązany obiekt._ – RocketR

+16

nie ma opcji ': delete' lub': destroy_all' przez jego wygląd? _ Opcja: dependent wymaga: destroy,: delete_all,: nullify lub: restrict (: delete) _ –

26

See zniszczyć usuwa związane z nim elementy gdzie delete_all możesz usuwać wiele danych z tabeli siebie jak DELETE * FROM table where field = 'xyz'

: w zależności od opcji:

Kontrole co dzieje się z powiązane obiekty, gdy ich właściciel zostanie zniszczony. Zauważ, że są one implementowane jako wywołania zwrotne, a Railsy wykonują wywołania zwrotne w kolejności. Dlatego inne podobne wywołania zwrotne mogą wpływać na: zależne zachowanie, a zachowanie :dependent może wpływać na inne wywołania zwrotne.

:destroy powoduje również zniszczenie wszystkich powiązanych obiektów.

:delete_all powoduje, że wszystkie powiązane obiekty są usuwane bezpośrednio z bazy danych (więc wywołania zwrotne nie zostaną wykonane).

:nullify powoduje, że klucze obce mają wartość NULL. Połączenia zwrotne nie są wykonywane.

:restrict_with_exception powoduje, że wyjątek zostanie podniesiony, jeśli istnieją powiązane rekordy.

:restrict_with_error powoduje, że właściciel otrzymuje błąd, jeśli istnieją powiązane z nim obiekty.

W przypadku używania z opcją :through powiązanie w modelu łączenia musi być wartością belongs_to, a rekordy, które zostaną usunięte, są rekordami łączenia, a nie powiązanymi rekordami.

1

W rzeczywistości główna różnica polega na tym, że wszelkie wywołania zwrotne nie będą wywoływane, gdy użyto :delete_all. Ale po użyciu :destroy stos wywołań zwrotnych (:after_destroy, :after_commit ...) zostanie uruchomiony.

W związku z tym, jeśli posiadasz touch: deklaracji w modelach, które zostały usunięte, lepiej jest użyć dependent: :delete_all raczej "dependent:: destroy".