如何在Rails上导入CSV到数据库,同时跳过回调



我目前正试图导入超过40 CSV的从sqlite3导出到oracle db,但我似乎有问题,同时导入一些的CSV文件,到相应的表中。

包含:

的代码行

class_name.create!(row.to_hash)

在某些类上产生错误,因为当

.create!()方法被称为

def import_csv_into_db
Dir.foreach(Rails.root.join('db', 'csv_export')) do |filename|
next if filename == '.' or filename == '..' or filename == 'extract_db_into_csv.sh' or filename =='import_csv.rb'
filename_renamed = File.basename(filename, File.extname(filename)).chomp('s').titleize.gsub(/s+/, "")
CSV.foreach(Rails.root.join('db', 'csv_export',filename), headers: true) do |row|
class_name = Object.const_get(filename_renamed)
puts class_name
class_name.create!(row.to_hash)
puts "Insert on table #{class_name}s complete with:  #{row.to_hash}"
end
end
end

手头的问题是,我的CSV导入功能是在seeds.rb,所以每当我运行bundle exec rake db:seedCSV的导入。

class_name.create!(row.to_hash)seeds.rb的函数内被触发时,我该如何避免回调被触发?

在我的customer.rb我有回调,如:

after_create :add_default_userafter_create :add_build_config

我想在seeds.rb中操作我的函数,以便在函数尝试导入像customers.csv这样的CSV文件(逻辑上调用Customer.create!(row.to_hash))时跳过回调。

有较低级别的方法不会运行回调。例如,可以调用insert!而不是create!。您可以调用delete而不是destroy

旁注:使用insert_all!一次批量插入多行。您的导入将更快,而且它不使用验证。不过我还是推荐更灵活的active-import


但是,跳过回调可能会导致问题,如果它们是数据完整性所必需的。如果您用delete代替destroy关联的数据可能不会被删除,或者您可能会因为引用完整性而得到错误。确保在外键上添加on delete操作以避免这种情况。然后数据库自己会处理它。

考虑db:seeds是否做得太多了。如果导入这个CSV妨碍了数据库的播种,那么考虑是否应该将它作为一个单独的rake任务。

考虑是否可以将回调重写为幂等的,即能够多次运行。例如,after_create :add_default_user应该识别已经存在一个默认用户,而不会尝试重新添加它。

最后,考虑每次创建模型时运行的回调是否是执行此工作的正确位置。

最新更新