【问题标题】:Using Ruby CSV header converters使用 Ruby CSV 标头转换器
【发布时间】:2014-03-21 04:58:59
【问题描述】:

假设我有以下课程:

class Buyer < ActiveRecord::Base
  attr_accesible :first_name, :last_name

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

First Name,Last Name
John,Doe
Jane,Doe

我想将 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

结束

我收到了undefined method 'downcase' for nil:NilClass。如果我排除标头转换器,那么我会得到unknown attribute 'First Name'。将标头从 First Name 转换为 first_name 的正确语法是什么?

【问题讨论】:

  • 完全给出错误undefined method 'downcase',这有助于我们知道该方法是在什么对象上调用的。
  • @ArupRakshit 编辑了问题,在nil:NilClass
  • 只需在:return_headers =&gt; true 处添加一个条目。我没有测试,但希望它会工作。如果有帮助,请告诉我,我会向您解释发生的一切。
  • 谢谢,给我几分钟看看。
  • 好像是这样。将其发布为答案,以便我接受。

标签: ruby csv


【解决方案1】:

在我的桌面上进行了一些研究之后,在我看来,错误是针对其他原因的。

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

First Name,Last Name
John,Doe
Jane,Doe

现在我运行了代码,该代码保存在我的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

现在运行:

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">

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

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

First Name,Last Name,
John,Doe
Jane,Doe

现在我再次运行了保存在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)

看来,在您的标题行中,有 空白列值 导致错误。因此,如果您对源 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

【讨论】:

  • 你说得对,某处多了一个逗号,但奇怪的是,代码仍然需要你最初的:return_headers =&gt; true 建议才能工作。否则会出现undefined attribute: 错误。
  • @jcm 然后添加,但没有:return_headers =&gt; true,代码在这里按预期运行。
【解决方案2】:

一个更一般的答案,但是如果您有需要作为文本处理的代码,有时您可能会在其中得到一个 nil,然后在对象上调用 to_s。这会将 nil 变成一个空字符串。例如

h.to_s.downcase.gsub(' ', '_') 

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

【讨论】:

    【解决方案3】:

    将 :symbol 传递给 :header_converters 也会自动将字符串转换为蛇形大小写。

    options = {:headers => true, 
               :header_converters => :symbol}
    CSV.foreach(filepath, options) ...
    #<CSV::Row first_name:"John" last_name:"Doe">
    #<CSV::Row first_name:"Jane" last_name:"Doe">
    

    【讨论】:

      猜你喜欢
      • 2012-02-12
      • 2016-04-28
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      • 2014-12-24
      • 2019-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多