Ruby:如何使用dump方法将数据输出到csv文件?

时间:2012-06-01 05:01:57

标签: ruby csv

我尝试使用ruby标准csv lib将对象的arr转储到csv.file,称为'a.csv'

http://ruby-doc.org/stdlib-1.9.3/libdoc/csv/rdoc/CSV.html#method-c-dump

dump(ary_of_objs, io = "", options = Hash.new)

但是在这种方法中,我如何转储到文件中? 没有这样的例子存在和帮助。我谷歌没有为我做的例子...

此外,文档说......

  

您可以提供的下一个方法是调用实例方法   csv_headers()。预计此方法将返回第二行   文档(再次作为数组),用于给每个文档   列标题。默认情况下,:: load将设置实例变量if   字段标题以@字符开头或调用send()传递   header作为方法名称,字段值作为参数。这个   method仅在Array的第一个对象上调用。

任何人都知道如何将实例方法csv_headers()传递给此转储函数?

2 个答案:

答案 0 :(得分:3)

我还没有测试过,但看起来应该将io设置为文件。根据您链接的文档“io参数可用于序列化为文件”

类似的东西:
f = File.open("filename")
dump(ary_of_objs, io = f, options = Hash.new)

答案 1 :(得分:2)

接受的答案并没有真正回答这个问题,所以我想我会给出一个有用的例子。

首先,如果您查看http://ruby-doc.org/stdlib-1.9.3/libdoc/csv/rdoc/CSV.html处的文档,如果将鼠标悬停在dump的方法名称上,则表明您可以click to show source。如果您这样做,您会看到dump方法尝试在您从csv_headers传入的第一个对象上调用ary_of_objs

obj_template = ary_of_objs.first

...snip...

headers = obj_template.csv_headers

之后您会看到该方法会在csv_dump中的每个对象上调用ary_of_objs并传入headers

ary_of_objs.each do |obj|
    begin
      csv << obj.csv_dump(headers)
    rescue NoMethodError
      csv << headers.map do |var|
        if var[0] == @
          obj.instance_variable_get(var)
        else
          obj[var[0..-2]]
        end
      end
    end
  end

因此我们需要扩充array_of_objs中的每个条目以响应这两种方法。这是一个示例包装器类,它将采用Hash,并将散列键作为CSV标头返回,然后能够根据标头转储每一行。

class CsvRowDump               
  def initialize(row_hash)     
    @row = row_hash            
  end                                                  

  def csv_headers              
    @row.keys                  
  end                          

  def csv_dump(headers)        
    headers.map { |h| @row[h] }
  end                          
end                       

还有一个问题。这个dump方法想要在标题之前在CSV文件的顶部写一个额外的行,如果由于此代码在顶部调用此方法,则无法跳过该行:

  # write meta information
  begin
    csv << obj_template.class.csv_meta
  rescue NoMethodError
    csv << [:class, obj_template.class]
  end     

即使你从CsvRowDump.csv_meta返回''仍然是一个空白行,其中一个解析器需要标题。因此,让我们让dump写下该行,然后在我们调用dump时将其删除。此示例假设您有一个哈希数组,这些哈希都具有相同的键(将是CSV标题)。

@rows = @hashes.map { |h| CsvRowDump.new(h) }
File.open(@filename, "wb") do |f|
  str = CSV::dump(@rows)
  f.write(str.split(/\n/)[1..-1].join("\n"))
end