我想做与此问题How to write Rake task to import data to Rails app?中解释的相同的事情。
但是,我对接受的答案不满意,因为它不考虑来源中的已删除项目。
考虑到源中的已删除条目,最简单,最常用的轨道符合这一点的方法是什么?
注意:
答案 0 :(得分:0)
您绝对不应该删除所有记录,然后从数据中重新创建它们。这将产生各种各样的问题,例如,破坏其他表中的任何外键字段,这些字段在删除之前用于指向该对象。这就像敲房子并重建它以便有一个不同颜色的门。所以,"看看它是否在那里,如果它然后更新它(如果它不同),如果它不是那么创建它"是正确的策略。
您不能说明您的删除标准是什么,但是如果它是"任何在导入数据中未提及的记录都应该被删除"那么你只需要跟踪输入数据中的一些独特字段,然后删除该列表中自己唯一字段不存在的所有记录。
所以,你进行导入的代码看起来像这样(从另一个问题复制代码:这段代码以极其笨重的方式设置数据,但我不会在这里解决这个问题)
namespace :data do
desc "import data from files to database"
task :import => :environment do
file = File.open(<file to import>)
identifiers = []
file.each do |line|
#disclaimer: this way of setting the data from attrs[0], attrs[1] etc is crappy and fragile and is not how i would do it
attrs = line.split(":")
identifier = attrs[0]
identifiers << identifier
if p = Product.find_or_initialize_by_identifier(identifier)
p.name = attrs[1]
etc...
p.save!
end
end
#destroy any which didn't appear in the import data
Product.where("identifier not in (?)", identifiers).each(&:destroy)
end
end
答案 1 :(得分:0)
我使用的是使用.delete_all和没有rails的默认id
auto_increment列的表架构,以避免在.delete_all之后增加值。
create_table :airport_locations, id: false do |t|
t.string :iata_faa_code, :primary_key
t.float :latitude
t.float :longitude
end
add_index :airport_locations, :iata_faa_code
注释