Rieles: dependiente =>: destruir VS: dependiente =>: eliminar_todos

192

En las guías de rieles se describe así:

Además, los objetos se destruirán si están asociados :dependent => :destroyy se eliminarán si están asociados a:dependent => :delete_all

Bien, genial. Pero, ¿cuál es la diferencia entre ser destruido y ser eliminado? Intenté ambos y parece hacer lo mismo.

Sergey
fuente

Respuestas:

200

La diferencia está con la devolución de llamada.

El :delete_allse realiza directamente en su aplicación y se elimina por SQL:

DELETE * FROM users where compagny_id = XXXX

Con el :destroy, hay una instanciación de todos sus hijos. Entonces, si no puede destruirlo o si cada uno tiene el suyo :dependent, se pueden llamar sus devoluciones de llamada.

shingara
fuente
83
La creación de instancias y el llamado a destruir en cada uno de los objetos secundarios serán lentos si tienes muchos hijos (y n ^ 2 si tienes nietos, y así sucesivamente). delete_all es el tipo de solución "nuke it from orbit" en la que no te importa / no tienes ninguna antes / después de destruir callbacks en los modelos.
Ryan Bigg
131

En una asociación de modelo de Rails, puede especificar la :dependentopción, que puede tomar una de las siguientes tres formas:

  • :destroy/:destroy_all Los objetos asociados se destruyen junto con este objeto llamando a su destroy método
  • :delete/:delete_all Todos los objetos asociados se destruyen inmediatamente sin llamar a su :destroy método.
  • :nullifyLas claves externas de todos los objetos asociados se configuran NULLsin llamar a sus savedevoluciones de llamada
John Topley
fuente
2
Consulte api.rubyonrails.org/classes/ActiveRecord/Associations/… (busque "nullify") para ver los rdocs autorizados.
mrm
21
Desde Rails 3.0 también es posible especificar :restrict. Si se establece en: restringir este objeto no se puede eliminar si tiene algún objeto asociado.
RocketR
17
no hay opciones :deleteo :destroy_allpor lo que parece? La opción: dependiente espera: destroy,: delete_all,: nullify o: restrict (: delete)
Mike Campbell
2
@MikeCampbell, :deletey las :destroy_allopciones no existen. Sin embargo, hay métodos de clase en los modelos que se llaman deletey, destroy_allpor lo tanto, podría ser el motivo de confusión.
berezovskyi
@MikeCampbell Le faltan algunas opciones más, consulte La opción dependiente debe ser una de [: destroy,: delete_all,: nullify,: restrict_with_error,: restrict_with_exception]
Pravin Mishra
30

Ver destruir elimina sus elementos asociados donde delete_all puede eliminar múltiples datos de la tabla propia comoDELETE * FROM table where field = 'xyz'

: Opciones posibles dependientes:

Controla lo que sucede con los objetos asociados cuando su propietario es destruido. Tenga en cuenta que estos se implementan como devoluciones de llamada, y Rails ejecuta devoluciones de llamada en orden. Por lo tanto, otras devoluciones de llamada similares pueden afectar el comportamiento dependiente, y el :dependentcomportamiento puede afectar otras devoluciones de llamada.

:destroy hace que todos los objetos asociados también sean destruidos.

:delete_all hace que todos los objetos asociados se eliminen directamente de la base de datos (por lo que no se ejecutarán las devoluciones de llamada).

:nullifyhace que las claves foráneas se establezcan en NULL. Las devoluciones de llamada no se ejecutan.

:restrict_with_exception hace que se genere una excepción si hay registros asociados.

:restrict_with_error hace que se agregue un error al propietario si hay algún objeto asociado.

Si se usa con la :throughopción, la asociación en el modelo de unión debe ser un pertenece a, y los registros que se eliminan son los registros de unión, en lugar de los registros asociados.

Shrivastava Manish
fuente
3

En realidad, la principal diferencia es que no se invocará ninguna devolución de llamada cuando :delete_allse usó. Pero cuando se usa :destroyla pila de devoluciones de llamada ( :after_destroy, :after_commit...) se disparará.

En consecuencia, si tiene touch:declaraciones que se están eliminando en los modelos, es mejor usar dependent: :delete_all'dependiente: destruir'.

atlascoder
fuente