2012-06-07 13 views
7

Conoces el ejercicio: algunos datos no válidos aparecen en la base de datos de producción y debes deshacerte de ellos. Es el fuego de su consola de Rails en el servidor de producción y el tipo de la consulta:Cómo obtener una vista previa de una consulta delete_all o destroy_all en Rails

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

revisar los datos devueltos y es lo que hay que eliminar. Luego escriba:

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

Y su corazón se detiene por un segundo. Solo quieres ver la consulta antes de que se ejecute.

¿Hay alguna manera de hacerlo en Rails? Estoy buscando un método similar al

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

pero el que va a devolver el BORRAR consulta.

Respuesta

1

Justo en la parte superior de mi cabeza, podría ejecutar la consola en modo de espacio aislado y ejecutar la consulta de eliminación para ver el sql. Los cambios simplemente se revertirían en la salida.

+0

supongo que esto no es así en realidad sin embargo, responda su pregunta si realmente está buscando una comunicación similar a la de "to_sql" y. – cdesrosiers

+0

¡Me olvidé por completo del modo de espacio aislado! No es exactamente lo que estaba buscando, pero hace exactamente lo que necesitaba. Sobre todo teniendo en cuenta que lo que estaba buscando es imposible: D –

2

El problema es que destroy_all no ejecuta una sola consulta SQL. Se itera a través de un hash de objetos, los crea instancias, ejecuta sus devoluciones de llamada y luego llama al método de destrucción de ese objeto. Rails no ha construido una manera de producir una variedad de estas consultas.

Cdesroisiers tiene razón en que puede probar la consulta en el modo de espacio aislado, pero el problema real es que está cuestionando su decisión de ejecutar delete_all, aunque haya verificado los datos que se están tratando.

Considere usar una gema de control de versiones de ActiveRecord como PaperTrail si no está dispuesto a confiar en que ActiveRecord elimine objetos correctamente.

+0

¿Cuál es la justificación detrás de no implementar 'delete_all' como una operación por lotes? Pensé que era mucho más barato hacerlo en un lote en lugar de hacer un serio viaje de ida y vuelta a la base de datos. – Bedasso

+2

delete_all es una operación por lotes. destroy_all los hace uno por uno. delete_all existe porque es más rápido, destroy_all puede ser útil porque se activará antes/después de destruir devoluciones de llamada. –

+0

PaperTrail es ideal para usar en la aplicación, pero solo necesitaba deshacerme de algunos datos redundantes. ¡Gracias de cualquier manera! –

1

el método destroy_all es lo mismo que hacer:

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

Así que el SQL se convierte en

DELETE FROM foo WHERE foo.id = your_objects_id_attribute 



a partir de documentos:

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

Creo que el SQL generado consistirá en múltiples consultas ELIMINAR, una por cada objeto encontrado. – mrt

Cuestiones relacionadas