Schienen: abhängig =>: zerstören VS: abhängig =>: delete_all

192

In Schienenführungen wird es folgendermaßen beschrieben:

Objekte werden zusätzlich zerstört, wenn sie zugeordnet sind :dependent => :destroy, und gelöscht, wenn sie zugeordnet sind:dependent => :delete_all

Richtig, cool. Aber was ist der Unterschied zwischen Zerstörung und Löschung? Ich habe beide ausprobiert und es scheint dasselbe zu tun.

Sergey
quelle

Antworten:

200

Der Unterschied liegt im Rückruf.

Das :delete_allwird direkt in Ihrer Anwendung erstellt und von SQL gelöscht:

DELETE * FROM users where compagny_id = XXXX

Mit dem :destroygibt es eine Instanziierung aller Ihrer Kinder. Wenn Sie es also nicht zerstören können oder wenn jedes sein eigenes hat :dependent, können seine Rückrufe aufgerufen werden.

Shingara
quelle
83
Die Instanziierung und der Aufruf der Zerstörung für jedes der untergeordneten Objekte ist langsam, wenn Sie viele Kinder haben (und n ^ 2, wenn Sie Enkelkinder haben, und so weiter). delete_all ist die Art von "Nuke it from Orbit" -Lösung, bei der Sie sich nicht darum kümmern / keine Vorher / Nachher-Zerstörungs-Rückrufe auf den Modellen haben.
Ryan Bigg
131

In einer Rails-Modellzuordnung können Sie die :dependentOption angeben , die eine der folgenden drei Formen annehmen kann:

  • :destroy/:destroy_allDie zugehörigen Objekte werden neben diesem Objekt durch Aufrufen ihrer destroyMethode zerstört
  • :delete/:delete_allAlle zugehörigen Objekte werden sofort zerstört, ohne ihre :destroyMethode aufzurufen
  • :nullifyDie Fremdschlüssel aller zugeordneten Objekte werden auf gesetzt, NULLohne ihre saveRückrufe aufzurufen
John Topley
quelle
2
Siehe api.rubyonrails.org/classes/ActiveRecord/Associations/… (Suche nach "nullify") für die maßgeblichen rdocs.
Herr
21
Seit Rails 3.0 ist es auch möglich anzugeben :restrict. Bei der Einstellung: einschränken kann dieses Objekt nicht gelöscht werden, wenn ihm ein Objekt zugeordnet ist.
RocketR
17
Es gibt keine :deleteoder :destroy_allOptionen, wie es aussieht? Die: abhängige Option erwartet entweder: destroy ,: delete_all ,: nullify oder: einschränken (: löschen)
Mike Campbell
2
@ MikeCampbell :deleteund :destroy_allOptionen existieren nicht. Allerdings gibt es Klassenmethoden auf Modelle , die aufgerufen werden deleteund destroy_allso könnte es der Grund für die Verwirrung.
berezovskyi
@ MikeCampbell Sie vermissen einige weitere Optionen, siehe Die: abhängige Option muss eine der folgenden sein: [: destroy ,: delete_all ,: nullify ,: einschränken_mit_Fehler ,: einschränken_mit_Ausnahme]
Pravin Mishra
30

Sehen zerstören Löschungen seiner zugehörigen Elemente , wo DELETE_ALL mehrere Daten aus Selbst Tabelle löschen können alsDELETE * FROM table where field = 'xyz'

: Abhängig mögliche Optionen:

Steuert, was mit den zugeordneten Objekten passiert, wenn deren Besitzer zerstört wird. Beachten Sie, dass diese als Rückrufe implementiert sind und Rails Rückrufe der Reihe nach ausführt. Daher können andere ähnliche Rückrufe das: abhängige Verhalten beeinflussen, und das :dependentVerhalten kann andere Rückrufe beeinflussen.

:destroy bewirkt, dass alle zugehörigen Objekte ebenfalls zerstört werden.

:delete_all bewirkt, dass alle zugeordneten Objekte direkt aus der Datenbank gelöscht werden (Rückrufe werden also nicht ausgeführt).

:nullifybewirkt, dass die Fremdschlüssel auf NULL gesetzt werden. Rückrufe werden nicht ausgeführt.

:restrict_with_exception bewirkt, dass eine Ausnahme ausgelöst wird, wenn Datensätze zugeordnet sind.

:restrict_with_error bewirkt, dass dem Eigentümer ein Fehler hinzugefügt wird, wenn Objekte zugeordnet sind.

Wenn Sie diese :throughOption verwenden, muss die Zuordnung im Join-Modell zu gehören gehören, und die Datensätze, die gelöscht werden, sind die Join-Datensätze und nicht die zugeordneten Datensätze.

Manish Shrivastava
quelle
3

Tatsächlich besteht der Hauptunterschied darin, dass Rückrufe nicht aufgerufen werden, wenn sie :delete_allverwendet wurden. Bei Verwendung wird jedoch :destroyder Rückrufstapel ( :after_destroy, :after_commit...) ausgelöst.

Wenn Sie touch:Deklarationen in Modellen haben, die gelöscht werden, ist es daher besser, dependent: :delete_alleher "abhängig :: zerstören" zu verwenden.

Atlascoder
quelle