<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Synthesis: How to generate CSV files in Rails</title>
    <link>http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>by Scott Becker</description>
    <item>
      <title>How to generate CSV files in Rails</title>
      <description>&lt;p&gt;A while back someone posted on rubyonrails-talk asking how to export to &lt;span class="caps"&gt;CSV&lt;/span&gt; from Rails.  I posted a solution, and people seemed to dig it, so I&amp;#8217;ll share it again here.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails"&gt;&lt;img src="http://synthesis.sbecker.net/files/csv-storage-engine.png" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;h2&gt;Use FasterCSV&lt;/h2&gt;


	&lt;p&gt;Get the &lt;a href="http://fastercsv.rubyforge.org/"&gt;FasterCSV gem.&lt;/a&gt; Why? It&amp;#8217;s faster, and easier to use. Once you&amp;#8217;ve got it, require it in environment.rb. Here&amp;#8217;s an abbreviated version of my working controller method. Copy/paste/modify. And you&amp;#8217;re done!&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;export_to_csv&lt;/span&gt;
  &lt;span class="attribute"&gt;@users&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

  &lt;span class="ident"&gt;csv_string&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;FasterCSV&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;generate&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;csv&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="comment"&gt;# header row&lt;/span&gt;
    &lt;span class="ident"&gt;csv&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;first_name&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;last_name&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;

    &lt;span class="comment"&gt;# data rows&lt;/span&gt;
    &lt;span class="attribute"&gt;@users&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;csv&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first_name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;last_name&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# send it to the browsah&lt;/span&gt;
  &lt;span class="ident"&gt;send_data&lt;/span&gt; &lt;span class="ident"&gt;csv_string&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
            &lt;span class="symbol"&gt;:type&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;text/csv; charset=iso-8859-1; header=present&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
            &lt;span class="symbol"&gt;:disposition&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;attachment; filename=users.csv&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h2&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt; or &lt;span class="caps"&gt;CSV&lt;/span&gt;, have it your way&lt;/h2&gt;


	&lt;p&gt;Now, if we wanted to get all clever about it, we could go further and serve both html and &lt;span class="caps"&gt;CSV&lt;/span&gt; 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:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;index&lt;/span&gt;
  &lt;span class="attribute"&gt;@users&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:all&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

  &lt;span class="ident"&gt;respond_to&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;wants&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;wants&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;html&lt;/span&gt;
    &lt;span class="ident"&gt;wants&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;csv&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;csv_string&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;FasterCSV&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;generate&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;csv&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
        &lt;span class="comment"&gt;# header row&lt;/span&gt;
        &lt;span class="ident"&gt;csv&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;first_name&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;last_name&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;

        &lt;span class="comment"&gt;# data rows&lt;/span&gt;
        &lt;span class="attribute"&gt;@users&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
          &lt;span class="ident"&gt;csv&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first_name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;last_name&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;

      &lt;span class="comment"&gt;# send it to the browsah&lt;/span&gt;
      &lt;span class="ident"&gt;send_data&lt;/span&gt; &lt;span class="ident"&gt;csv_string&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
                &lt;span class="symbol"&gt;:type&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;text/csv; charset=iso-8859-1; header=present&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
                &lt;span class="symbol"&gt;:disposition&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;attachment; filename=users.csv&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Now if the user requests:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;/users &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;she&amp;#8217;ll get &lt;span class="caps"&gt;HTML&lt;/span&gt;. If she requests:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;/users.csv&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;You get the point.&lt;/p&gt;</description>
      <pubDate>Thu, 07 Jun 2007 16:21:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:5b2d2c11-6e14-42ad-a58b-5dba39c2ab4e</guid>
      <author>sbecker</author>
      <link>http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails</link>
      <category>Ruby on Rails</category>
      <category>Web Development</category>
      <category>rails</category>
      <category>csv</category>
      <category>export</category>
    </item>
    <item>
      <title>"How to generate CSV files in Rails" by Jill</title>
      <description>&lt;p&gt;Good tutorial, thanks!&lt;/p&gt;</description>
      <pubDate>Wed, 07 May 2008 12:08:31 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:c242bee7-6579-4881-a47a-6b4d5120df77</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails#comment-7840</link>
    </item>
    <item>
      <title>"How to generate CSV files in Rails" by תוכנת תיווך</title>
      <description>&lt;p&gt;Sweet nifty little tip.
