How to download CSV data using ActionController::Live from MongoDB?
Asked Answered
P

2

9

I have created a CSV downloader in a controller like this

format.csv do
  @records  = Model.all

  headers['Content-Disposition'] = "attachment; filename=\"products.csv\"" 
  headers['Content-Type'] ||= 'text/csv'
end

Now I want to create server sent events to download CSV from this for optimising purpose. I know I can do this in Rails using ActionController::Live but I have have no experience with it.

Can some one explain to me how I can

  1. Query records as batches
  2. Add records to stream
  3. Handle sse from browser side
  4. Write records to CSV files

Correct me if any of my assumptions are wrong. Help me do this in a better way. Thanks.

Preempt answered 1/9, 2016 at 7:37 Comment(0)
M
0

Mongoid automatically query your records in batches (More info over here)

To add your records to a CSV file, you should do something like:

records = MyModel.all
# By default batch_size is 100, but you can modify it using .batch_size(x)

result = CSV.generate do |csv|
  csv << ["attribute1", "attribute2", ...]
  records.each do |r|
    csv << [r.attribute1, r.attribute2, ...]
  end
end

send_data result, filename: 'MyCsv.csv'

Remember that send_data is an ActionController method!

Melodymeloid answered 31/10, 2016 at 20:52 Comment(0)
S
0

I think you don´t need SSE for generating a CSV. Just include ActionController::Live into the controller to use the response.stream.write iterating your collection:

include ActionController::Live
...
def some_action
  format.csv do
    # Needed for streaming to workaround Rack 2.2 bug
    response.headers['Last-Modified'] = Time.now.httpdate

    headers['Content-Disposition'] = "attachment; filename=\"products.csv\""
    headers['Content-Type'] ||= 'text/csv'

    [1,2,3,4].each do |i|   # --> change it to iterate your DB records
      response.stream.write ['SOME', 'thing', "interesting #{i}", "#{Time.zone.now}"].to_csv

      sleep 1  # some fake delay to see chunking
    end

    ensure
      response.stream.close
    end
  end

Try it with curl or similar to see the output line by line:

$ curl -i  http://localhost:3000/test.csv
Shantung answered 4/9, 2021 at 22:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.