Je cherche la meilleure approche pour supprimer des enregistrements d'une table. Par exemple, j'ai un utilisateur dont l'ID utilisateur est réparti sur plusieurs tables. Je veux supprimer cet utilisateur et chaque enregistrement qui a son identifiant dans toutes les tables.
u = User.find_by_name('JohnBoy')
u.usage_indexes.destroy_all
u.sources.destroy_all
u.user_stats.destroy_all
u.delete
Cela fonctionne et supprime toutes les références de l'utilisateur de toutes les tables, mais j'ai entendu dire que destroy_all
était très lourd en processus. J'ai donc essayé delete_all
. Il supprime uniquement l'utilisateur de sa propre table et le id
de toutes les autres tables devient nul, mais laisse les enregistrements intacts dans celles-ci. Quelqu'un peut-il indiquer quel est le processus correct pour effectuer une tâche de ce type?
Je vois que destroy_all
appelle la fonction destroy
sur tous les objets associés, mais je veux simplement confirmer l'approche correcte.
Tu as raison. Si vous souhaitez supprimer l'utilisateur et tous les objets associés -> destroy_all
Toutefois, si vous souhaitez uniquement supprimer l'utilisateur sans supprimer tous les objets associés -> delete_all
Selon ce post: Rails: dépendants =>: détruisent VS: dépendants =>: delete_all
destroy
/destroy_all
: Les objets associés sont détruits à côté de cet objet en appelant leur méthode destroydelete
/delete_all
: Tous les objets associés sont détruits immédiatement sans appeler leur méthode: destroydelete_all est une instruction SQL DELETE unique et rien de plus. destroy_all appelle destroy () sur tous les résultats correspondants de: conditions (si vous en avez une) qui peuvent être au moins NUM_OF_RESULTS instructions SQL.
Si vous devez faire quelque chose de radical, tel que destroy_all () sur un grand jeu de données, je ne le ferais probablement pas à partir de l'application et ne le manipulerais pas manuellement avec soin. Si le jeu de données est suffisamment petit, vous ne souffrirez pas autant.
Pour éviter le fait que destroy_all
instancie tous les enregistrements et les détruit un à un, vous pouvez l'utiliser directement à partir de la classe de modèle.
Donc au lieu de:
u = User.find_by_name('JohnBoy')
u.usage_indexes.destroy_all
Tu peux faire :
u = User.find_by_name('JohnBoy')
UsageIndex.destroy_all "user_id = #{u.id}"
Le résultat est une requête pour détruire tous les enregistrements associés
J'ai créé un petit bijo qui évite d'avoir à supprimer manuellement les enregistrements associés dans certaines circonstances.
Ce bijou ajoute une nouvelle option pour les associations ActiveRecord:
dépendant:: delete_recursively
Lorsque vous détruisez un enregistrement, tous les enregistrements associés à l'aide de cette option seront supprimés de manière récursive (c.-à-d. Entre modèles), sans en instancier aucun.
Notez que, tout comme dépendante:: delete ou dépendante:: delete_all, cette nouvelle option ne déclenche pas les rappels autour/avant/après_destroy des enregistrements dépendants.
Cependant, il est possible d'avoir des associations dépendantes:: détruisent n'importe où dans une chaîne de modèles autrement associés à dépendantes:: delete_recursively. L'option: destroy fonctionne normalement n'importe où sur la ligne, instanciant et détruisant tous les enregistrements pertinents et déclenchant ainsi leurs rappels.