4

Edit: I don't need to use the same file. A new file can be created. What I do need is the result to contain the same columns and rows as in the original plus the new columns, but in the same order.

I've been trying to append columns to an existing CSV file with Ruby but I'm getting an error that I don't understand it. Here's my code:

CSV.foreach("test.csv", "a+") do | row |
c = Curl::Easy.perform("http://maps.googleapis.com/maps/api/geocode/json?latlng=#{row[1]},#{row[0]}&sensor=false")
result = JSON.parse(c.body_str)
if result['status'] != 'OK'
    sleep(5)
else
    row << result['results'][0]['formatted_address']
    result['results'][0]['address_components'].each do | w |
        row << w['short_name']
    end
end

end

On the CSV.foreach... part I've tried CSV.foreach('file.csv', 'a+'), CSV.foreach('file.csv', 'wb'), CSV.foreach('file.csv', 'a') and nothing seemed to work.

Then it dawned on me that maybe I should be using open instead:

        file = CSV.open('test.csv', 'wb')
    file.each do | csv |
        c = Curl::Easy.perform("http://maps.googleapis.com/maps/api/geocode/json?latlng=#{row[1]},#{row[0]}&sensor=false")
        result = JSON.parse(c.body_str)
        if result['status'] != 'OK'
            sleep(5)
        else
            row << result['results'][0]['formatted_address']
            result['results'][0]['address_components'].each do | w |
                row << w['short_name']
            end
        end
    end

But that didn't work either.

What am I missing? Thanks!

WagnerMatosUK
  • 4,309
  • 7
  • 56
  • 95
  • `row` is an internal representation read from the CSV file. The modification to it won't affect the original CSV source. You need to open another CSV file for write, and write the row to that file after modification. Is this what you're missing? – Arie Xiao Jul 07 '15 at 15:34
  • I thought there would be a way to modify the current document though. On the docs it seems that's the case but I couldn't figure it out for sure... – WagnerMatosUK Jul 07 '15 at 15:42
  • Editing files in place seems to be already covered in http://stackoverflow.com/questions/5452781 and http://stackoverflow.com/questions/4397412 with a couple of good answers. – Synoli Jul 07 '15 at 21:01
  • possible duplicate of [Edit each line in a file in Ruby](http://stackoverflow.com/questions/5452781/edit-each-line-in-a-file-in-ruby) – Synoli Jul 07 '15 at 21:04
  • But both answers address editing a file rather than a CSV. I'm using the CSV class, wouldn't it be different approach? – WagnerMatosUK Jul 08 '15 at 08:02
  • Other point is that I don't need to use the same file. I can create another file, but it got to be based off the initial file but with the new columns appended. – WagnerMatosUK Jul 08 '15 at 08:24
  • Oh I see! In that case, please disregard my comment. – Synoli Jul 08 '15 at 09:54

1 Answers1

1

Why don't you try opening the file with a different mode?

Looks like this is what you are looking for:

CSV.open('test.csv', 'r+') do |row|
  row << ['existing_header1','existing_header2','new_header']
end

This will in fact overwrite your first line for the one you just specified. It works because 'r+' reads from the beginning of the file, and overwrites any existing rows as it goes through the file. But in this case you just need to change the first one :)

Here's a list of useful modes you can use to open a file. Cheers.

"r" -- read only from the beginning of the file

"r+" -- read/write from the beginning of the file

"w" -- write only, overwriting the entire existing file or creating a new one if none existed

"w+" -- read/write, overwriting the entire existing file or creating a new one if none existed

"a" -- write only, starting at the end of existing file or creating a new one if none existed

"a+" -- read/write, starting at the end of existing file or creating a new one if none existed

Source: Opening modes

Community
  • 1
  • 1
David Meza
  • 3,080
  • 3
  • 16
  • 18