Using Ruby CSV header converters
Solution 1
After doing some research here in my desktop, it seems to me the error is for something else.
First I put the data in my "a.txt"
file as below :
First Name,Last Name
John,Doe
Jane,Doe
Now I ran the code, which is saved in my so.rb
file.
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
Now running the :
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">
So everything is working now. Now let me reproduce the error :
I put the data in my "a.txt"
file as below ( just added a ,
after the last column) :
First Name,Last Name,
John,Doe
Jane,Doe
Now I ran the code, which is saved in my so.rb
file, again.
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)
It seems, in your header row, there is blank column value which is causing the error. Thus if you have a control to the source CSV file, check there the same. Or do some change in your code, to handle the error as below :
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
Solution 2
A more general answer, but if you have code that you need to process as text, and sometimes you might get a nil in there, then call to_s on the object. This will turn nil into an empty string. eg
h.to_s.downcase.gsub(' ', '_')
This will never blow up, whatever h is, because every class in ruby has the to_s method, and it always returns a string (unless you've overridden it to do something else, which would be unadvisable).
jcm
Updated on July 28, 2022Comments
-
jcm almost 2 years
Say I have the following class:
class Buyer < ActiveRecord::Base attr_accesible :first_name, :last_name
and the following in a CSV file:
First Name,Last Name John,Doe Jane,Doe
I want to save the contents of the CSV into the database. I have the following in a Rake file:
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
end
I am getting an
undefined method 'downcase' for nil:NilClass
. If I exclude the header converters then I getunknown attribute 'First Name'
. What's the correct syntax for converting a header from, say,First Name
tofirst_name
? -
jcm about 10 yearsYou're right, there was an extra comma somewhere, but the strange thing is, the code still needs your initial suggestion of
:return_headers => true
to work. Otherwise it gives anundefined attribute:
error. -
Arup Rakshit about 10 years@jcm Then do add that, but without
:return_headers => true
, the code ran as expected here for me.