我正在尝试使用耙子任务(耙子数据:导入)从csv fle导入数据,但出现错误。在过去的几个月里,我一直在自学rails,但经过一天半的谷歌搜索,我找到了很多解决方案,没有一个我能开始工作。
这是我到目前为止与我的耙子文件站在一起的地方:
require 'CSV'
namespace :data do
desc "Import teams from csv file"
task :import => [:environment] do
file=IO.read('filepath of my csv').force_encoding("ISO-8859-1").encode("utf-8", replace: nil)
CSV.foreach(file, :headers => true) do |row|
product.create ([
:name => row['name'],
:rating => row['rating'],
:year => row['year'],
:country => row['country'],
:state_or_province => row['state_or_province']]
)
end
end
end
我没有收到任何特定的错误(据我所知)。让我感到困惑的输出是:
tasks/dataimport.rake:7:in `block (2 levels) in <top (required)>'
该输出是否表明正在发生任何特定事件?
这里有很多问题,所以我将从顶部开始。
CSV.foreach
旨在打开一个文件并一次遍历所有文件。要CSV.foreach
的第一个参数应该是文件名,而不是文件的内容。这意味着:
CSV.foreach(file, :headers => true) do |row|
出错file
因为 是一个包含 CSV 数据的字符串,而不是CSV.foreach
期望的文件名。由于您要从拉丁语 1 文本转换为 UTF-8,因此您需要CSV.foreach
为您处理这个问题,您可以使用:encoding
选项:
此方法还了解可用于指定要读取的文件中数据的编码的其他
:encoding
参数。[...]例如,encoding: "UTF-32BE:UTF-8"
会从文件中读取 UTF-32BE 数据,但在 CSV 解析之前将其转码为 UTF-8。
综上所述,我们有:
CSV.foreach('filepath of my csv', :headers => true, :encoding => 'ISO-8859-1:UTF-8') do |row|
进行 CSV 读取和迭代后,您将看到如下错误:
NameError: undefined local variable or method `product' for ...
你会得到一个NameError
,因为你的耙子任务中没有任何地方定义product
。我怀疑你的意思是说Product.create
,这将尝试创建Product
模型的新实例。Ruby 区分大小写,因此product
和Product
是不同的东西,Product
类。
处理NameError
后,您会看到如下投诉:
NoMethodError: undefined method `keys' for [{ ... }]:Array
您将获得NoMethodError
,因为Product.create
希望看到属性及其值的哈希,而不是包含哈希的数组。你会想说:
Product.create(
:name => row['name'],
:rating => row['rating'],
:year => row['year'],
:country => row['country'],
:state_or_province => row['state_or_province']
)
当然,如果您的row
只包含这五个值,那么只需将整个row
交给create
:
Product.create(row.to_hash)
如果row
包含(或可能包含)一堆你不想让create
看到的其他内容,请使用Hash#slice
只抓取你感兴趣的row
部分:
Product.create(row.to_hash.slice(*%w[name rating year country state_or_province]))
请注意,%w[...]
从空格分隔的列表构建一个字符串数组,因此这些字符串是相同的:
%w[a b]
['a', 'b']
然后 splat (*
) 删除数组包装器,因此这些是相同的:
row.to_hash.slice(*%w[name rating year country state_or_province])
row.to_hash.slice('name', 'rating', 'year', 'country', 'state_or_province')
您可以使用任何对眼睛更容易的形式。
还要注意那里的to_hash
调用。您的row
将是一个CSV::Row
对象,在其上调用to_hash
会将该行作为哈希。
这应该使您的整个耙子任务看起来像这样:
CSV.foreach('filepath of my csv', :headers => true, :encoding => 'ISO-8859-1:UTF-8') do |row|
Product.create(row.to_hash)
end
或
CSV.foreach('filepath of my csv', :headers => true, :encoding => 'ISO-8859-1:UTF-8') do |row|
Product.create(row.to_hash.slice(*%w[name rating year country state_or_province]))
end
您可能还希望向这些create
调用添加一些错误处理。