Suppression de tous les enregistrements dans une table de base de données

129

Comment supprimer tous les enregistrements de l'une de mes tables de base de données dans une application Ruby on Rails?

Justin Meltzer
la source

Réponses:

249

Si vous cherchez un moyen d'y parvenir sans SQL, vous devriez pouvoir utiliser delete_all.

Post.delete_all

ou avec un critère

Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else')"

Voir ici pour plus d' informations.

Les enregistrements sont supprimés sans les charger au préalable, ce qui le rend très rapide mais cassera des fonctionnalités telles que le cache de compteur qui dépend du code de rails à exécuter lors de la suppression.

HakonB
la source
13
Il est intéressant de noter que si vous avez des associations avec: dependants =>: destroy, ou tout ce qui doit être nettoyé lors de la suppression, vous voudrez probablement Post.destroy_all - bien que ce soit beaucoup plus lent. Voir apidock.com/rails/ActiveRecord/Base/destroy_all/class
Michael Hellein
Cette réponse suppose que la table est associée à un modèle. L'OP ne l'a pas spécifié - et si la table est une table de jointure?
Toby 1 Kenobi
1
@BradWerth, que certains le considèrent ou non comme un bon ou un mauvais style, je dis simplement qu'il est possible qu'une base de données Rails ait des tables qui ne soient pas des ActiveRecordmodèles. La question porte sur la suppression d'un enregistrement d'une «table» et je ne fais que pointer ou l'hypothèse contenue dans la réponse.
Toby 1 Kenobi du
J'ai la même requête que celle de @ Toby1Kenobi.
nbsamar du
30

Pour supprimer via SQL

Item.delete_all # accepts optional conditions

Pour supprimer en appelant la méthode destroy de chaque modèle (coûteuse mais garantit que les rappels sont appelés)

Item.destroy_all # accepts optional conditions

Tout ici

lebreeze
la source
21

si vous souhaitez vider complètement la base de données et pas simplement supprimer un ou plusieurs modèles qui y sont attachés, vous pouvez faire:

rake db:purge

vous pouvez également le faire sur la base de données de test

rake db:test:purge
KensoDev
la source
5

Si vous voulez dire supprimer toutes les instances de tous les modèles, j'utiliserais

ActiveRecord::Base.connection.tables.map(&:classify)
  .map{|name| name.constantize if Object.const_defined?(name)}
  .compact.each(&:delete_all)
dfaulken
la source
1
Préférez selectchaque fois que vous avez besoin d'utiliser une expression if à l'intérieur d'un bloc, de cette façon vous évitez d'avoir à chaîner la méthode compacte pour supprimer les éléments nil.
Sebastian Palma
4
BlogPost.find_each(&:destroy)
Philippe
la source
Ceci est idéal pour les circonstances de faible mémoire.
Epigene
C'est la seule réponse qui prend en compte la consommation de mémoire.
John
2
Omg, pourquoi faire une boucle pour ça ... pas de sens. supprimez simplement tous les enregistrements DELETE FROM table, Model.delete_all
Imnl
@John pourquoi une seule requête consomme plus de mémoire qu'une boucle de requêtes?
Imnl
@Imnl Chaque itération instancie une nouvelle instance du modèle en question afin qu'elle puisse traiter les rappels de la méthode de suppression.
John
2

Si votre modèle s'appelle BlogPost, ce serait:

BlogPost.all.map(&:destroy)
stef
la source
cela récupérera chaque BlogPost et le chargera dans un tableau Ruby avant de les détruire.
hdgarrood
Dépend de l'ORM. Datamapper ne ferait pas cela car vous ne demandez rien sur chaque modèle. Et voici un stacktrace mongoïde qui montre qu'il ne sélectionne aucun champ avant de détruire chaque entrée:MOPED: 127.0.0.1:27017 QUERY database=a_database collection=nothings selector={} flags=[:slave_ok] limit=0 skip=0 batch_size=nil fields=nil (0.3378ms)
stef
4
puisque c'est une question de rails, et que le demandeur n'a pas dit quel ORM il utilise, nous devrions supposer ActiveRecord
hdgarrood
2

Réponse plus récente dans le cas où vous souhaitez supprimer toutes les entrées de toutes les tables:

def reset
    Rails.application.eager_load!
    ActiveRecord::Base.descendants.each { |c| c.delete_all unless c == ActiveRecord::SchemaMigration  }
end

Plus d'informations sur eager_load ici .

Après l'avoir appelé, nous pouvons accéder à tous les descendants de ActiveRecord::Baseet nous pouvons appliquer un delete_allsur tous les modèles.

Notez que nous nous assurons de ne pas effacer la table SchemaMigration.

Simon Ninon
la source