Antworten:
Grundsätzlich werden destroy
keine Rückrufe auf dem Modell ausgeführt, während delete
dies nicht der Fall ist.
Aus der Rails-API :
ActiveRecord::Persistence.delete
Löscht den Datensatz in der Datenbank und friert diese Instanz ein, um anzuzeigen, dass keine Änderungen vorgenommen werden sollten (da sie nicht beibehalten werden können). Gibt die eingefrorene Instanz zurück.
Die Zeile wird einfach mit einer SQL DELETE-Anweisung auf dem Primärschlüssel des Datensatzes entfernt, und es werden keine Rückrufe ausgeführt.
Verwenden Sie #destroy, um die Rückrufe vor_destroy und after_destroy des Objekts oder andere: abhängige Zuordnungsoptionen zu erzwingen.
ActiveRecord::Persistence.destroy
Löscht den Datensatz in der Datenbank und friert diese Instanz ein, um anzuzeigen, dass keine Änderungen vorgenommen werden sollten (da sie nicht beibehalten werden können).
Es gibt eine Reihe von Rückrufen, die mit Zerstörung verbunden sind. Wenn der Rückruf before_destroy false zurückgibt, wird die Aktion abgebrochen und destroy gibt false zurück. Weitere Informationen finden Sie unter ActiveRecord :: Callbacks.
model#before_destroy
kann verwendet werden, um den letzten destroy()
Anruf unter bestimmten Bedingungen anzuhalten.
delete
löscht nur den aktuellen Objektdatensatz aus der Datenbank, nicht jedoch die zugehörigen untergeordneten Datensätze aus der Datenbank.
destroy
löscht den aktuellen Objektdatensatz aus der Datenbank und den zugehörigen untergeordneten Datensatz aus der Datenbank.
Ihre Verwendung ist wirklich wichtig:
Wenn mehrere übergeordnete Objekte gemeinsame untergeordnete Objekte verwenden, werden durch Aufrufen eines destroy
bestimmten übergeordneten Objekts untergeordnete Objekte gelöscht, die von mehreren übergeordneten Objekten gemeinsam genutzt werden .
destroy
sind Nachkommen , keine Kinder : Gemäß der Dokumentation erstellt destroy "ein neues Objekt aus den Attributen und ruft dann destroy darauf auf". rubydoc.info/docs/rails/4.1.7/ActiveRecord%2FRelation:destroy
Wenn Sie ein Objekt aufrufen destroy
oder destroy_all
ein ActiveRecord
Objekt aufrufen , wird der ActiveRecord
Zerstörungsprozess eingeleitet, die zu löschende Klasse analysiert, festgelegt, was für Abhängigkeiten getan werden soll, Überprüfungen durchlaufen usw.
Wenn Sie ein Objekt aufrufen delete
oder delete_all
bearbeiten, wird ActiveRecord
lediglich versucht, die DELETE FROM tablename WHERE conditions
Abfrage für die Datenbank auszuführen , ohne dass ActiveRecord
Aufgaben auf anderer Ebene ausgeführt werden.
Ja, es gibt einen großen Unterschied zwischen den beiden Methoden. Verwenden Sie delete_all, wenn Datensätze schnell gelöscht werden sollen, ohne dass Modellrückrufe aufgerufen werden
Wenn Sie sich für Rückrufe Ihrer Modelle interessieren, verwenden Sie destroy_all
Aus den offiziellen Dokumenten
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class
destroy_all (Bedingungen = Null) public
Zerstört die übereinstimmenden Bedingungen der Datensätze, indem jeder Datensatz instanziiert und seine Zerstörungsmethode aufgerufen wird. Die Rückrufe jedes Objekts werden ausgeführt (einschließlich: abhängiger Zuordnungsoptionen und before_destroy / after_destroy Observer-Methoden). Gibt die Sammlung von Objekten zurück, die zerstört wurden. Jedes wird eingefroren, um zu berücksichtigen, dass keine Änderungen vorgenommen werden sollten (da sie nicht beibehalten werden können).
Hinweis: Das Instanziieren, Ausführen von Rückrufen und Löschen jedes Datensatzes kann zeitaufwändig sein, wenn Sie mehrere Datensätze gleichzeitig entfernen. Es generiert mindestens eine SQL DELETE-Abfrage pro Datensatz (oder möglicherweise mehr, um Ihre Rückrufe zu erzwingen). Wenn Sie viele Zeilen schnell löschen möchten, ohne Rücksicht auf ihre Zuordnungen oder Rückrufe, verwenden Sie stattdessen delete_all.
Grundsätzlich sendet "Löschen" eine Abfrage direkt an die Datenbank, um den Datensatz zu löschen. In diesem Fall weiß Rails nicht, welche Attribute in dem zu löschenden Datensatz enthalten sind oder ob Rückrufe (z. B. before_destroy
) vorliegen .
Die "destroy" -Methode nimmt die übergebene ID, ruft das Modell mit der "find" -Methode aus der Datenbank ab und ruft dann destroy auf. Dies bedeutet, dass die Rückrufe ausgelöst werden.
Sie möchten "Löschen" verwenden, wenn Sie nicht möchten, dass die Rückrufe ausgelöst werden, oder wenn Sie eine bessere Leistung wünschen. Andernfalls (und meistens) möchten Sie "destroy" verwenden.
Viele Antworten schon; wollte mit etwas mehr weitermachen.
docs :
Bei has_many rufen destroy und destroy_all immer die destroy-Methode der zu entfernenden Datensätze auf, damit Rückrufe ausgeführt werden. Löschen und delete_all führen das Löschen jedoch entweder gemäß der durch die Option: abhängige Strategie angegebenen Strategie durch, oder wenn keine: abhängige Option angegeben ist, folgt es der Standardstrategie. Die Standardstrategie besteht darin, nichts zu tun (die Fremdschlüssel mit den übergeordneten IDs belassen), außer has_many: through, wobei die Standardstrategie delete_all lautet (Löschen der Join-Datensätze, ohne deren Rückrufe auszuführen).
Das delete
Verb funktioniert anders für ActiveRecord::Association.has_many
und ActiveRecord::Base
. Für letzteres führt delete SQL DELETE
alle Überprüfungen / Rückrufe aus und umgeht sie. Ersteres wird basierend auf der :dependent
an den Verein übergebenen Option ausgeführt . Beim Testen stellte ich jedoch den folgenden Nebeneffekt fest, bei dem Rückrufe nur ausgeführt wurden delete
und nichtdelete_all
dependent: :destroy
Beispiel:
class Parent < ApplicationRecord
has_many :children,
before_remove: -> (_) { puts "before_remove callback" },
dependent: :destroy
end
class Child < ApplicationRecord
belongs_to :parent
before_destroy -> { puts "before_destroy callback" }
end
> child.delete # Ran without callbacks
Child Destroy (99.6ms) DELETE FROM "children" WHERE "children"."id" = $1 [["id", 21]]
> parent.children.delete(other_child) # Ran with callbacks
before_remove callback
before_destroy callback
Child Destroy (0.4ms) DELETE FROM "children" WHERE "children"."id" = $1 [["id", 22]]
> parent.children.delete_all # Ran without callbacks
Child Destroy (1.0ms) DELETE FROM "children" WHERE "children"."parent_id" = $1 [["parent_id", 1]]