2011-05-30 9 views
7

Actualmente estoy empezando a aprender Ruby y el framework Ruby on Rails. He encontrado que en la tabla records, no puedo encontrar un registro con un id de 5 y eliminarlo mediante el siguiente código:¿Por qué no puedo usar Record.all.destroy en Rails?

Record.find(5).destroy

Esto hace que los métodos de la cadena me sensoriales para encontrar el registro y destruyelo. Sin embargo, si quiero destruir todos los registros de la tabla, el comando lógico sería lo siguiente, según el selector all selecciona todos los registros de la tabla:

Record.all.destroy

Y esto devuelve un NoMethodError! Soy consciente de que puedo usar Record.destroy_all o Record.delete_all para realizar esta tarea, sin embargo, me gustaría saber por qué no puedo usar la opción más lógica en lugar de tener que buscar cosas como delete_all. Soy nuevo en este marco, por lo que es muy posible que me esté perdiendo algo fundamental aquí.

Gracias por cualquier respuesta con anticipación.

+0

de hecho una buena pregunta, porque intenté lo mismo primero ... Podría usar 'Record.all.each {| r | r.destroy} 'por supuesto, pero eso no es tan lógico como el' Record.all.destroy' –

Respuesta

14

Fue una decisión de diseño. DataMapper tomó your approach. Ser obligado a escribir destroy_all explícitamente puede ser tedioso, pero también le impedirá hacer algo que realmente no desea (es decir, eliminar todo en una tabla, como x = User; ...; x.destroy).

+0

Gracias- esta fue la respuesta que estoy buscando. Supongo que podría ser una buena protección contra la eliminación masiva involuntaria de registros. – element119

3

Acepto que sería lógico para poder hacer esto. Técnicamente hablando, Record.all devuelve una colección (o proxy a una colección) que no implementa el método destroy.

1

Cuando se tiene

Record.find(5) 

este devuelve un registro de objeto/instancia que representa los datos de una fila en la tabla. Luego llama al método #destroy en ese objeto que está definido por su modelo de registro.

Cuando se tiene

Record.all 

Esto devuelve un objeto Array. Para que puedas llamar a #destroy en la matriz, tendrás que parchear el parche de la clase Array central de Ruby para tener un método #destroy.

+0

sí y no ... Debido a la naturaleza dinámica de ruby, los rieles en sí * podrían * insertar una acción de destrucción en matrices de registros, sin monos parcheando todos los objetos de matriz ... pero es una decisión de diseño no hacerlo, creo que creo. – DGM

1

La manera más simple de evitar Record.destroy_all sería Record.all.each {|r| r.destroy}. Esto puede satisfacer un poco las preferencias de diseño de la API, pero debe ser mucho más lento que la primera opción.

0

En realidad se puede (de alguna manera). Como .all devuelve una matriz, y no una relación de registro activa, ¿qué es exactamente lo que va a eliminar? No diría que Record.all.destroy es lógico en absoluto. ¿Estás eliminando el objeto de la matriz?

Una cosa que podría hacer es mapear el conjunto resultante, y dado que map acepta un proceso (&), puede ejecutar ese proceso para cada objeto en su conjunto.

Record.all.map(&:destroy) 

Nota, esto va a desencadenar devoluciones de llamada en todos sus objetos, que podrían ser más lenta de lo previsto. Si desea evitar la activación de devoluciones de llamada, puede asignar el método destructivo apropiado en lugar de destruir.(Pista:: eliminar)

Alternativamente, usted podría hacer:

Record.destroy_all or Record.delete_all 

como ha afirmado en su pregunta.

Cuestiones relacionadas