Question

I am very new to ruby. I have a question that how can I export two files within one click.

In the exsiting version, I can generate only one file at a time by calling 'def stream_csv', but when I try to call it twice in order to get two files, I got an error indicating about "ActionController::DoubleRenderError (Can only render or redirect once per action):" I guess, it is because of render.

Here is the source code of stream_csv:

def stream_csv
    require 'fastercsv'

        filename = params[:action] + ".csv"

        #this is required if you want this to work with IE      
        if request.env['HTTP_USER_AGENT'] =~ /msie/i
            headers['Pragma'] = 'public'
            headers["Content-type"] = "text/plain"
            headers['Cache-Control'] = 'no-cache, must-revalidate, post-check=0, pre-check=0'
            headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""
            headers['Expires'] = "0"
        else
            headers["Content-Type"] ||= 'text/csv'
            headers["Content-Disposition"] = "attachment; filename=\"#{filename}\""
            controller.response.headers["Content-Transfer-Encoding"] = "binary"
        end

        render :text => Proc.new { |response, output|
            csv = FasterCSV.new(output, :row_sep => "\r\n")
            yield csv
        }
    end
end

Is it possible to create two files under one click? If yes, how can I do it?

Was it helpful?

Solution

You're right, it's because of render. When you're setting headers, and then finally call render, you're building up an HTTP response to be sent to the browser. You can't do this twice from one HTTP request, which is why you get the ActionController::DoubleRenderError.

One way to send multiple .csv files at once is to combine them into a single .zip file and send that instead of the raw .csv files. There is an excellent, very easy to use rubyzip gem you can use to build your .zip file.

Instead of calling render inside stream_csv, you can simply return the FasterCSV instance itself or it's String output. From the calling method you can build up a .zip file (I'm not including code for that here since I'd just be copying and pasting from the README at the gem above).

Finally, instead of setting so many headers to force the download, take a look at Rails send_file method

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top