FasterCSV default options and their usage - ruby

FasterCSV has a default options hash;
DEFAULT_OPTIONS = { :col_sep => ",",
:row_sep => :auto,
:quote_char => '"',
:converters => nil,
:unconverted_fields => nil,
:headers => false,
:return_headers => false,
:header_converters => nil,
:skip_blanks => false,
:force_quotes => false }
These options can be overridden by passing a hash to FasterCSV read and write methods. Most of them are self explanatory and easy to use but I couldn't find documentation explaining their usage. Is this information available (I haven't been able to find any credible source on the internet) I have had to resort to just trying them out to see what they do.

FasterCSV has replaced the former CSV module in the standard library and is since then renamed to 'CSV'. Have a look at the new method for the options.

Related

Ruby CSV input value format

I'm using ruby CSV module to read in a csv file.
One of the values inside the csv file is in format is XXX_XXXXX where X are number. I treat this value as string, actually, but CSV module is reading in these values as XXXXXXXX, as numbers, which I do not want.
Options I am currently using
f = CSV.read('file.csv', {:headers => true, :header_converters => :symbol, :converters => :all} )
Is there a way to tell CSV to not do that?
f = CSV.read('file.csv', {:headers => true, :header_converters => :symbol)}
Leave out the :converters => :all; that one tries (amongst others) to convert all numerical looking strings to numbers.
The :convertors => all causes this, try the following
require "csv"
CSV.parse(DATA, :col_sep => ",", :headers => true, :converters => :all).each do |row|
puts row["numfield"]
end
__END__
textfield,datetimefield,numfield
foo,2008-07-01 17:50:55.004688,123_45678
bar,2008-07-02 17:50:55.004688,234_56789
# gives
# 12345678
# 23456789
and
CSV.parse(DATA, :col_sep => ",", :headers => true).each do |row|
puts row["numfield"]
end
__END__
textfield,datetimefield,numfield
foo,2008-07-01 17:50:55.004688,123_45678
bar,2008-07-02 17:50:55.004688,234_56789
# gives
# 123_45678
# 234_56789

Create a new Ruby CSV object with headers in a single csv.new() line

I'm trying to create a new CSV object with only the header row in it, but the headers are not set until I call read():
[32] pry(main)> c = CSV.new("Keyword,Index,Page,Index in Page,Type,Title,URL", :headers => :first_row, :write_headers => true, :return_headers => true)
=> <#CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"" headers:true>
[33] pry(main)> c.headers
=> true
[34] pry(main)> c.read
=> #<CSV::Table mode:col_or_row row_count:1>
[35] pry(main)> c.headers
=> ["Keyword", "Index", "Page", "Index in Page", "Type", "Title", "URL"]
Why is that? Why can't I get a properly working CSV object with my single CSV.new line?
As the documentation will tell you it's treating the string as if it were the contents of a file (i.e. StringIO) so you still have to read the string just as you would any other IO source.
If you want to set the headers explicitly, you pass an array as the :headers parameter.
There does not appear to be a way to do this in one call but you can easily remedy that with a custom method of your own:
Given:
def new_csv(headers, data)
csv = CSV.new(data, headers: headers, write_headers: true, return_headers: true)
csv.read
csv
end
You can call use it as:
csv = new_csv("Header 1, Header 2", "abc,def")
=> <#CSV io_type:StringIO encoding:UTF-8 lineno:1 col_sep:"," row_sep:"\n" quote_char:"\"" headers:["abc", "def"]>
csv.headers
=> ["Header 1", "Header 2"]
Hope that helps.

rake import- only adding one line from csv to database

