2012-06-07 2 views
7

Conosci il drill: alcuni dati non validi si aprono nel database di produzione e devi liberartene. Si accende il console Rails sul server di produzione e digitare la query:Come visualizzare in anteprima una query delete_all o destroy_all in Rails

Foo.where(bar: 'baz').all 

si esaminano i dati restituiti ed è ciò che è necessario rimuovere. Quindi digiti:

Foo.where(bar: 'baz').destroy_all 

E il tuo cuore si ferma per un secondo. Vuoi solo vedere la query prima che venga eseguita.

C'è un modo per farlo in Rails? Sto cercando un metodo simile a

Foo.where(bar: 'baz').to_sql 

ma quello che restituirà il DELETE query.

risposta

1

Appena fuori dalla mia testa, è possibile eseguire la console in modalità sandbox ed eseguire la query di eliminazione per visualizzare lo sql. Le modifiche verrebbero semplicemente ripristinate all'uscita.

+0

Suppongo che questo in realtà non rispondi alla tua domanda, se stai davvero cercando una comunicazione "to_sql" e. – cdesrosiers

+0

Mi sono completamente dimenticato della modalità sandbox! Non è esattamente quello che stavo cercando, ma fa esattamente ciò di cui avevo bisogno. Soprattutto considerando che ciò che stavo cercando è impossibile: D –

2

Il problema è che destroy_all non esegue una singola query SQL. Esso scorre attraverso un hash di oggetti, li istanzia, esegue i loro callback e quindi chiama il metodo destroy di quell'oggetto. Rails non ha costruito un modo per produrre una serie di queste query.

Cdesroisiers ha ragione: è possibile testare la query in modalità sandbox, ma il vero problema è che si sta prendendo in considerazione la decisione di eseguire delete_all, anche se è stato verificato qualsiasi dato venga preso di mira.

Considerare l'utilizzo di una gemma di versione di ActiveRecord come PaperTrail se non si desidera affidare a ActiveRecord la corretta eliminazione di oggetti.

+0

Qual è la giustificazione alla base della mancata implementazione di 'delete_all' come operazione batch, ho pensato che è molto più economico farlo in un batch piuttosto che fare un giro di tutto il database. – Bedasso

+2

delete_all è un'operazione batch. destroy_all li fa uno per uno. delete_all esiste perché è più veloce, destroy_all può essere utile perché sparerà prima/dopo distrugge i callback. –

+0

PaperTrail è perfetto per l'uso nell'app, ma ho solo bisogno di eliminare alcuni dati ridondanti. Grazie comunque! –

1

il metodo destroy_all è lo stesso fare:

Foo.where(bar: 'baz').each { |object| object.destroy } 

Così lo SQL diventa

DELETE FROM foo WHERE foo.id = your_objects_id_attribute 



Da docs:

def destroy_all(conditions = nil) 
    find(:all, :conditions => conditions).each { |object| object.destroy } 
    end 
+1

Credo che l'SQL generato consisterà in più query DELETE, una per ogni oggetto trovato. – mrt

Problemi correlati