Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you use Ruby CSV converters?

Tags:

ruby

csv

Suppose you have the following file:

textfield,datetimefield,numfield
foo,2008-07-01 17:50:55.004688,1
bar,2008-07-02 17:50:55.004688,2

The Ruby code to read a .csv is something like:

#!/usr/bin/env ruby

require 'csv'

csv = CSV($stdin, :headers => true, :converters => :all)
csv.each do |row|
  print "#{row}"
  the_date = row['datetimefield'].to_date
end

That code gives this error message:

./foo2.rb:8:in `block in <main>': undefined method `to_date' for "2008-07-01 17:50:55.004688":String (NoMethodError)

What gives?

I've read the docs, but I don't get it.

Edit: Yes, I could parse the fields individually. The point of this question is that I want to learn how to use the documented converters feature.

like image 457
dfrankow Avatar asked Jan 18 '12 00:01

dfrankow


People also ask

How do I create a CSV file in rails?

First, set up the application and seed in some data. Now, in post. rb , declare a method which will be responsible for generating data in CSV format. Depending upon your Rails version and the dependencies added, it's possible you'll need to add a require statement.


1 Answers

You are asking how to use converters.

My example defines the usage of a new converter mytime. The converter my_time tries to build a time object if possible.

#Define test data
src = <<csv
textfield,datetimefield,numfield
foo,2008-07-01 17:50:55.004688,1
bar,2008-07-02 17:50:55.004688,2
csv

require 'csv'
require 'time'
CSV::Converters[:mytime] = lambda{|s| 
  begin 
    Time.parse(s)
  rescue ArgumentError
    s
  end
}

csv = CSV(src, :headers => true, :converters => [:mytime])
csv.each do |row|
  print "#{row}"
  the_date = row['datetimefield'].to_date
end

Using this technique, you may also define a converter to create a date from time-like strings. This solution also keeps all other converters.

#define test data
src = <<csv
textfield,datetimefield,numfield
foo,2008-07-01 17:50:55.004688,1
bar,2008-07-02 17:50:55.004688,2
csv

require 'csv'
require 'time'
CSV::Converters[:time2date] = lambda{|s| 
  begin 
    Time.parse(s).to_date
  rescue ArgumentError
    s
  end
}

csv = CSV(src, :headers => true, :converters => CSV::Converters.keys + [:time2date])
csv.each do |row|
  print "#{row}"
  p row['datetimefield'] #Date-field
end
like image 103
knut Avatar answered Nov 14 '22 08:11

knut