web-dev-qa-db-fra.com

Comment supprimer toutes les données de toutes les tables dans Rails?

Je peux faire Post.delete_all pour supprimer tous mes messages, mais que se passe-t-il si je souhaite supprimer tous les messages, commentaires, blogs, etc.? 

Comment puis-je parcourir tous mes modèles et exécuter la méthode delete_all?

57
Tom Lehman
rake db:reset 

Il recrée votre table à partir des migrations.

Comme suggéré dans les commentaires, un moyen plus rapide de le faire (mais vous devez ajouter une nouvelle tâche de rake) est:

namespace :db do
  desc "Truncate all tables"
  task :truncate => :environment do
    conn = ActiveRecord::Base.connection
    tables = conn.execute("show tables").map { |r| r[0] }
    tables.delete "schema_migrations"
    tables.each { |t| conn.execute("TRUNCATE #{t}") }
  end
end

Réponse copiée de: réponse le SO .

78
Vlad Zloteanu

Vous pouvez avoir un contrôle plus fin avec:

rake db:drop:all

Et puis créer la base de données sans exécuter les migrations,

rake db:create:all

Puis lancez toutes vos migrations,

rake db:migrate 

Vous pouvez aussi faire:

mysqladmin drop databasename
27
Sameer C

Si vous essayez de le faire depuis le code au lieu de la ligne de commande, par exemple avec une méthode Test::Unit::TestCase#teardown, vous pouvez faire soit

class MyTest < Test::Unit::TestCase

  def teardown
    ActiveRecord::Base.subclasses.each(&:delete_all)
  end

end

ou

class MyTest < Test::Unit::TestCase

  def teardown
    Rake::Task['db:reset'].invoke
  end

end

Je vous préviens cependant: ni en particulier rapide. Vous êtes certainement mieux avec des tests transactionnels si vous le pouvez.

22
James A. Rosen

Si vous voulez simplement recommencer à zéro avec un nouvel ensemble de tables vides, vous devez d'abord vous assurer que vous avez une définition à jour du schéma dans db/schema.rb:

rake db:schema:dump

et alors:

rake db:schema:load

ce qui a pour effet de supprimer des tables, puis de les recréer, sans passer par toute votre batterie de migrations.

15
KenB

Un moyen plus rapide de juste supprimer des lignes de table consiste à utiliser la commande TRUNCATE.

Beaucoup d'autres réponses semblent ignorer la différence entre la suppression de lignes et la suppression d'un tableau. La suppression d'une table détruit les données et le schéma de la table; ce qui signifie que vous avez besoin d'étapes supplémentaires pour recréer les tables. La réponse de Sean McLeary était la meilleure que j'ai vue, alors je l'ai utilisée comme point de départ. Cependant, je pense qu'il est préférable de tirer parti de la commande TRUNCATE, car elle devrait être plus rapide et réinitialiser les clés à incrémentation automatique. De plus, utiliser map au lieu de each raccourcit un peu le code.

namespace :db do
  desc "Truncate all tables"
  task :truncate => :environment do
    conn = ActiveRecord::Base.connection
    tables = conn.execute("show tables").map { |r| r[0] }
    tables.delete "schema_migrations"
    tables.each { |t| conn.execute("TRUNCATE #{t}") }
  end
end
10
David J.

Rails db:purge

a récemment été ajouté à ActiveRecord dans la branche principale de Rails 4.2.0.alpha

https://github.com/Rails/rails/commit/e2f232aba15937a4b9d14bd91e0392c6d55be58d

9
gef

Cela fonctionnera aussi pour Rails 4

(ActiveRecord::Base.connection.tables - ['schema_migrations']).each do |table|
    table.classify.constantize.destroy_all
end
4
Rene

Réponse acceptée avec Postgres db:

namespace :db do
  desc "Truncate all tables"
  task :truncate => :environment do
    conn = ActiveRecord::Base.connection
    postgres = "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname='public'"
    tables = conn.execute(postgres).map { |r| r['tablename'] }
    tables.delete "schema_migrations"
    tables.each { |t| conn.execute("TRUNCATE \"#{t}\"") }
  end
end
4
vaughan

Vous pouvez lister tous les modèles dans le fichier seed (seeds.rb), et simplement lancer

rake db:seed

Le fichier de départ ressemblerait alors à quelque chose comme ça:

Model1.delete_all
Model2.delete_all
Model3.delete_all
Model4.delete_all
Model5.delete_all
Model6.delete_all
Model7.delete_all

...

rake db:reset est trop pour votre travail ici. Cela va complètement tuer votre base de données et la reconstruire à partir de zéro, en exécutant toutes les migrations, etc. Pour exécuter la commande de démarrage est plus rapide.

