【发布时间】:2009-07-28 19:14:49
【问题描述】:
我可以通过Post.delete_all 删除我所有的帖子,但是如果我想删除所有帖子、cmets、博客等怎么办?
如何遍历我的所有模型并运行 delete_all 方法?
【问题讨论】:
标签: ruby-on-rails activerecord
我可以通过Post.delete_all 删除我所有的帖子,但是如果我想删除所有帖子、cmets、博客等怎么办?
如何遍历我的所有模型并运行 delete_all 方法?
【问题讨论】:
标签: ruby-on-rails activerecord
rake db:reset
它从迁移中重新创建您的表。
根据 cmets 的建议,一种更快的方法(但您必须添加新的 rake 任务)是:
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
回复来自:answer on SO。
【讨论】:
tables,您还可以使用conn.tables 以更不可知的方式获取表格列表。这样它也适用于 postgres。
您可以通过以下方式进行更好的控制:
rake db:drop:all
然后在不运行迁移的情况下创建数据库,
rake db:create:all
然后运行所有迁移,
rake db:migrate
你也可以这样做:
mysqladmin drop databasename
【讨论】:
rake db:drop:all 正是我想要的。谢谢!
RAILS_ENV 环境变量进行更精细的控制
如果您尝试从代码而不是命令行执行此操作,例如从 Test::Unit::TestCase#teardown 方法,您可以执行任一操作
class MyTest < Test::Unit::TestCase
def teardown
ActiveRecord::Base.subclasses.each(&:delete_all)
end
end
或
class MyTest < Test::Unit::TestCase
def teardown
Rake::Task['db:reset'].invoke
end
end
不过,我警告你:特别也不是很快。如果可以的话,你肯定会更好地使用事务测试。
【讨论】:
如果您只是想从一组新的空表重新开始,您可以首先确保您在 db/schema.rb 中拥有最新的架构定义:
rake db:schema:dump
然后:
rake db:schema:load
这具有删除表然后重新创建它们的效果,而无需运行整个迁移电池。
【讨论】:
在 Rails 6 中,您可以通过 rails db:truncate_all 删除所有数据而不删除任何表。
如果您想在那之后为您的数据库播种,您也可以使用rails db:seed:replant 截断所有数据和种子数据库
【讨论】:
rails db:purge
最近已在 rails 4.2.0.alpha 的 master 分支中添加到 ActiveRecord
https://github.com/rails/rails/commit/e2f232aba15937a4b9d14bd91e0392c6d55be58d
【讨论】:
rails db:purge 实际上会删除数据库中的所有表(虽然不是数据库本身)。
只是删除表行的更快方法是使用 TRUNCATE 命令。
许多其他答案似乎忽略了删除行和删除表之间的区别。删除表会破坏表数据和模式;这意味着您需要额外的步骤来重新创建表。 Sean McLeary 的回答是我见过的最好的,所以我用它作为起点。但是,我认为最好利用 TRUNCATE 命令,因为它应该更快,并且它还重置自动增量键。此外,使用map 而不是each 会稍微缩短代码。
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
【讨论】:
schema_migrations 并不是必不可少的。但是,在截断表之后,您可能已将数据置于无法通过迁移进行导航的状态。因此,删除 schema_migrations 会让 Rails 从已知状态重新开始迁移。
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
如果有foreign_key类似ActiveRecord::StatementInvalid (PG::FeatureNotSupported: ERROR: cannot truncate a table referenced in a foreign key constraint)的错误
那么,CASCADE 选项会有所帮助。
tables.each { |t| conn.execute("TRUNCATE \"#{t}\" CASCADE") }
【讨论】:
如果您想在应用程序或 Rails 控制台中使用数据时只删除数据而不触及表格:
Rails.application.eager_load!
ActiveRecord::Base.connection.disable_referential_integrity do
ApplicationRecord.descendants.each do |model|
model.delete_all
end
end
使用此代码,您不必费心手动引用您的模型和/或使用外键约束(感谢 disable_referential_integrity)。
ApplicationRecord.descendants 只返回真正的应用程序模型,这与 ActiveRecord::Base.descendants 不同(不再有 ApplicationRecord、schema_migrations 和 ar_internal_metadata)。
【讨论】:
这也适用于 Rails 4
(ActiveRecord::Base.connection.tables - ['schema_migrations']).each do |table|
table.classify.constantize.destroy_all
end
【讨论】:
schema_migrations 相同的方式从 tables 数组中删除它。
您可以列出种子文件 (seeds.rb) 中的所有模型,然后简单地运行
rake db:seed
种子文件将如下所示:
Model1.delete_all
Model2.delete_all
Model3.delete_all
Model4.delete_all
Model5.delete_all
Model6.delete_all
Model7.delete_all
...
rake db:reset 对你的工作来说太过分了。这将完全杀死您的数据库并从头开始重建它,运行所有迁移等。运行种子命令更快。
【讨论】:
由于没有提及database_cleaner gem,我们在 Stack Overflow 上失职了:
Database Cleaner 是一组用于在 Ruby 中清理数据库的策略。 最初的用例是在测试期间确保干净的状态。每个策略 是少量的代码,但它是任何 ruby 应用程序中通常需要的代码 那是用数据库进行测试。
通过“策略”,Mabey 先生的意思是:截断、事务和删除。
支持 ActiveRecord、DataMapper、Sequel、MongoMapper、Mongoid 和 CouchPotato。
这是来自Database Cleaner README的快速代码sn-p:
require 'database_cleaner'
DatabaseCleaner.strategy = :truncation
# then, whenever you need to clean the DB
DatabaseCleaner.clean
【讨论】:
# 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
【讨论】:
我知道这是一个老问题,但我认为这可能对某人有所帮助。这是从数据库中清除所有数据的一种非常快速的方法。
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
我在 after(:all) 块的某些规范中使用了这种技术。这比用于清除、迁移、重置数据库的任何 Rails rake 任务都更快、更有效。
顺便说一句:我很确定如果您在数据库端强制执行外键约束,这可能会失败。
【讨论】:
我的 50 美分,用于清理数据库并能够再次运行迁移(以防您无法删除数据库,例如 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")
现在您可以运行rake db:migrate 让您的数据库处于干净状态。
【讨论】:
以@Vlad Zloteanu 的回答为基础,这是一个删除所有表的版本,同时保留用户记录和登录会话以及一些元信息。随意调整表格列表以满足您的要求。
# 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
【讨论】:
如果您想删除所有表并使用您可以使用的默认值重新初始化。
rails db:bootstrap
【讨论】: