DEV Community

Francisco Quintero 🇨🇴
Francisco Quintero 🇨🇴

Posted on • Originally published at otroespacioblog.wordpress.com

6 1

¿Cuál es la diferencia entre :destroy y :delete en Rails?

Una de las enseñanzas o instrucciones que se da cuando se diseñan bases de datos es que no debe haber información relacionada que no tenga su “dueño” o “padre”. Si un artículo tiene muchos comentarios y dicho artículo se elimina de la base de datos, tales comentarios también deben hacerlo.

En SQL a esto se le llama borrado en cascada. Para lograr esto en Rails usando ActiveRecord podemos usar la opción dependent y pasando algunas opciones disponibles.

A continuación trataré de explicar la diferencia entre las dos más comunes.

:destroy

Se utiliza así:

class User < ApplicationRecord
  has_many :payment_methods, dependent: :destroy
end
Enter fullscreen mode Exit fullscreen mode

La opción :destroy le dice a ActiveRecord que elimine los registros hijos pero usando el método destroy de cada uno de ellos, es decir, primero los instancia y luego los elimina, uno por uno.

Si hay muchos registros hijos, será muy lento de esta forma.

Así luce mi consola al usar esta opción:

User Load (0.4ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
   (0.1ms)  BEGIN
PaymentMethod Load (0.3ms)  SELECT "payment_methods".* FROM "payment_methods" WHERE "payment_methods"."user_id" = $1  [["user_id", 1]]
  SQL (24.7ms)  DELETE FROM "payment_methods" WHERE "payment_methods"."id" = $1  [["id", 3]]
  SQL (0.3ms)  DELETE FROM "payment_methods" WHERE "payment_methods"."id" = $1  [["id", 2]]
  SQL (0.2ms)  DELETE FROM "payment_methods" WHERE "payment_methods"."id" = $1  [["id", 1]]
  SQL (0.4ms)  DELETE FROM "users" WHERE "users"."id" = $1  [["id", 1]]
    (0.3ms)  COMMIT
Enter fullscreen mode Exit fullscreen mode

:delete_all

Se utiliza así:

class User < ApplicationRecord
  has_many :payment_methods, dependent: :delete_all
end
Enter fullscreen mode Exit fullscreen mode

En cambio, la opción :delete_all lo que hace es una eliminación directa mediante una consulta SQL pura. Más eficiente si hay muchos registros asociados a un padre.

Así luce mi consola cuando uso esta opción:

User Load (0.4ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
   (0.1ms)  BEGIN
  SQL (0.3ms)  DELETE FROM "payment_methods" WHERE "payment_methods"."user_id" = $1  [["user_id", 3]]
  SQL (0.1ms)  DELETE FROM "users" WHERE "users"."id" = $1  [["id", 3]]
   (0.3ms)  COMMIT
Enter fullscreen mode Exit fullscreen mode

Usar :delete_all no efectúa el llamado a cualquier callback definido en el modelo.

Así que hay varios puntos aquí para diferenciar estas dos opciones:

  • :destroy: Instancia cada objeto. Llamado a callbacks. Menos eficiente.
  • :delete_all: Borrado directo por SQL. No llama a callbacks. Más eficiente.

Dicha eficiencia depende de lo que se necesite hacer y es un costo aceptable en muchas ocasiones.

Cualquiera de los dos es correcto usar, ya cada caso particular determina cuál elegir al final.

Enlaces

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay