jfa*_*son 2 ruby csv rake rails-migrations ruby-on-rails-4
我正在尝试使用rake任务(rake data:import)从csv fle导入数据并且收到错误.过去几个月我一直在教自己,但经过一天半的谷歌搜索后,我找到了许多解决方案,但没有一个可以开始工作.
到目前为止,我的rake文件就在这里:
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
Run Code Online (Sandbox Code Playgroud)
我没有得到任何具体的错误(据我所知).混淆我的输出是:
tasks/dataimport.rake:7:in `block (2 levels) in <top (required)>'
Run Code Online (Sandbox Code Playgroud)
该输出是否表明具体发生了什么?
mu *_*ort 10
这里出了很多问题,所以我会从顶部开始.
CSV.foreach
意味着打开一个文件并立即迭代它.第一个参数CSV.foreach
应该是文件名而不是文件的内容.这意味着:
CSV.foreach(file, :headers => true) do |row|
Run Code Online (Sandbox Code Playgroud)
出错是因为file
是包含CSV数据的字符串而不是CSV.foreach
期望的文件名.由于您要将Latin-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|
Run Code Online (Sandbox Code Playgroud)
一旦获得CSV读取和迭代,您将看到如下错误:
NameError: undefined local variable or method `product' for ...
Run Code Online (Sandbox Code Playgroud)
你得到一个,NameError
因为product
你的rake任务中没有任何定义.我怀疑你的意思是说Product.create
,这会尝试创建一个新的Product
模型实例.Ruby是区分大小写,product
并且Product
是不同的东西,Product
将是一流的.
一旦NameError
处理完毕,你会看到这样的抱怨:
NoMethodError: undefined method `keys' for [{ ... }]:Array
Run Code Online (Sandbox Code Playgroud)
你会得到NoMethodError
因为Product.create
想要查看属性及其值的哈希,而不是包含哈希的数组.你想说:
Product.create(
:name => row['name'],
:rating => row['rating'],
:year => row['year'],
:country => row['country'],
:state_or_province => row['state_or_province']
)
Run Code Online (Sandbox Code Playgroud)
当然,如果你row
只包含那五个值,那么只需将整个内容row
交给create
:
Product.create(row.to_hash)
Run Code Online (Sandbox Code Playgroud)
如果row
包含(或可能包含)一堆您不想create
看到的其他内容,请使用Hash#slice
以获取row
您感兴趣的部分内容:
Product.create(row.to_hash.slice(*%w[name rating year country state_or_province]))
Run Code Online (Sandbox Code Playgroud)
请注意,%w[...]
从白色空格分隔列表构建字符串数组,因此它们是相同的:
%w[a b]
['a', 'b']
Run Code Online (Sandbox Code Playgroud)
然后splat(*
)删除数组包装器,因此它们是相同的:
row.to_hash.slice(*%w[name rating year country state_or_province])
row.to_hash.slice('name', 'rating', 'year', 'country', 'state_or_province')
Run Code Online (Sandbox Code Playgroud)
您可以使用更容易在眼睛上使用的任何形式.
还要注意to_hash
那里的电话.你row
将成为一个CSV::Row
对象,调用to_hash
它会给你一行作为哈希.
这应该让你的整个rake任务看起来像这样:
CSV.foreach('filepath of my csv', :headers => true, :encoding => 'ISO-8859-1:UTF-8') do |row|
Product.create(row.to_hash)
end
Run Code Online (Sandbox Code Playgroud)
要么
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
Run Code Online (Sandbox Code Playgroud)
您可能还想为这些create
调用添加一些错误处理.
归档时间: |
|
查看次数: |
2894 次 |
最近记录: |