I am attempting to import a CSV file into my rails database (SQLite in Development) following this tutorial. Data is actually getting inserted into my database but it seems to only insert the first record from the CSV File. the rake seems to run without problem. and a running it with --trace reveals no additional information.
require 'csv'
desc "Import Voters from CSV File"
task :import => [:environment] do
file = "db/GOTV.csv"
CSV.foreach(file, :headers => false) do |row|
Voter.create({
:last_name => row[0],
:first_name => row[1],
:middle_name => row[2],
:name_suffix => row[3],
:primary_address => row[4],
:primary_city => row[5],
:primary_state => row[6],
:primary_zip => row[7],
:primary_zip4 => row[8],
:primary_unit => row[9],
:primary_unit_number => row[10],
:phone_number => row[11],
:phone_code => row[12],
:gender => row[13],
:party_code => row[14],
:voter_score => row[15],
:congressional_district => row[16],
:house_district => row[17],
:senate_district => row[18],
:county_name => row[19],
:voter_key => row[20],
:household_id => row[21],
:client_id => row[22],
:state_voter_id => row[23]
})
end
end
Just ran into this as well - guess you solved it some other way, but still might be useful for others.
In my case, the issue seems to be an incompatible change in the CSV library.
I guess you were using Ruby 1.8, where
CSV.foreach(path, rs = nil, &block)
The docs here are severely lacking, actually no docs at all, so have to guess from source: http://ruby-doc.org/stdlib-1.8.7/libdoc/csv/rdoc/CSV.html#method-c-foreach..
Anyway, 'rs' is clearly not an option hash, it looks like the record separator.
In Ruby 1.9 this is nicer: http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html#method-c-foreach
self.foreach(path, options = Hash.new, &block)
so this is the one that supports options such as :headers..

Transliteration with Iconv in Ruby

When I'm trying to transliterate a Cyrillic utf-8 string with
Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s
(see questions/1726404/transliteration-in-ruby)
I'm getting everything but those symbols that have to be transliterated.
For example: 'r-строка' → 'r-' and 'Gévry' → 'Gvry'.
What's wrong?
Ruby 1.8.7 / Rails 2.3.5 / WSeven
require 'iconv'
p Iconv.iconv('ascii//translit//ignore', 'utf-8', 'Gévry') #=> ["Gevry"]
# not 'ascii//ignore//translit'
For Cyrillic the translit gem might work.
It seems the solution is too tricky for me. Problem solved using stringex gem.
Another way is to create custom translit by tr and gsub methods of String without using iconv.
# encoding: UTF-8
def russian_translit(text)
translited = text.tr('абвгдеёзийклмнопрстуфхэыь', 'abvgdeezijklmnoprstufhey\'')
translited = translited.tr('АБВГДЕЁЗИЙКЛМНОПРСТУФХЭ', 'ABVGDEEZIJKLMNOPRSTUFHEY\'')
translited = translited.gsub(/[жцчшщъюяЖЦЧШЩЪЮЯ]/,
'ж' => 'zh', 'ц' => 'ts', 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sch', 'ъ' => '', 'ю' => 'ju', 'я' => 'ja',
'Ж' => 'ZH', 'Ц' => 'TS', 'Ч' => 'CH', 'Ш' => 'SH', 'Щ' => 'SCH', 'Ъ' => '', 'Ю' => 'JU', 'Я' => 'JA')
return translited
end
p russian_translit("В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!")
#=> "V chaschah juga zhil by tsitrus? Da, no fal'shivyj ekzempljar!"

fastercsv - save object table in one go (ruby)

I read my csv using the line below
data = FCSV.table("test.csv", {:quote_char => '"', :col_sep =>',', :row_sep =>:auto, :headers => true, :return_headers => false, :header_converters => :downcase, :converters => :all} )
QUESTION
Can I save object data in the same manner (one line, one go + csv options)? see above
I sort the table (see the code below) and then I want so save it again. I couldn't work out how to save the table in one go. I know how to do it row by row though.
array_of_arrays = data.to_a()
headers = array_of_arrays.shift # remove the headers
array_of_arrays.sort_by {|e| [e[3], e[4].to_s, e[1]]} .each {|line| p line }
array_of_arrays.insert(0,headers)
Anything I tried did not work and gave me something very similar to
csv.rb:33: syntax error, unexpected '{', expecting ')'
... FCSV.table("sorted.csv","w" {:quote_char => '"', :col_sep =...
NOTE:
Please note that I want to use all the CSV options when saving the file {:quote_char => '"', :col_sep =>',', :row_sep =>:auto, :headers => true, :return_headers => false, :header_converters => :downcase, :converters => :all}
Since you've got an array of arrays in data, it looks like you can just do:
FCSV::Table.new(data).to_csv
to get all the csv for data as a string, then output that back to the file.
Just following up on what dunedain said, the following will write the file out
#csv = FCSV::Table.new(data).to_csv
File.open("modified_csv.csv", 'w') {|f| f.write(#csv) }
also the error you had in the code below is because you didnt have a comma after the "w" and before the { but it looks like you were perhaps tring to the reader functions instead of the writer functions
csv.rb:33: syntax error, unexpected '{', expecting ')'
... FCSV.table("sorted.csv","w" {:quote_char => '"', :col_sep =...

Resources