Before, when attempting to download the CSV export of nodes and their resource
statuses, the download wouldn't start until after all of the data had been
collected, and converted to CSV.

By passing render a proc, and using output.write, we can send each CSV line to
the client as it is generated.

The main reason for doing this is to give the user immediate feedback that we
recognize they clicked on the download link, instead of stalling until all of
the data has been collected.  This also should reduce the server-side memory
footprint of the CSV, since we don't need to generate the entire CSV string in
memory before sending it.

Paired-with: Jacob Helwig <[email protected]>
Signed-off-by: Nick Lewis <[email protected]>
---
Local-branch: ticket/next/7007
 app/controllers/nodes_controller.rb       |   11 ++++++++++-
 spec/controllers/nodes_controller_spec.rb |   14 ++++++++++----
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/app/controllers/nodes_controller.rb 
b/app/controllers/nodes_controller.rb
index 3e0f60d..ea79b72 100644
--- a/app/controllers/nodes_controller.rb
+++ b/app/controllers/nodes_controller.rb
@@ -123,7 +123,16 @@ class NodesController < InheritedResources::Base
 
       format.html { render :index }
       format.yaml { render :text => collection.to_yaml, :content_type => 
'application/x-yaml' }
-      format.csv  { render :text => collection.to_csv, :content_type => 
'text/csv' }
+      format.csv do
+        response["Content-Type"] = 'text/comma-separated-values;'
+        response["Content-Disposition"] = 'filename="nodes.csv";'
+
+        render :text => proc { |response,output|
+          collection.to_csv do |line|
+            output.write(line)
+          end
+        }, :layout => false
+      end
     end
   end
 end
diff --git a/spec/controllers/nodes_controller_spec.rb 
b/spec/controllers/nodes_controller_spec.rb
index f1d79f3..dadba2b 100644
--- a/spec/controllers/nodes_controller_spec.rb
+++ b/spec/controllers/nodes_controller_spec.rb
@@ -66,11 +66,17 @@ describe NodesController do
                             'change_count',    'out_of_sync_count', 'skipped', 
       'failed' ]
       end
 
+      def body_from_proc
+        body = StringIO.new
+        response.body.call(response, body)
+        body.string
+      end
+
       it "should make correct CSV" do
         get :index, :format => "csv"
 
         response.should be_success
-        response.body.split("\n").should =~ [
+        body_from_proc.split("\n").should =~ [
           header,
           
"#{@node.name},changed,1,0,0,1,#{@resource.resource_type},#{@resource.title},#{@resource.evaluation_time},#{@resource.file},#{@resource.line},#{@resource.time},#{@resource.change_count},#{@resource.out_of_sync_count},#{@resource.skipped},#{@resource.failed}"
         ]
@@ -83,7 +89,7 @@ describe NodesController do
         get :index, :format => "csv"
 
         response.should be_success
-        response.body.split("\n").should =~ [
+        body_from_proc.split("\n").should =~ [
           header,
           
"#{@node.name},changed,1,0,0,1,#{@resource.resource_type},#{@resource.title},#{@resource.evaluation_time},#{@resource.file},#{@resource.line},#{@resource.time},#{@resource.change_count},#{@resource.out_of_sync_count},#{@resource.skipped},#{@resource.failed}",
           "#{unreported_node.name},,,,,,,,,,,,,,,"
@@ -97,7 +103,7 @@ describe NodesController do
           get :index, :format => "csv"
 
           response.should be_success
-          CSV.parse(response.body).last.first.should == name
+          CSV.parse(body_from_proc).last.first.should == name
         end
       end
 
@@ -123,7 +129,7 @@ describe NodesController do
         get :index, :format => "csv"
 
         response.should be_success
-        response.body.split("\n").should =~ [
+        body_from_proc.split("\n").should =~ [
           header,
           
%Q[#{@node.name},failed,2,0,1,1,File,/etc/sudoers,1.0,/etc/puppet/manifests/site.pp,1,#{res1.time},1,1,false,false],
           
%Q[#{@node.name},failed,2,0,1,1,File,/etc/hosts,2.0,/etc/puppet/manifests/site.pp,5,#{res2.time},2,2,false,true]
-- 
1.7.5.1

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to