DEV Community

Cover image for Export Records to CSV Files with Rails

Export Records to CSV Files with Rails

Victor Hazbun on June 22, 2019

Learn how to export records into CSV files using Ruby on Rails. Here are the steps. Steps: Add a controller and make sure you handle t...
Collapse
 
haroldus profile image
haroldus-

How about doing this as a concern instead?

# models/concerns/generate_csv.rb
module GenerateCSV
  extend ActiveSupport::Concern

  class_methods do
    def generate_csv
      CSV.generate(headers: true) do |csv|
        csv << self.attribute_names

        all.each do |record|
          csv << record.attributes.values
        end
      end
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Then

# models/user.rb
class User
  include GenerateCSV
end
Enter fullscreen mode Exit fullscreen mode

or

# models/whatever.rb
class Whatever
 include GenerateCSV
end
Enter fullscreen mode Exit fullscreen mode
Collapse
 
countalucard2022 profile image
countalucard2022

Great for DRY approach, thanks for this :)

Collapse
 
tomk32 profile image
Thomas R. Koll • Edited

Nitpicking if I may, a missing last or first name won't be noticed in HTML but it will be noticed in CSV when a human reads it directly or imported in Excel/LibreCalc.

def name
  [first_name, last_name].compact.join(' ')
end
Collapse
 
nuno101 profile image
Nuno

Nice, but there's a mistake in the controller/ model. The code appears to work because @users=User.all which matches the set of users computed within the model class

The correct call would be User.to_csv(@users). The User model function has to be modified to take the new parameter into account.

Collapse
 
victorhazbun profile image
Victor Hazbun

nope, it's right the way it is. Since @users is an ActiveRecord::Relation so you can say @users.to_csv

Collapse
 
von_christian profile image
Von Christian

How to run it in background job(Sidekiq) ?

Collapse
 
victorhazbun profile image
Victor Hazbun

It depends, are you going to send an email on a background job? or are you going to upload the file on S3? please give some context.

Collapse
 
von_christian profile image
Von Christian

from my experience, when large amounts of data is involved, the server times out. Im thinking if it is possible to move the CSV export and show a download link to the user?

Thread Thread
 
victorhazbun profile image
Victor Hazbun

Ok, then you will need to do the following:

  1. On a BG job generate the CSV file
  2. Upload the file to AWS S3
  3. Save the URL in the DB
  4. Expose the URL in the front-end
Collapse
 
victorhazbun profile image
Victor Hazbun

UPDATE: I was using #each, I changed it to#find_each which saves memory. See api.rubyonrails.org/classes/Active...

Collapse
 
countalucard2022 profile image
countalucard2022

But this will not be a report friendly, find_each forces the sequence to be order by id desc :( thanks to the postoverall!