Ruby 通过rake任务将CSV文件上载到Rails 4 DB
我试图使用rake任务(rake data:import)从csv fle导入数据,但出现了错误。在过去的几个月里,我一直在自学rails,但在谷歌搜索了一天半之后,我找到了很多解决方案,但没有一个能让我投入工作 这里是我目前使用rake文件的地方:Ruby 通过rake任务将CSV文件上载到Rails 4 DB,ruby,csv,ruby-on-rails-4,rake,rails-migrations,Ruby,Csv,Ruby On Rails 4,Rake,Rails Migrations,我试图使用rake任务(rake data:import)从csv fle导入数据,但出现了错误。在过去的几个月里,我一直在自学rails,但在谷歌搜索了一天半之后,我找到了很多解决方案,但没有一个能让我投入工作 这里是我目前使用rake文件的地方: require 'CSV' namespace :data do desc "Import teams from csv file" task :import => [:environment] do file=IO.read
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)>'
tasks/dataimport.rake:7:in'block(2层)in'
这个输出是否表明发生了什么具体情况?这里有很多错误,因此我将从顶部开始 是指打开一个文件并一次对其进行迭代。
CSV.foreach
的第一个参数应该是文件名,而不是文件内容。这意味着:
CSV.foreach(file, :headers => true) do |row|
出现错误,因为file
是包含CSV数据的字符串,而不是CSV.foreach
所需的文件名。由于您正在从拉丁语-1文本转换为UTF-8,因此需要获取CSV.foreach
来为您处理该问题,您可以使用: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 ...
你会得到一个namererror
,因为在你的rake任务中没有定义产品。我猜想您的意思是说Product.create
,这将尝试创建您的Product
模型的新实例。Ruby是区分大小写的,因此product
和product
是不同的东西,product
将是类
一旦处理了名称错误
,您将看到如下投诉:
NoMethodError: undefined method `keys' for [{ ... }]:Array
CSV.foreach('filepath of my csv', :headers => true, :encoding => 'ISO-8859-1:UTF-8') do |row|
Product.create(row.to_hash)
end
您将得到NoMethodError
,因为Product.create
希望看到属性及其值的散列,而不是包含散列的数组。你会想说:
Product.create(
:name => row['name'],
:rating => row['rating'],
:year => row['year'],
:country => row['country'],
:state_or_province => row['state_or_province']
)
当然,如果行
仅包含这五个值,则只需将整个行
交给创建
:
Product.create(row.to_hash)
如果行
包含(或可能包含)一堆您不希望创建
看到的其他内容,请使用仅获取您感兴趣的行
部分:
Product.create(row.to_hash.slice(*%w[name rating year country state_or_province]))
请注意,%w[…]
从以空格分隔的列表中构建字符串数组,因此它们是相同的:
%w[a b]
['a', 'b']
row.to_hash.slice(*%w[name rating year country state_or_province])
row.to_hash.slice('name', 'rating', 'year', 'country', 'state_or_province')
然后splat(*
)删除数组包装器,使它们相同:
%w[a b]
['a', 'b']
row.to_hash.slice(*%w[name rating year country state_or_province])
row.to_hash.slice('name', 'rating', 'year', 'country', 'state_or_province')
你可以用任何一种更容易看的形式
还要注意里面的电话。您的行
将是一个CSV::row
对象,在其上调用以_hash
将该行作为hash提供给您
这将使您的整个rake任务如下所示:
NoMethodError: undefined method `keys' for [{ ... }]:Array
CSV.foreach('filepath of my csv', :headers => true, :encoding => 'ISO-8859-1:UTF-8') do |row|
Product.create(row.to_hash)
end
或
您可能还需要为那些创建调用添加一些错误处理。谢谢!一旦我开始工作,我会把它标记为asnwer。正在尝试找出stringify_keys undefined方法错误。关于stringify_keys
,您有完整的错误吗?是产品。创建抱怨什么吗?非常感谢您的帮助。对于刚接触rails的人来说,这是一个非常用户友好的解释。再次感谢!当我用行中的每个元素替换行时,代码运行良好。完整的错误是未定义方法“stringify_keys”,对,我忘记了CSV::Row
这件事。你应该能够说row.to_hash
而不是row
来处理这个问题。我会更新我的答案。