Dynamically generated CSV files

Greetings, I have a method from which I want to generate CSV files based
on the model name:

def export_table_to_csv(table)

require ‘csv’

@table = table
@results = @table.find(:all)
@titles = @table.column_names

report = StringIO.new
CSV::Writer.generate(report, ‘,’) do |title|
title << @titles
@results.each do |result|
title << result.attributes.values
end
end

report.rewind
file = File.open("#{RAILS_ROOT}/the_directory/#{@table}.csv", “wb”)
file.write(report.read)

end

The above script works fine right now, however the call to
result.attributes.values returns them in a different order than
@table.column_names, so that the values end up in the wrong places. ie.
the name will be under the email column etc.

any thoughts on how I can make it spit out in the order it’s in from the
database?

Cheers,

Jason

Jason P. wrote:

file.write(report.read)

end

The above script works fine right now, however the call to
result.attributes.values returns them in a different order than
@table.column_names, so that the values end up in the wrong places. ie.
the name will be under the email column etc.

any thoughts on how I can make it spit out in the order it’s in from the
database?

Replace title << result.attributes.values with

title << @titles.map { |a| result.send(a) }


Rails Wheels - Find Plugins, List & Sell Plugins -
http://railswheels.com

title << @titles.map { |a| result.send(a) }

thanks! That’s working great. Would you care to explain for me how
that works? When I read the code, I think this:

@titles.map iterates over each item in the titles array, so if I were
just to do:

@titles = [1, 4, 6, 8]
@titles.map { |a| a + 2 }
=> [3, 6, 8, 10]

So if I have that correct, I don’t understand how the send method
operates on the result object. Is it just passing a method name? I
guess I was just mistakenly thinking of it in terms of key value
pairing:

result.send(a) AS result[a]

Thanks.

Jason

And, for anyone needing the code to dump any database table to a CSV
file, here is the refactored, much tidier code using fastercsv

def table2CSV(table)
require ‘fastercsv’

@table = table
@titles = @table.column_names

@users = @table.find(:all)
FasterCSV.open("#{RAILS_ROOT}/csv_directory/#{@table}.csv", “wb”) do
|csv|
csv << @titles
@users.each do |user|
csv << @titles.map { |a| user.send(a) }
end
end

end

Jason P. wrote:

So if I have that correct, I don’t understand how the send method
operates on the result object. Is it just passing a method name? I
guess I was just mistakenly thinking of it in terms of key value
pairing:

result.send(a) AS result[a]

result.send(a) just calls the method with name a on the result object.

result[a] would also be acceptable, accessing the attribute directly,
but failing if you’ve written a custom accessor method for that
attribute.


Rails Wheels - Find Plugins, List & Sell Plugins -
http://railswheels.com