I was actually rebooting and using windows every time I needed to do a .csv . You just saved me a lot of time Scott.&lt;/p&gt;


	&lt;p&gt;Thanks a lot.&lt;/p&gt;


	&lt;p&gt;Michal&lt;/p&gt;</description>
      <pubDate>Sat, 05 Apr 2008 01:51:40 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:0a8e844b-e327-4f1e-8618-7b87ccc3baae</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails#comment-7833</link>
    </item>
    <item>
      <title>"How to generate CSV files in Rails" by Gregory Brown</title>
      <description>&lt;p&gt;Using Ruport:&lt;/p&gt;


&lt;pre&gt;
class User &amp;lt; ActiveRecord::Base
  acts_as_reportable :only =&amp;gt; ["id, "first_name", "last_name"]
end

# in controller
def export_to_csv
   User.report_table.to_csv
end

&lt;/pre&gt;

	&lt;p&gt;Of course, maybe overkill if that&amp;#8217;s all you need, but Ruport + acts_as_reportable also handles all associations and whatnot.  (And uses FCSV under the hood)&lt;/p&gt;</description>
      <pubDate>Wed, 27 Jun 2007 07:27:50 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:f9baffdb-43b6-42cd-b48b-cd51779198eb</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails#comment-7457</link>
    </item>
    <item>
      <title>"How to generate CSV files in Rails" by Meekish</title>
      <description>&lt;p&gt;Now that&amp;#8217;s hot :)&lt;/p&gt;</description>
      <pubDate>Fri, 08 Jun 2007 07:32:09 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:7b0c95f9-efdd-4cd2-a06e-e07974f60213</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails#comment-7381</link>
    </item>
    <item>
      <title>"How to generate CSV files in Rails" by Scott Becker</title>
      <description>&lt;p&gt;@Meekish &amp;#8211; Updated with a respond_to example.&lt;/p&gt;</description>
      <pubDate>Thu, 07 Jun 2007 21:45:04 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:abf52b8f-f79f-49c9-9e62-d36317691f7e</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails#comment-7380</link>
    </item>
    <item>
      <title>"How to generate CSV files in Rails" by Scott Becker</title>
      <description>&lt;p&gt;@Meekish &amp;#8211; Good idea. That would be more Rails 2.0ish, wouldn&amp;#8217;t it. Maybe I will post another example using respond_to soon.&lt;/p&gt;</description>
      <pubDate>Thu, 07 Jun 2007 20:57:38 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:c689e370-6c8b-4dbb-9924-d1311593d7eb</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails#comment-7379</link>
    </item>
    <item>
      <title>"How to generate CSV files in Rails" by Meekish</title>
      <description>&lt;p&gt;That&amp;#8217;s very nice.&lt;/p&gt;


	&lt;p&gt;How about making UsersController#index respond_to .csv instead of creating an entire action for it?&lt;/p&gt;</description>
      <pubDate>Thu, 07 Jun 2007 20:51:39 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:bca90599-29b6-45df-8ff9-26c65e8d5f38</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails#comment-7378</link>
    </item>
    <item>
      <title>"How to generate CSV files in Rails" by Jason Perry</title>
      <description>&lt;p&gt;I&amp;#8217;ve got a little &lt;a href="http://svn.ambethia.com/pub/ruby/reporter/lib/report.rb"&gt;ruby class&lt;/a&gt; that encapsulates to dumping of csv files out to disk. I use this to generate some regular reports.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;Report.create &amp;quot;District Participation&amp;quot; do
  data = District.find(:all, :order =&amp;gt; &amp;quot;number&amp;quot;).map do |district|
    profiles = district.profiles
    ratings  = profiles.collect { |p| p.ratings.size }
    [district.county, profiles.size, ratings.sum]
  end
  [[&amp;quot;District&amp;quot;, &amp;quot;Respondants&amp;quot;, &amp;quot;Ratings&amp;quot;]] + data
end

Report.create &amp;quot;Subject Area Participation&amp;quot; do
  data = Subject.find(:all, :order =&amp;gt; &amp;quot;area&amp;quot;).map do |subject|
    profiles = subject.profiles
    ratings  = profiles.collect { |p| p.ratings.size }
    [subject.area, profiles.size, ratings.sum]
  end
  [[&amp;quot;Subject Area&amp;quot;, &amp;quot;Respondants&amp;quot;, &amp;quot;Ratings&amp;quot;]] + data
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It needs somework, to clean up the way reports are defined, but it works well.&lt;/p&gt;</description>
      <pubDate>Thu, 07 Jun 2007 20:11:25 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:5c44222d-3d97-4e77-994c-3d57d038c7e8</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/07/how-to-generate-csv-files-in-rails#comment-7377</link>
    </item>
  </channel>
</rss>
