0

Initially I have am empty csv file on my computer. I start with this piece of code:

     CSV.open("GreenTea.csv", "wb") do |csv|
      csv << ["ObjectID", "PropertyID", "PropertyValue", "SourceID"]
    end 

This does its job right and writes this into the file. Later on I made a struct and would like to convert it into csv so I did this:

....

  current = info.new
  current.ObjectID = text[0] #Green tea
  current.PropertyID = nil #Relation
  current.PropertyValue = text[1] #description of antioxidant
  current.SourceID = a['href'] #source extracted by clubweb

  CSV.open("GreenTea.csv", "wb") do |csv|
        csv << [current.ObjectID, current.PropertyID, current.PropertyValue, current.SourceID]
    end 
end

However when I check the file again, I only see this: enter image description here

It seems like the info is being overwritten by the very last info in the loop! How can i prevent this? i want to keep adding into the file not overwrite.

Sarah cartenz
  • 1,313
  • 2
  • 14
  • 37

4 Answers4

4

You are opening the CSV with the wrong flags.

"r" flag opens the file in read-only mode.

When you want to write to a file, you need to open it using the w (write) mode, or a (write append).

CSV.open("GreenTea.csv", "ab") do |csv|
   csv << [current.ObjectID, current.PropertyID, current.PropertyValue, current.SourceID]
end

Ruby allows the following open modes:

  • "r" Read-only, starts at beginning of file (default mode).
  • "r+" Read-write, starts at beginning of file.
  • "w" Write-only, truncates existing file to zero length or creates a new file for writing.
  • "w+" Read-write, truncates existing file to zero length or creates a new file for reading and writing.
  • "a" Write-only, each write call appends data at end of file. Creates a new file for writing if file does not exist.
  • "a+" Read-write, each write call appends data at end of file. Creates a new file for reading and writing if file does not exist.
Mihai Dinculescu
  • 19,743
  • 8
  • 55
  • 70
1

have a try:

CSV.open("GreenTea.csv", "a+") do |csv|
....

a+: Preserves file content by writing to the end of the file, if file is not exists, it will create a new file.

pangpang
  • 8,581
  • 11
  • 60
  • 96
1

Though both already presented answers do their job, I would go with different approach. Instead of reopening a csv file a dozillion number of times, surround the whole execution with csv handling. Instead of (pseudocode):

my_table.each do |row| 
  CSV.open('file.csv', 'a+') do |csv|
    puts ...
  end
end

use:

CSV.open('file.csv', 'w') do |csv|
  csv << ["ObjectID", "PropertyID", "PropertyValue", "SourceID"]
  my_table.each do |row| 
    csv << ...
  end
end
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
1

You can follow the following code example for generate csv, if you are using an rails application. when you browse this controller action it will download the csv file with data.

In application.rb require csv

require 'csv'

In controller action call send data and file name for generate csv file

class ExampleController < ApplicationController
 def example_action
   respond_to do |format|
      format.csv { send_data ExampleModel.to_csv, :filename => "example.csv" }
   end
 end
end

In model to_csv generate csv rows

class ExampleModel < ActiveRecord::Base
   def self.to_csv
     CSV.generate do |csv|
        csv << ["Headers"]
        csv << ["attributes"]
     end
   end
end
Rokibul Hasan
  • 4,078
  • 2
  • 19
  • 30