Reputation: 25348
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
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
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