Jim Wharton
Jim Wharton

Reputation: 1415

Rails 3.1 active record query to an array of arrays for CSV export via FastCSV

I'm attempting to DRY up a method I've been using for a few months:

def export(imagery_requests)
  csv_string = FasterCSV.generate do |csv|    
    imagery_requests.each do |ir|
      csv << [ir.id, ir.service_name, ir.description, ir.first_name, ir.last_name, ir.email,
        ir.phone_contact, ir.region, ir.imagery_type, ir.file_type, ir.pixel_type,
        ir.total_images, ir.tile_size, ir.progress, ir.expected_date, ir.high_priority,
        ir.priority_justification, ir.raw_data_location, ir.service_overviews,
        ir.is_def, ir.isc_def, ir.special_instructions, ir.navigational_path,
        ir.fyqueue, ir.created_at, ir.updated_at]
    end
  end
  # send it to the browser with proper headers
  send_data csv_string,
    :type => 'text/csv; charset=iso-8859-1; header=present',
    :disposition => "attachment; filename=requests_as_of-#{Time.now.strftime("%Y%m%d")}.csv"
end

I figured it would be a LOT better if instead of specifying EVERY column manually, I did something like this:

def export(imagery_requests)
  csv_string = FasterCSV.generate do |csv|
    line = []
    imagery_requests.each do |ir|
      csv << ir.attributes.values.each do |i|
        line << i
      end      
    end
  end
  # send it to the browser with proper headers
  send_data csv_string,
    :type => 'text/csv; charset=iso-8859-1; header=present',
    :disposition => "attachment; filename=requests_as_of-#{Time.now.strftime("%Y%m%d")}.csv"
end

That should be creating an array of arrays. It works just fine in the Rails console. But in the production environment, it just produces garbage output. I'd much rather make this method extensible so I can add more fields to the ImageryRequest model at a later time. Am I going about this all wrong?

Upvotes: 0

Views: 735

Answers (1)

Taryn East
Taryn East

Reputation: 27747

I'm guessing that it probably works in the console when you do it for just one imagery_request, yes? But when you do multiple it fails?

Again I'm guessing that's because you never reset line to be an empty array again. So you're continually filling a single array.

Try the simple way first, to check it works, then start going all << on it then:

csv_string = FasterCSV.generate do |csv|
  imagery_requests.each do |ir|
    csv << ir.attributes.values.clone
  end
end

PS - in the past I've even used clone on my line-by-line array, just to be sure I wasn't doing anything untoward with persisted stuff...

Upvotes: 3

Related Questions