Shpigford
Shpigford

Reputation: 25348

How to generate a CSV file in a background task?

We allow users to download all of their data in CSV format, but we're finding that for a lot of users (who have a lot of data) we really need to generate the CSV file in the background and then provide them a link to download it later.

I know how to generate a CSV file on the fly in the view, but I'm not totally clear on the best way to generate it in a background task.

I'm currently using csv_builder to generate CSV files in the view...so it'd be awesome to be able to still use that and just somehow output that directly into a CSV file that I can then upload to S3 using paperclip...but that might be too far-fetched.

Upvotes: 3

Views: 5203

Answers (2)

Asad Hameed
Asad Hameed

Reputation: 59

You can make a database table where you can save the file after its made in the background. I can show you the rails migration.

  create_table "csv_table", force: :cascade do |t|
    t.binary "csv_file"
    t.string "file_name"
  end

After creating this You can save your csv file here. You can save your file into binary by using

csv_converted_file = Base64.encode64(csv)

Here csv is the data.

Now, if you want to download your csv in background. You can download this by using this coffee script. You will make an ajax request to get the data of csv you just saved in your csv table.

   $.ajax
    type: 'GET'
    dataType: "text"
    url: url
    success: (data) ->
      blob = new Blob([data], { type: "text/csv" })
      file_name_url = new URL(window.location.href)
      file_name = file_name_url.searchParams.get("file_name");
      url = window.URL.createObjectURL(blob)
      a = document.createElement('a')
      a.setAttribute('hidden', '')
      a.setAttribute('href', url)
      a.setAttribute('download', file_name)
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
  return

By this, Your csv will be downloaded on desired page load.

Upvotes: 0

sbauch
sbauch

Reputation: 830

I had a similar problem, but used the built in rails CSV library rather than csv_builder (which I know nothing about).

in my model I have a method for generating a csv and saving as paerclip attachment on s3:

def csv_export
  @entries = self.entries    
  @filename = "naming my file"    
  CSV.open("#{Rails.root.to_s}/tmp/#{@filename}", "wb") do |csv| #creates a tempfile csv
    csv << ["Date & Time", "Name", "Email"] #creates the header
    @entries.each do |e|            
      csv << [e.created_at, e.name, e.email] #create new line for each item in collection
    end
end

self.update_attribute(:csv_report, File.open("#{Rails.root.to_s}/tmp/#{@filename}"))
  #saves tempfile as paperclip attachment
end

I invoke this method in a rake task that offloads to a delayed job worker.

So in the rake task: Object.delay.csv_export

Upvotes: 5

Related Questions