For administration purposes, I had to rework an uploaded CSV file, and stream it back to the user. I started wondering how I could test this uncommon response body type.
I knew about:
fixture_file_upload
which allows the simulation of a file upload, so I looked at the Rails source, in ActionController’s TestProcess class, where the method lies.
There I found the:
binary_content
method, which does the job by returning the entire streamed content in a string!
How it works
First, let’s take a look at the send_file sources:
... render :status => options[:status], :text => Proc.new { |response, output| logger.info "Streaming file #{path}" unless logger.nil? len = options[:buffer_size] || 4096 File.open(path, 'rb') do |file| while buf = file.read(len) output.write(buf) end end } ...
We see that the response is returned as a Proc. All that binary_content has to do is to:
- create an IO object,
- call the proc and pass it the IO object
- read the IO and return the content as a string
Here is the binary_content method:
def binary_content raise "Response body is not a Proc: #{body.inspect}" unless body.kind_of?(Proc) require 'stringio' sio = StringIO.new body.call(self, sio) sio.rewind sio.read end
StringIO’s for the win!