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

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

👋 Kindness is contagious

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

Okay