bcparanj-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2007-Jun-16 01:24 UTC
CSV Download of any given model
I found sample code from the archives of this list to make CSV download of a model. It works fine. I am wondering if it is possible to generalize the code posted by François on his blog to handle any given model. class ReportController < ApplicationController def report @models = Model.find(:all, :conditions => [''...'']) report = StringIO.new CSV::Writer.generate(report, '','') do |csv| csv << %w(Title Total) @models.each do |model| csv << [model.title, model.total] end end report.rewind send_data(report.read, :type => ''text/csv; charset=iso-8859-1; header=present'', :filename => ''report.csv'') end end TIA. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I''m curious on this as well... my code is a little different then that of the blog post referenced: class SignaturesController < ApplicationController def export require ''csv'' content_type = if request.user_agent =~ /windows/i ''application/vnd.ms-excel'' else ''text/csv'' end CSV::Writer.generate(output = "") do |csv| csv << Signature.column_names Signature.find(:all).each do |signature| csv << [signature.id, signature.firstname, signature.lastname] end end send_data(output, :type => content_type, :filename => "#{controller_name}-export.csv") end end I''m already using Model.column_names to get the header of the CSV file. Is there a way to loop through Model.content_columns and grab the name variable to include within the block rather then specifying the column individually? Thoughts from anyone? Thanks... Tim On Jun 15, 9:24 pm, "bcpar...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org" <bcpar...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I found sample code from the archives of this list to makeCSV > download of a model. It works fine. I am wondering if it is possible > to generalize the code posted by François on his blog to handle any > given model. > > class ReportController < ApplicationController > def report > @models = Model.find(:all, :conditions => [''...'']) > report = StringIO.new > CSV::Writer.generate(report, '','') do |csv| > csv<< %w(Title Total) > @models.each do |model| > csv<< [model.title, model.total] > end > end > > report.rewind > send_data(report.read, > :type => ''text/csv; charset=iso-8859-1; header=present'', > :filename => ''report.csv'') > end > end > > TIA.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I think you''ll find this simpler and more flexible. First, you''ll need to download the FasterCSV gem (''gem install fastercsv''). Then you can use: class FasterCSVExport require ''fastercsv'' def create_report( field_names = [], data_rows = [] ) FasterCSV.generate do |csv| csv << field_names.map {|fn| fn.humanize.titleize } data_rows.each {|row| csv << row } end end end I''ve given it to you as a stand-alone class but the create_report method can also be added to each model directly or as part of a module that gets mixed in (which is how I do it). Then in your controller you can just have: field_names = [''id'', ''firstname'', ''lastname''] table_rows = YourModel.find(:all).collect {|item| [item.id, item.firstname, item.lastname] export_data = FasterCSVExport.create_report(field_names, table_rows) send_data(export_data, :type => "text/csv; charset=utf-8; header=present", :disposition => ''attachment'', :filename => "exported_data.csv") Even easier, you can pass your field_names to the "select" option when performing the find to quickly have both the table header and the table rows contain the same attributes. Something like: field_names = [''id'', ''firstname'', ''lastname''] table_rows = YourModel.find(:all, :select => field_names) export_data = FasterCSVExport.create_report(field_names, table_rows) send_data(export_data, :type => "text/csv; charset=utf-8; header=present", :disposition => ''attachment'', :filename => "exported_data.csv") Or if you opt to put the ''create_report'' method into your model directly, you can push the find to the model too and let it handle both steps at once. export_data = YourModel.create_report([''id'', ''firstname'', ''lastname'']) send_data(export_data, :type => "text/csv; charset=utf-8; header=present", :disposition => ''attachment'', :filename => "exported_data.csv")>From there you can start to add bells and whistles. Tim, somethinglike: field_names = YourModel.column_names if field_names.blank? might be what you want to grab all the column names. (I''m typing this from scratch without testing it so it''s quite possible I''ve typo''d something...) HTH, Kevin Skoglund http://www.nullislove.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Thank you Kevin - that makes sense, I''ll check it out when I get back to the office tomorrow. Regards, Tim On Jul 27, 1:08 pm, Kevin Skoglund <ke...-WGmuFPN42W8gMxX8nMqP6gC/G2K4zDHf@public.gmane.org> wrote:> I think you''ll find this simpler and more flexible. First, you''ll > need to download the FasterCSV gem (''gem install fastercsv''). Then > you can use: > > class FasterCSVExport > require ''fastercsv'' > > def create_report( field_names = [], data_rows = [] ) > FasterCSV.generate do |csv| > csv << field_names.map {|fn| fn.humanize.titleize } > data_rows.each {|row| csv << row } > end > end > end > > I''ve given it to you as a stand-alone class but the create_report > method can also be added to each model directly or as part of a module > that gets mixed in (which is how I do it). Then in your controller > you can just have: > > field_names = [''id'', ''firstname'', ''lastname''] > table_rows = YourModel.find(:all).collect {|item| [item.id, > item.firstname, item.lastname] > export_data = FasterCSVExport.create_report(field_names, table_rows) > send_data(export_data, :type => "text/csv; charset=utf-8; > header=present", > :disposition => ''attachment'', :filename => "exported_data.csv") > > Even easier, you can pass your field_names to the "select" option when > performing the find to quickly have both the table header and the > table rows contain the same attributes. Something like: > > field_names = [''id'', ''firstname'', ''lastname''] > table_rows = YourModel.find(:all, :select => field_names) > export_data = FasterCSVExport.create_report(field_names, table_rows) > send_data(export_data, :type => "text/csv; charset=utf-8; > header=present", > :disposition => ''attachment'', :filename => "exported_data.csv") > > Or if you opt to put the ''create_report'' method into your model > directly, you can push the find to the model too and let it handle > both steps at once. > > export_data = YourModel.create_report([''id'', ''firstname'', ''lastname'']) > send_data(export_data, :type => "text/csv; charset=utf-8; > header=present", > :disposition => ''attachment'', :filename => "exported_data.csv") > > >From there you can start to add bells and whistles. Tim, something > > like: > field_names = YourModel.column_names if field_names.blank? > might be what you want to grab all the column names. > > (I''m typing this from scratch without testing it so it''s quite > possible I''ve typo''d something...) > > HTH, > Kevin Skoglund > > http://www.nullislove.com--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---