Ruby on rails rails db种子文件在种子设定之前删除特定表中现有数据的最佳方式,以防止重复数据

Ruby on rails rails db种子文件在种子设定之前删除特定表中现有数据的最佳方式,以防止重复数据,ruby-on-rails,activerecord,seeding,Ruby On Rails,Activerecord,Seeding,我在rails应用程序中有几个表。 一个表包含我现在想要更新的种子数据,而不涉及其他表。 但是,如果我没有弄错的话,简单地使用rakedb:seed将复制我的数据 我可以包括这样的命令吗 ModelName.全部删除 在种子文件的开头 最好的方法是什么?您可以,但是如果ModelName有任何关联,那么您将破坏外键ID。听起来有点冒险 既然如此。。。我在种子文件中有一些代码,可以将一小部分非常特定的数据加载到模型中。我有一个包含我想要的所有字段的散列,然后我循环遍历它,找到并更新或创建行 pro

我在rails应用程序中有几个表。 一个表包含我现在想要更新的种子数据,而不涉及其他表。 但是,如果我没有弄错的话,简单地使用
rakedb:seed
将复制我的数据

我可以包括这样的命令吗
ModelName.全部删除
在种子文件的开头


最好的方法是什么?

您可以,但是如果ModelName有任何关联,那么您将破坏外键ID。听起来有点冒险

既然如此。。。我在种子文件中有一些代码,可以将一小部分非常特定的数据加载到模型中。我有一个包含我想要的所有字段的散列,然后我循环遍历它,找到并更新或创建行

providers = {
  foo: {name: 'Foo', ...},
  bar: {name: 'Bar', ...}
}

providers.each do |(code, attrs)|
  p = Provider.find_by(code: code) || Provider.new(code: code)
  p.update!(attrs)
end

可以,但是如果ModelName有任何关联,那么您将破坏外键ID。听起来有点冒险

既然如此。。。我在种子文件中有一些代码,可以将一小部分非常特定的数据加载到模型中。我有一个包含我想要的所有字段的散列,然后我循环遍历它,找到并更新或创建行

providers = {
  foo: {name: 'Foo', ...},
  bar: {name: 'Bar', ...}
}

providers.each do |(code, attrs)|
  p = Provider.find_by(code: code) || Provider.new(code: code)
  p.update!(attrs)
end
我可以在种子文件的开头包含ModelName.delete\u all这样的命令吗

当然可以,seed.rb只是一系列ruby(和rails)命令,所以您可以用它做任何事情

在我的一些项目中,我使用以下snipet从seed.rb删除了整个数据库:

tables = ActiveRecord::Base.connection.tables - ['schema_migrations']

tables.each do |table|
  ActiveRecord::Base.connection.execute "DELETE FROM `#{table}`"
  ActiveRecord::Base.connection.execute "ALTER TABLE `#{table}` AUTO_INCREMENT = 1"
end
使用此snipet,无需担心关联或链接ID。唯一剩下的垃圾是公共文件夹中的链接文件(例如通过carrierware或paper_trail)。在这种情况下,您需要手动清理这些文件夹

snipet的另一个优点是,在项目中添加新表时不必更新它,因为它负责删除所有表,除了
schema_迁移
,rails使用它跟踪包含/挂起的迁移

我可以在种子文件的开头包含ModelName.delete\u all这样的命令吗

当然可以,seed.rb只是一系列ruby(和rails)命令,所以您可以用它做任何事情

在我的一些项目中,我使用以下snipet从seed.rb删除了整个数据库:

tables = ActiveRecord::Base.connection.tables - ['schema_migrations']

tables.each do |table|
  ActiveRecord::Base.connection.execute "DELETE FROM `#{table}`"
  ActiveRecord::Base.connection.execute "ALTER TABLE `#{table}` AUTO_INCREMENT = 1"
end
使用此snipet,无需担心关联或链接ID。唯一剩下的垃圾是公共文件夹中的链接文件(例如通过carrierware或paper_trail)。在这种情况下,您需要手动清理这些文件夹


snipet的另一个优点是,在项目中添加新表时不必更新它,因为它负责删除所有表,除了
schema_迁移
,rails使用它跟踪已包含/正在等待的迁移

,我将使用
first\u或\u initialize
方法来确保我们在不破坏现有数据的情况下创建和更新现有数据。例如,您在种子数据中创建了几个用户,如下所示

3.times do |i|
   User.create(email: "abc@example.com", name: "Test #{i}")
end
3.times do |i|
   user = User.where(email: "abc@example.com").first_or_initialize
   user.name = "New Test #{i}"
   user.save
end
那么你应该这样做

3.times do |i|
   User.create(email: "abc@example.com", name: "Test #{i}")
end
3.times do |i|
   user = User.where(email: "abc@example.com").first_or_initialize
   user.name = "New Test #{i}"
   user.save
end

根据我的最佳实践,我将使用
first\u或\u initialize
方法来确保我们在不破坏现有数据的情况下创建和更新现有数据。例如,您在种子数据中创建了几个用户,如下所示

3.times do |i|
   User.create(email: "abc@example.com", name: "Test #{i}")
end
3.times do |i|
   user = User.where(email: "abc@example.com").first_or_initialize
   user.name = "New Test #{i}"
   user.save
end
那么你应该这样做

3.times do |i|
   User.create(email: "abc@example.com", name: "Test #{i}")
end
3.times do |i|
   user = User.where(email: "abc@example.com").first_or_initialize
   user.name = "New Test #{i}"
   user.save
end