Synthesis : Scott Becker

How to generate CSV files in Rails

A while back someone posted on rubyonrails-talk asking how to export to CSV from Rails. I posted a solution, and people seemed to dig it, so I’ll share it again here.

Use FasterCSV

Get the FasterCSV gem. Why? It’s faster, and easier to use. Once you’ve got it, require it in environment.rb. Here’s an abbreviated version of my working controller method. Copy/paste/modify. And you’re done!

def export_to_csv 
  @users = User.find(:all) 
  csv_string = FasterCSV.generate do |csv| 
    # header row 
    csv << ["id", "first_name", "last_name"] 

    # data rows 
    @users.each do |user| 
      csv << [user.id, user.first_name, user.last_name] 
    end 
  end 

  # send it to the browsah
  send_data csv_string, 
            :type => 'text/csv; charset=iso-8859-1; header=present', 
            :disposition => "attachment; filename=users.csv" 
end

HTML or CSV, have it your way

Now, if we wanted to get all clever about it, we could go further and serve both html and CSV data with only one action, using respond_to. This also requires that you add a RESTful route (map.resources :users) to your routes.rb file:

def index 
  @users = User.find(:all) 
  respond_to do |wants| 
    wants.html 
    wants.csv do 
      csv_string = FasterCSV.generate do |csv| 
        # header row 
        csv << ["id", "first_name", "last_name"] 
        # data rows 
        @users.each do |user| 
          csv << [user.id, user.first_name, user.last_name] 
        end 
      end 
      # send it to the browsah
      send_data csv_string, 
                :type => 'text/csv; charset=iso-8859-1; header=present', 
                :disposition => "attachment; filename=users.csv" 
    end 
  end 
end

Now if the user requests:

/users

she’ll get HTML. If she requests:

/users.csv

You get the point.

 

Comments are closed.