通过耙子任务将CSV文件上传到Rails 4 DB



我正在尝试使用耙子任务(耙子数据:导入)从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 区分大小写,因此productProduct是不同的东西,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调用添加一些错误处理。

相关内容

  • 没有找到相关文章

最新更新