Ruby 在 Rails - 从不常见格式的 CSV 导入数据
Ruby on Rails - Import Data from uncommon formatted CSV
我有以下格式的 CSV 文件;
Category-1-GUID,Product1
,Product2
,Product3
Category-2-GUID,Product4
,Product5
任务应将以下数据写入模型:
Category-1-GUID,Product1
Category-1-GUID,Product2
Category-1-GUID,Product3
Category-2-GUID,Product4
Category-2-GUID,Product5
我发现 Ruby on Rails - Import Data from a CSV file 对导入数据非常有用,但是这个小差异让我变成了一个笨蛋....
提前致谢!最好的问候
-- 编辑 1:import_productdata.rake 文件:--
desc "Import Product with Category-GUID"
task :import_productdata do
require 'csv'
rows = CSV.read('tmp/export1.csv')
category_id = nil
items = rows.map do |row|
category_id = row[0] unless row[0].nil?
[category_id, row[1]]
end
csv = CSV.parse(items, :headers => false)
csv.each do |row|
Product.create!(row.to_hash)
end
end
错误:
** Invoke import_productdata (first_time)
** Execute import_productdata
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1326:in `ensure in parse': CSV#close at /Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/forwardable.rb:156 forwarding to private method Array#close
rake aborted!
NoMethodError: undefined method `close' for #<Array:0x007fd69f43c3d0>
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/forwardable.rb:226:in `close'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1326:in `ensure in parse'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1326:in `parse'
/Users/bn/Documents/RubyApps/TestApp/lib/tasks/import_productdata.rake:13:in `block in <top (required)>'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `block in execute'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `each'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `execute'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:213:in `block in invoke_with_call_chain'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/monitor.rb:214:in `mon_synchronize'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:193:in `invoke_with_call_chain'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:182:in `invoke'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:160:in `invoke_task'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `each'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block in top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:125:in `run_with_threads'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:110:in `top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:83:in `block in run'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:80:in `run'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/exe/rake:27:in `<top (required)>'
/Users/bn/.rvm/gems/ruby-2.4.0/bin/rake:23:in `load'
/Users/bn/.rvm/gems/ruby-2.4.0/bin/rake:23:in `<main>'
Caused by:
NoMethodError: private method `gets' called for #<Array:0x007fd69f43c3d0>
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1830:in `block in shift'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1828:in `loop'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1828:in `shift'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1770:in `each'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1784:in `to_a'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1784:in `read'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1324:in `parse'
/Users/bn/Documents/RubyApps/TestApp/lib/tasks/import_productdata.rake:13:in `block in <top (required)>'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `block in execute'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `each'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `execute'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:213:in `block in invoke_with_call_chain'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/monitor.rb:214:in `mon_synchronize'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:193:in `invoke_with_call_chain'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:182:in `invoke'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:160:in `invoke_task'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `each'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block in top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:125:in `run_with_threads'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:110:in `top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:83:in `block in run'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:80:in `run'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/exe/rake:27:in `<top (required)>'
/Users/bn/.rvm/gems/ruby-2.4.0/bin/rake:23:in `load'
/Users/bn/.rvm/gems/ruby-2.4.0/bin/rake:23:in `<main>'
Tasks: TOP => import_productdata
如果你只调用 CSV.read
那么,
rows = CSV.read('test.csv')
输出为
[["Category-1-GUID", "Product1"], [nil, "Product2"], [nil, "Product3"], ["Category-2-GUID", "Product4"], [nil, "Product5"]]
因此只需将类别 ID 放入 category_id、product_id 对数组。
require 'csv'
rows = CSV.read('test.csv')
category_id = nil
items = rows.map do |row|
category_id = row[0] unless row[0].nil?
[category_id, row[1]]
end
p items # [["Category-1-GUID", "Product1"], ["Category-1-GUID", "Product2"], ["Category-1-GUID", "Product3"], ["Category-2-GUID", "Product4"], ["Category-2-GUID", "Product5"]]
我有以下格式的 CSV 文件;
Category-1-GUID,Product1
,Product2
,Product3
Category-2-GUID,Product4
,Product5
任务应将以下数据写入模型:
Category-1-GUID,Product1
Category-1-GUID,Product2
Category-1-GUID,Product3
Category-2-GUID,Product4
Category-2-GUID,Product5
我发现 Ruby on Rails - Import Data from a CSV file 对导入数据非常有用,但是这个小差异让我变成了一个笨蛋....
提前致谢!最好的问候
-- 编辑 1:import_productdata.rake 文件:--
desc "Import Product with Category-GUID"
task :import_productdata do
require 'csv'
rows = CSV.read('tmp/export1.csv')
category_id = nil
items = rows.map do |row|
category_id = row[0] unless row[0].nil?
[category_id, row[1]]
end
csv = CSV.parse(items, :headers => false)
csv.each do |row|
Product.create!(row.to_hash)
end
end
错误:
** Invoke import_productdata (first_time)
** Execute import_productdata
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1326:in `ensure in parse': CSV#close at /Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/forwardable.rb:156 forwarding to private method Array#close
rake aborted!
NoMethodError: undefined method `close' for #<Array:0x007fd69f43c3d0>
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/forwardable.rb:226:in `close'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1326:in `ensure in parse'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1326:in `parse'
/Users/bn/Documents/RubyApps/TestApp/lib/tasks/import_productdata.rake:13:in `block in <top (required)>'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `block in execute'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `each'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `execute'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:213:in `block in invoke_with_call_chain'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/monitor.rb:214:in `mon_synchronize'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:193:in `invoke_with_call_chain'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:182:in `invoke'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:160:in `invoke_task'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `each'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block in top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:125:in `run_with_threads'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:110:in `top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:83:in `block in run'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:80:in `run'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/exe/rake:27:in `<top (required)>'
/Users/bn/.rvm/gems/ruby-2.4.0/bin/rake:23:in `load'
/Users/bn/.rvm/gems/ruby-2.4.0/bin/rake:23:in `<main>'
Caused by:
NoMethodError: private method `gets' called for #<Array:0x007fd69f43c3d0>
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1830:in `block in shift'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1828:in `loop'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1828:in `shift'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1770:in `each'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1784:in `to_a'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1784:in `read'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1324:in `parse'
/Users/bn/Documents/RubyApps/TestApp/lib/tasks/import_productdata.rake:13:in `block in <top (required)>'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `block in execute'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `each'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `execute'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:213:in `block in invoke_with_call_chain'
/Users/bn/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/monitor.rb:214:in `mon_synchronize'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:193:in `invoke_with_call_chain'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/task.rb:182:in `invoke'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:160:in `invoke_task'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `each'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block in top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:125:in `run_with_threads'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:110:in `top_level'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:83:in `block in run'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/lib/rake/application.rb:80:in `run'
/Users/bn/.rvm/gems/ruby-2.4.0/gems/rake-12.3.1/exe/rake:27:in `<top (required)>'
/Users/bn/.rvm/gems/ruby-2.4.0/bin/rake:23:in `load'
/Users/bn/.rvm/gems/ruby-2.4.0/bin/rake:23:in `<main>'
Tasks: TOP => import_productdata
如果你只调用 CSV.read
那么,
rows = CSV.read('test.csv')
输出为
[["Category-1-GUID", "Product1"], [nil, "Product2"], [nil, "Product3"], ["Category-2-GUID", "Product4"], [nil, "Product5"]]
因此只需将类别 ID 放入 category_id、product_id 对数组。
require 'csv'
rows = CSV.read('test.csv')
category_id = nil
items = rows.map do |row|
category_id = row[0] unless row[0].nil?
[category_id, row[1]]
end
p items # [["Category-1-GUID", "Product1"], ["Category-1-GUID", "Product2"], ["Category-1-GUID", "Product3"], ["Category-2-GUID", "Product4"], ["Category-2-GUID", "Product5"]]