it-swarm.com.de

delete_all vs destroy_all?

Ich suche nach dem besten Ansatz, um Datensätze aus einer Tabelle zu löschen. Ich habe zum Beispiel einen Benutzer, dessen Benutzer-ID sich über viele Tabellen erstreckt. Ich möchte diesen Benutzer und jeden Datensatz löschen, dessen ID in allen Tabellen enthalten ist.

u = User.find_by_name('JohnBoy')
u.usage_indexes.destroy_all
u.sources.destroy_all
u.user_stats.destroy_all
u.delete

Das funktioniert und entfernt alle Referenzen des Benutzers aus allen Tabellen, aber ich habe gehört, dass destroy_all Sehr prozesslastig war, also habe ich es mit delete_all Versucht. Es wird nur der Benutzer aus seiner eigenen Benutzertabelle entfernt und id aus allen anderen Tabellen wird auf null gesetzt, die Datensätze bleiben jedoch intakt. Kann jemand mitteilen, wie eine solche Aufgabe korrekt ausgeführt wird?

Ich sehe, dass destroy_all Die Funktion destroy für alle zugeordneten Objekte aufruft, möchte aber nur den korrekten Ansatz bestätigen.

179
glogic

Du hast recht. Wenn Sie den Benutzer und alle zugehörigen Objekte löschen möchten -> destroy_all Wenn Sie jedoch nur den Benutzer löschen möchten, ohne alle zugehörigen Objekte zu unterdrücken -> delete_all

Laut diesem Beitrag: Rails: dependent =>: destroy VS: dependent =>: delete_all

  • destroy/destroy_all: Die zugehörigen Objekte werden neben diesem Objekt durch Aufrufen ihrer destroy-Methode zerstört
  • delete/delete_all: Alle verknüpften Objekte werden sofort gelöscht, ohne die Methode: destroy aufzurufen
222
Sandro Munda

delete_all ist eine einzelne SQL-Anweisung DELETE und nichts weiter. destroy_all ruft destroy () für alle übereinstimmenden Ergebnisse von: conditions (falls vorhanden) auf, bei denen es sich mindestens um NUM_OF_RESULTS-SQL-Anweisungen handeln könnte.

Wenn Sie etwas drastisches wie destroy_all () für große Datenmengen tun müssen, würde ich es wahrscheinlich nicht über die App tun und es sorgfältig manuell handhaben. Wenn der Datensatz klein genug ist, würden Sie nicht so viel verletzen.

21
Ryan Her

Um zu vermeiden, dass destroy_all instanziiert alle Datensätze und löscht sie einzeln. Sie können sie direkt aus der Modellklasse verwenden.

Also statt:

u = User.find_by_name('JohnBoy')
u.usage_indexes.destroy_all

Du kannst tun :

u = User.find_by_name('JohnBoy')
UsageIndex.destroy_all "user_id = #{u.id}"

Das Ergebnis ist eine Abfrage, mit der alle zugehörigen Datensätze gelöscht werden

16
simon-olivier

Ich habe ein kleines Juwel erstellt, das unter bestimmten Umständen das manuelle Löschen zugeordneter Datensätze erleichtert.

Dieses Juwel fügt eine neue Option für ActiveRecord-Zuordnungen hinzu:

abhängig:: delete_recursively

Wenn Sie einen Datensatz löschen, werden alle Datensätze, die mit dieser Option verknüpft sind, rekursiv gelöscht (d. H. Modellübergreifend), ohne einen von ihnen zu instanziieren.

Beachten Sie, dass diese neue Option genau wie dependant:: delete oder dependant:: delete_all nicht die around/before/after_destroy-Rückrufe der abhängigen Datensätze auslöst.

Es ist jedoch möglich, dass abhängige:: Verknüpfungen an einer beliebigen Stelle innerhalb einer Kette von Modellen zerstört werden, die ansonsten abhängigen:: delete_recursively zugeordnet sind. Die Option: destroy funktioniert normalerweise überall auf der Leitung und instanziiert und zerstört alle relevanten Datensätze und löst damit auch deren Rückrufe aus.

1
Janosch