需要使用ActivereCord-Import和Rubyzip Gem将ZIP文件内的CSV数据导入我的产品模型。
此代码有效(下载zip并显示CSV名称)
desc "Import products data from web"
task import_product: :environment do
url = "https://example.com"
dir = "db/example_zip.zip"
File.open(dir, "wb") do |f|
f.write HTTParty.get(url).body
end
Zip::File.open(dir) do |zip|
zip.each do |entry|
entry.name
end
end
end
在" zip.east循环"中,我尝试了:
items = []
CSV.foreach(entry, headers: true) do |row|
items << Item.new(row.to_h)
end
Item.import(items)
我有以下错误 TypeError:Zip ::进入字符串
的隐含转换根据本教程:https://mattboldt.com/importing-massive-data-into-rails/
使用此CSV刷新我的产品模型数据的最佳方法是什么?我必须将文件读取到内存中(entry.get_input_stream.read)或保存文件然后导入吗?
感谢您的帮助
引起的异常TypeError: no implicit conversion of Zip::Entry into String
是因为CSV.foreach
方法接受文件路径(String
对象)作为参数,但您将其发送给Zip::Entry
对象。
您可以简单地提取zip文件并将其内容直接加载到内存中:
Zip::File.open(dir) do |zip|
zip.each do |entry|
items = []
CSV.new(entry.get_input_stream.read, headers: true).each do |row|
items << Item.new(row.to_h)
end
Item.import(items)
end
end
或CSV文件太大,您可以持久持续解压缩文件,然后使用CSV.foreach
加载这些文件:
Zip::File.open(dir) do |zip|
zip.each do |entry|
csv_file = File.join(File.dirname(dir), entry.name)
entry.extract(csv_file)
items = []
CSV.foreach(csv_file, headers: true) do |row|
items << Item.new(row.to_h)
end
Item.import(items)
end
end
您可以在这些文档中阅读更多:
-
CSV.foreach
:https://ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/csv.html#method-c-foreach -
rubyzip
gem https://github.com/rubyzip/rubyzip#reading-a-zip-file
最后,这是我下载zip文件并导入数据模型的代码
require 'zip'
require 'httparty'
require 'active_record'
require 'activerecord-import'
namespace :affiliate_datafeed do
desc "Import products data from Awin"
task import_product_awin: :environment do
url = "https://productdata.awin.com"
dir = "db/affiliate_datafeed/awin.zip"
File.open(dir, "wb") do |f|
f.write HTTParty.get(url).body
end
zip_file = Zip::File.open(dir)
entry = zip_file.glob('*.csv').first
csv_text = entry.get_input_stream.read
products = []
CSV.parse(csv_text, :headers=>true).each do |row|
products << Product.new(row.to_h)
end
Product.import(products)
end
end
但是,下一个问题是,如何仅当产品不存在时才更新产品DB,或者在Last_updated字段中有新日期吗?刷新大DB的最佳方法是什么?谢谢