Ruby CSV不会在带引号的字符串中读取逗号格式的数字

时间:2015-02-03 19:01:06

标签: ruby-on-rails ruby csv

我在Rails应用程序中使用ruby的CSV类(ruby 2.1.5)来加载上传的csv文件中的记录。用户使用“另存为”从Excel创建csv文件,并且根据数字的格式,它们可能会保存为带逗号的带引号的字符串 - 在这种情况下,逗号后面的部分数字将被删除。 / p>

如果输入值为"3,500",则应保存3500,而不是3

我意识到可以在Excel中清理它,但它似乎也应该很容易处理(如果我必须告诉他们程序无法处理这个问题,我会从用户那里得到一个主要的WTF基本情况。)另外,由于csv文件的标题与数据库中的列名匹配,因此我不必编写特定于列的处理程序 - 我只是进行属性赋值。我希望保持这种方式,因为我的影响列比我在我的例子中所包含的要多得多。

输入记录:

recordid,valcurrent,valdate
11015,"3,500",6/7/2013

处理功能

def import_csv(file)
  CSV.foreach(file.path, headers: true, header_converters: :symbol, skip_blanks: true, converters: :all) do |row|
    # hash the input row 
    row_hash = row.to_hash
    # create a new row with the hash in original_record
    fl = self.forecast_lines.create(original_record: row_hash.to_s)
    # write the hash to the record attributes
    fl.attributes = row_hash
    fl.save
  end
end

原始记录哈希:

Original record: {:recordid=>"11015", :valcurrent=>"3,500", :valdate=>"6/7/2013"} 

valcurrent的数据类型是float。但是保存到数据库的valcurrent值不是3500.0,而是3.0

2 个答案:

答案 0 :(得分:4)

您可以添加正确处理数字列的自定义转换器。不确定这是否涵盖了所有可能的格式选项,但它看起来像这样:

创建一个lambda:

comma_numbers = ->(s) {(s =~ /^\d+,/) ? (s.gsub(',','').to_f) : s}

将其添加到您的转换器:

CSV::Converters[:comma_numbers] = comma_numbers

新的转换器不包含在转换器中:所有都将它添加为数组:

converters: [:all, :comma_numbers]

答案 1 :(得分:3)

问题不在于CSV,而是Ruby如何将字符串转换为浮点数。

在Ruby中:

"3,500".to_f => 3.0

这就是3.0存储在数据库中的原因。您应该更改import_csv方法以处理逗号。

另外我认为你不应该在create中做row_hash.to_s。这样创建方法接受哈希作为参数。