4
Automatico

Nous avons été négligent ici à Stack Overflow pour ne pas mentionner le database_cleaner gem :

Database Cleaner est un ensemble de stratégies permettant de nettoyer votre base de données en Ruby . Le cas d'utilisation original était d'assurer un état de propreté pendant les tests. Chaque stratégie est une petite quantité de code, mais est le code qui est généralement nécessaire dans toute application Ruby c'est tester avec une base de données.

Par «stratégie», M. Mabey entend: troncature, transaction et suppression.

ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid et CouchPotato sont pris en charge.

Voici un extrait de code rapide du Database Cleaner README :

require 'database_cleaner'
DatabaseCleaner.strategy = :truncation

# then, whenever you need to clean the DB
DatabaseCleaner.clean
3
David J.
# fast truncation of all tables that need truncations (select is 10x faster then truncate)
# http://grosser.it/2012/07/03/rubyactiverecord-fastest-way-to-truncate-test-database/
def truncate_all_tables
  connection = ActiveRecord::Base.connection
  connection.disable_referential_integrity do
    connection.tables.each do |table_name|
      next if connection.select_value("SELECT count(*) FROM #{table_name}") == 0
      connection.execute("TRUNCATE TABLE #{table_name}")
    end
  end
end
3
grosser

Si vous souhaitez supprimer uniquement les données sans toucher aux tables tout en les utilisant dans votre application ou la console Rails:

Rails.application.eager_load!
ActiveRecord::Base.connection.disable_referential_integrity do
  ApplicationRecord.descendants.each do |model|
    model.delete_all
  end
end

Avec ce code, vous n'avez pas à vous soucier de référencer manuellement vos modèles et/ou avec des contraintes de clé étrangère (grâce à disable_referential_integrity).
ApplicationRecord.descendants ne renvoie que des modèles d’application vrais contrairement à ActiveRecord :: Base.descendants (plus ApplicationRecord, schema_migrations et ar_internal_metadata).

3
devoh

Je sais que c'est une vieille question, mais j'ai pensé que cela pourrait être utile à quelqu'un. C'est un moyen très rapide de nettoyer toutes les données d'une base de données.

tables = []
ActiveRecord::Base.connection.execute("show tables").each { |r| tables << r[0] }
tables = tables - ["schema_migrations"]
tables.each do |table|
  ActiveRecord::Base.connection.execute("DELETE FROM #{table} WHERE 1 = 1")
end

J'utilise cette technique dans certaines spécifications d'un bloc after(:all). Cette opération est beaucoup plus rapide et efficace que n’importe laquelle des tâches de ratissage de Rails pour le nettoyage, la migration et la réinitialisation de la base de données.

BTW: Je suis à peu près sûr que cela échouerait probablement si vous appliquiez des contraintes de clé étrangère du côté de la base de données.

2
Sean McCleary

Dans Rails 6, vous pouvez utiliser Rails db:truncate_all pour supprimer toutes les données sans supprimer aucune table.

Si vous souhaitez utiliser votre base de données après cela, vous pouvez également utiliser Rails db:seed:replant pour tronquer toutes les données et la base de données

1
KahTim

Mes 50 centimes, pour le nettoyage de la base de données et la possibilité d'effectuer à nouveau des migrations (dans les cas où vous ne pouvez pas supprimer de base de données, par exemple AWS RDS):

# get connection
conn = ActiveRecord::Base.connection
# find all tables needed to be removed
tables = conn.execute("SELECT * FROM pg_catalog.pg_tables WHERE schemaname='public' AND tablename<>'schema_migrations'").to_a.map { |r| r['tablename'] }
# remove all tables except schema_migrations
tables.each { |t| conn.execute("DROP TABLE #{t}") }
# clean migrations table
conn.execute("TRUNCATE TABLE schema_migrations")

Et maintenant, vous pouvez exécuter rake db:migrate pour que votre base de données soit dans un état propre.

1
Vitaly Dyatlov

Sur la base de la réponse de @Vlad Zloteanu, voici une version permettant de supprimer toutes les tables tout en conservant les enregistrements utilisateur et les sessions de connexion, ainsi que des métadonnées. N'hésitez pas à adapter la liste des tableaux à vos besoins.

# lib/tasks/db/truncate.rake

namespace :db do
  desc 'Truncate all tables except users state and meta'
  task truncate: :environment do
    conn = ActiveRecord::Base.connection
    tables = conn.tables - %w[
      sessions
      users
      roles
      users_roles
      schema_migrations
      ar_internal_metadata
    ]
    tables.each { |t| conn.execute("TRUNCATE #{t}") }

    puts "Truncated tables\n================\n#{tables.sort.join("\n")}"
  end
end
0
Nic Nilov