Risposte:
Fondamentalmente destroy
esegue tutti i callback sul modello mentre delete
non lo fa.
Dalla API Rails :
ActiveRecord::Persistence.delete
Elimina il record nel database e blocca questa istanza per riflettere che non è necessario apportare modifiche (poiché non possono essere mantenute). Restituisce l'istanza congelata.
La riga viene semplicemente rimossa con un'istruzione DELETE SQL sulla chiave primaria del record e non vengono eseguiti callback.
Per forzare l'oggetto before_destroy e after_destroy callbacks o qualunque: opzione di associazione dipendente, usa #destroy.
ActiveRecord::Persistence.destroy
Elimina il record nel database e blocca questa istanza per riflettere che non è necessario apportare modifiche (poiché non possono essere mantenute).
C'è una serie di callback associati a distruggere. Se before_destroy callback restituisce false l'azione viene annullata e distrugge restituisce false. Vedi ActiveRecord :: Callbacks per ulteriori dettagli.
model#before_destroy
che può essere utilizzato per interrompere la destroy()
chiamata finale in determinate condizioni.
delete
eliminerà solo i record dell'oggetto corrente da db ma non i record figlio associati da db.
destroy
eliminerà il record dell'oggetto corrente da db e anche il record figlio associato da db.
Il loro uso conta davvero:
Se i tuoi oggetti padre multipli condividono oggetti figlio comuni, la chiamata destroy
a un oggetto padre specifico eliminerà gli oggetti figlio che sono condivisi tra altri genitori multipli.
destroy
è discendenti , non i bambini : secondo la documentazione, distruggono "crea un nuovo oggetto dagli attributi, e poi chiamate distruggono su di esso." rubydoc.info/docs/rails/4.1.7/ActiveRecord%2FRelation:destroy
Quando invochi destroy
o destroy_all
su un ActiveRecord
oggetto, ActiveRecord
viene avviato il processo di "distruzione", analizza la classe che stai eliminando, determina cosa dovrebbe fare per le dipendenze, passa attraverso le convalide, ecc.
Quando invochi delete
o delete_all
su un oggetto, ActiveRecord
prova semplicemente a eseguire la DELETE FROM tablename WHERE conditions
query sul db, senza eseguire altre ActiveRecord
attività di livello.
Sì, c'è una grande differenza tra i due metodi Utilizzare delete_all se si desidera che i record vengano eliminati rapidamente senza richiamare i callback del modello
Se ti interessano i callback dei tuoi modelli, usa destroy_all
Dai documenti ufficiali
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class
destroy_all (condizioni = zero) pubblico
Distrugge le condizioni corrispondenti ai record creando un'istanza di ogni record e chiamando il suo metodo di distruzione. I callback di ogni oggetto vengono eseguiti (inclusi: opzioni di associazione dipendenti e metodi before_destroy / after_destroy Observer). Restituisce la raccolta di oggetti che sono stati distrutti; ognuno verrà congelato, per riflettere che non è necessario apportare modifiche (poiché non possono essere mantenute).
Nota: l'istanza, l'esecuzione della richiamata e l'eliminazione di ciascun record possono richiedere molto tempo quando si rimuovono più record contemporaneamente. Genera almeno una query DELETE SQL per record (o forse più, per imporre i callback). Se si desidera eliminare rapidamente molte righe, senza preoccuparsi delle loro associazioni o callback, utilizzare invece delete_all.
Fondamentalmente "elimina" invia una query direttamente al database per eliminare il record. In quel caso Rails non sa quali sono gli attributi nel record che sta eliminando né se ci sono callback (come before_destroy
).
Il metodo "destroy" prende l'id passato, recupera il modello dal database usando il metodo "find", quindi chiama distruggere su quello. Ciò significa che i callback sono attivati.
Si desidera utilizzare "elimina" se non si desidera attivare i callback o si desiderano prestazioni migliori. Altrimenti (e la maggior parte delle volte) vorrai usare "destro".
Molte risposte già; volevo continuare con un po 'di più.
Per has_many, destroy e destroy_all chiamerà sempre il metodo di distruzione dei record da rimuovere in modo da eseguire i callback. Tuttavia, delete e delete_all eseguiranno la cancellazione in base alla strategia specificata dall'opzione: dipendente, oppure se viene fornita l'opzione no: dipendente, seguirà la strategia predefinita. La strategia predefinita è di non fare nulla (lasciare le chiavi esterne con gli ID parent impostati), tranne has_many: through, dove la strategia predefinita è delete_all (elimina i record di join, senza eseguire i loro callback).
Il delete
verbale funziona diversamente per ActiveRecord::Association.has_many
e ActiveRecord::Base
. Per quest'ultimo, delete eseguirà SQL DELETE
e bypasserà tutte le validazioni / callback. Il primo verrà eseguito in base :dependent
all'opzione passata all'associazione. Tuttavia, durante i test, ho riscontrato il seguente effetto collaterale in cui i callback venivano eseguiti solo delete
e nondelete_all
dependent: :destroy
Esempio:
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]]