使用Ruby CSV标头转换器

jcm*_*jcm 8 ruby csv

说我有以下课程:

class Buyer < ActiveRecord::Base
  attr_accesible :first_name, :last_name
Run Code Online (Sandbox Code Playgroud)

以及CSV文件中的以下内容:

First Name,Last Name
John,Doe
Jane,Doe
Run Code Online (Sandbox Code Playgroud)

我想将CSV的内容保存到数据库中.我在Rake文件中有以下内容:

namespace :migration do
  desc "Migrate CSV data"
  task :import, [:model, :file_path] => :environment do |t, args|
    require 'csv'

    model = args.model.constantize
    path = args.file_path
    CSV.foreach(path, :headers => true,
                      :converters => :all,
                      :header_converters => lambda { |h| h.downcase.gsub(' ', '_') }
                      ) do |row|
    model.create!(row.to_hash)
  end
end
Run Code Online (Sandbox Code Playgroud)

结束

我得到了一个undefined method 'downcase' for nil:NilClass.如果我排除标题转换器,那么我得到unknown attribute 'First Name'.什么是对,比如说,从转换头的正确语法First Namefirst_name

Aru*_*hit 19

在我的桌面上做了​​一些研究后,在我看来错误是其他的东西.

首先,我将数据放在我的"a.txt"文件中,如下所示:

First Name,Last Name
John,Doe
Jane,Doe
Run Code Online (Sandbox Code Playgroud)

现在我运行了代码,该代码保存在我的so.rb文件中.

so.rb

require 'csv'

CSV.foreach("C:\\Users\\arup\\a.txt", 
             :headers => true,
             :converters => :all,
             :header_converters => lambda { |h| h.downcase.gsub(' ', '_') }
           ) do |row|
    p row
end
Run Code Online (Sandbox Code Playgroud)

现在运行:

C:\Users\arup>ruby -v so.rb
ruby 1.9.3p448 (2013-06-27) [i386-mingw32]
#<CSV::Row "first_name":"John" "last_name":"Doe">
#<CSV::Row "first_name":"Jane" "last_name":"Doe">
Run Code Online (Sandbox Code Playgroud)

所以现在一切正常.现在让我重现错误:

我把数据放在我的"a.txt"文件中如下(只是,在最后一列之后添加了一个):

First Name,Last Name,
John,Doe
Jane,Doe
Run Code Online (Sandbox Code Playgroud)

现在我so.rb再次运行保存在我的文件中的代码.

C:\Users\arup>ruby -v so.rb
ruby 1.9.3p448 (2013-06-27) [i386-mingw32]
so.rb:5:in `block in <main>': undefined method `downcase' for nil:NilClass (NoMethodError)
Run Code Online (Sandbox Code Playgroud)

看来,在标题行中,存在导致错误的空白列值.因此,如果您对源CSV文件具有控制权,请检查相同的内容.或者对代码进行一些更改,以处理错误,如下所示:

require 'csv'

CSV.foreach("C:\\Users\\arup\\a.txt",
             :headers => true,
             :converters => :all,
             :header_converters => lambda { |h| h.downcase.gsub(' ', '_') unless h.nil? }
           ) do |row|
    p row
end
Run Code Online (Sandbox Code Playgroud)


Max*_*ams 8

一个更一般的答案,但如果你有需要作为文本处理的代码,有时你可能会在那里得到一个nil,那么在对象上调用to_s.这将把nil变为空字符串.例如

h.to_s.downcase.gsub(' ', '_') 
Run Code Online (Sandbox Code Playgroud)

无论h是什么,这都不会爆炸,因为ruby中的每个类都有to_s方法,并且它总是返回一个字符串(除非你重写它以做其他事情,这是不可取的).