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:in `each'
        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

···

--
Posted via http://www.ruby-forum.com/.

Zoltar Speaks wrote:

undefined method `process' for main:Object (NoMethodError)
        from /usr/local/lib/ruby/1.8/csv.rb:560:in `each'
        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.

···

--
Posted via http://www.ruby-forum.com/\.

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.

···

--
Posted via http://www.ruby-forum.com/.

undefined method `process' for main:Object (NoMethodError)
        from /usr/local/lib/ruby/1.8/csv.rb:560:in `each'
        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 Kramer

···

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

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

Zoltar Speaks 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:in `each'
        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.

···

--
Posted via http://www.ruby-forum.com/\.

Adam Boyle wrote:

Zoltar Speaks wrote:

undefined method `process' for main:Object (NoMethodError)
        from /usr/local/lib/ruby/1.8/csv.rb:560:in `each'
        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)}

···

--
Posted via http://www.ruby-forum.com/\.

Wayne Magor 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?

···

--
Posted via http://www.ruby-forum.com/\.

7stud -- wrote:

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

Whoops. "Methods, methods, methods."

···

--
Posted via http://www.ruby-forum.com/\.

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"

···

--
Posted via http://www.ruby-forum.com/\.

Wayne Magor 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

···

--
Posted via http://www.ruby-forum.com/\.