How to convert array of ActiveRecord models to CSV? How to convert array of ActiveRecord models to CSV? ruby ruby

How to convert array of ActiveRecord models to CSV?


The following will write the attributes of all users to a file:

CSV.open("path/to/file.csv", "wb") do |csv|  csv << User.attribute_names  User.find_each do |user|    csv << user.attributes.values  endend

Similarly you could create a CSV string:

csv_string = CSV.generate do |csv|  csv << User.attribute_names  User.find_each do |user|    csv << user.attributes.values  endend


@rudolph9's answer is really awesome. I just want to leave a note for people who need to do this task periodically: making it as a rake task would be a good idea!

lib/tasks/users_to_csv.rake

# usage:# rake csv:users:all => export all users to ./user.csv# rake csv:users:range start=1757 offset=1957 => export users whose id are between 1757 and 1957# rake csv:users:last number=3   => export last 3 usersrequire 'csv' # according to your settings, you may or may not need this linenamespace :csv do  namespace :users do    desc "export all users to a csv file"    task :all => :environment do      export_to_csv User.all    end    desc "export users whose id are within a range to a csv file"    task :range => :environment do |task, args|      export_to_csv User.where("id >= ? and id < ?", ENV['start'], ENV['offset'])    end    desc "export last #number users to a csv file"    task :last => :environment do |task, arg|      export_to_csv User.last(ENV['number'].to_i)    end    def export_to_csv(users)      CSV.open("./user.csv", "wb") do |csv|        csv << User.attribute_names        users.each do |user|          csv << user.attributes.values        end      end    end  endend


This might be off the original question but solve the problem. If you plan to make all or some of your Active Record models be able to convert to csv, you can use ActiveRecord concern. An example is shown below

module Csvable  extend ActiveSupport::Concern   class_methods do    def to_csv(*attributes)      CSV.generate(headers: true) do |csv|         csv << attributes         all.each do |record|           csv << attributes.map { |attr| record.send(attr) }        end       end    end  endend

The attribute provided will be used as the header for the CSV and it is expected that this attribute corresponds to methods name in the included class. Then you can include it in any ActiveRecord class of your choice, in this case, the User class

class User   include Csvable end

Usage

User.where(id: [1, 2, 4]).to_csv(:id, :name, :age)

Note: This only works for ActiveRecord relation and not for arrays