CSV with Ruby Newbie

Hey guys.

I am currently following an example in: “Programming Ruby: The Pragmatic
Programmers Guide” (pg. 663) on reading CSV files with Ruby. I am
struggling though to get the code to read a CSV file that has a header
in it. I have copied the example exactly but get the following error:

undefined method process' for main:Object (NoMethodError) from /usr/local/lib/ruby/1.8/csv.rb:560:ineach’
from solution.rb:4

My Code:

require ‘csv’
reader = CSV.open(“csvfile”, “r”)
header = reader.shift
reader.each{|row| process(header, row)}
CSV.open(“csvfile”, “r”) do |row|
qty = row[0].to_i
price = row[2].to_f
printf “%20s: $%5.2f %s\n”, row[1], qty*price, row[3] || " —"
end

(If your looking in the book then i have just adapted the csvfile to be
the same as csvfile_hdr)

Would really appreciate it if someone could perhaps point out what i am
doing wrong please. Thanks

Zoltar S. wrote:

undefined method process' for main:Object (NoMethodError) from /usr/local/lib/ruby/1.8/csv.rb:560:ineach’
from solution.rb:4

Does the book define a “process” function? The code below would require
you to define a function process that does whatever it is you need to do
with the header.

reader.each{|row| process(header, row)}

ex-
def process( header, row )

do something with header

do something with row

end

If process is a method of the CSV module, you’d need to prefix it with
CSV:: to get it to work.

Adam B. wrote:

Zoltar S. wrote:

undefined method process' for main:Object (NoMethodError) from /usr/local/lib/ruby/1.8/csv.rb:560:ineach’
from solution.rb:4

Does the book define a “process” function? The code below would require
you to define a function process that does whatever it is you need to do
with the header.

reader.each{|row| process(header, row)}

ex-
def process( header, row )

do something with header

do something with row

end

If process is a method of the CSV module, you’d need to prefix it with
CSV:: to get it to work.

Hmmmm no there is no definition of the function ‘process’ in the book, i
can’t see header as being a CSV module either.

The book starts simply with:

CSV…
Count, Description, Price
12,eggs,2.89,
2,“shirt, blue”,21.45,special
1,""“Hello Kitty”" bag",13.99

Ruby…

require ‘csv’

CSV.open(“csvfile”, “r”) do |row|
qty = row[0].to_i
price = row[2].to_f
printf “%20s: $%5.2f %s\n”, row[1], qty*price, row[3] || " —"
end

Output…

Description: $ 0.00 —
eggs: $34.68 —
shirt, blue: $42.90 special
“Hello Kitty” bag: $13.99 —

It then says:
“Some CSV files have a header line. Read it, and then process the rest
of the file.”

and the Ruby provided is:

require ‘csv’
reader = CSV.open(“csvfile”, “r”)
header = reader.shift
reader.each {|row| process(header, row)}

On Friday 02 November 2007 10:06 am, Zoltar S. wrote:

undefined method process' for main:Object (NoMethodError) from /usr/local/lib/ruby/1.8/csv.rb:560:ineach’
from solution.rb:4

Have you written/defined a method named “process”–it looks to me like
they
(in the book) have used “process” as sort of a generic method–something
that
doesn’t exist (and isn’t defined on that page) that you will have to
write
for yourself.

Randy K.

That example is making an assumption that you will write the ‘process’
method.

Change the 2nd CSV.open line to:
def process(header,row)

Then move the ‘process’ method to just after the ‘require’ line. That
should do it for you.

Wayne M. wrote:

That example is making an assumption that you will write the ‘process’
method.

Change the 2nd CSV.open line to:
def process(header,row)

Then move the ‘process’ method to just after the ‘require’ line. That
should do it for you.

Wayne,

Thanks alot that works.

So how would i go about displaying the headers above each row then?

So how would i go about displaying the headers above each row then?

The header variable is just an array of strings, so you can just print
header[0],header[1] and so on, but they won’t line up with the data
you’re printing from the rows. You should be able to figure out the
width of each data item.

The way it’s being printed doesn’t correspond to the headers any longer,
so you would have to make up your own headers. Something like this:

printf “%20s %7s %s\n\n”, header[1], header[2], “Is it a special”

Wayne M. wrote:

So how would i go about displaying the headers above each row then?

The header variable is just an array of strings, so you can just print
header[0],header[1] and so on, but they won’t line up with the data
you’re printing from the rows. You should be able to figure out the
width of each data item.

The way it’s being printed doesn’t correspond to the headers any longer,
so you would have to make up your own headers. Something like this:

printf “%20s %7s %s\n\n”, header[1], header[2], “Is it a special”

Ok brilliant that makes sense. Thanks alot for your help!

Pete

Zoltar S. wrote:

Hey guys.

I am currently following an example in: “Programming Ruby: The Pragmatic
Programmers Guide” (pg. 663) on reading CSV files with Ruby. I am
struggling though to get the code to read a CSV file that has a header
in it. I have copied the example exactly but get the following error:

undefined method process' for main:Object (NoMethodError) from /usr/local/lib/ruby/1.8/csv.rb:560:ineach’
from solution.rb:4

My Code:

require ‘csv’
reader = CSV.open(“csvfile”, “r”)
header = reader.shift
reader.each{|row| process(header, row)}

The book has a bad habit of calling non-existent functions in the
examples, so you have to be on the lookout for them. As a consequence,
a number of examples won’t run as presented. However the introduction
(in pickaxe2, p.5) says that you can download source code for the book
that will run, i.e. presumably the method process() will be defined in
the downloaded source.

I think the book should say something like this instead:

read.each do |row|
#process row however you see fit
end

so that beginners won’t get errors when they copy the examples verbatim.

7stud – wrote:

The book has a bad habit of calling non-existent functions

Whoops. “Methods, methods, methods.”