I have a Rails app where I'm parsing an uploaded CSV. I just discovered that the parsing has stopped working and am investigating.
I've tracked it back to the fact that I call .read
on an instance of ActionDispatch::Http::UploadedFile
, and that returns an empty string.
The uploaded file is not empty, and when I inspect the UploadedFile
object, it has an attribute like @tempfile=#<File:/tmp/RackMultipart20130530-34976-6jaqt5
. If I cat
that file on the filesystem, it contains what I expect.
Why might .read
return an empty string?
I'm using Rails 3.2.13.
My colleague suggested calling rewind
before read
, and that works. Apparently some other code is reading the file first.
Nobody's reading the file before I am, as far as I can tell. I created an initializer to spy on the UploadedFile
:
# config/initializers/uploaded_file.rb
class ActionDispatch::Http::UploadedFile
alias_method :old_read, :read
def read(*args)
Rails.logger.info "file #{self} is getting read by #{caller.first}!"
old_read(*args)
end
end
I didn't see any other calls to read
. Thinking there might be some other method called that would advance the read pointer, I went further and replaced the class entirely:
# config/initializers/uploaded_file.rb
ActionDispatch::Http::UploadedFile = Class.new do
def initialize(*args)
Rails.logger.info "initilized with #{args}"
end
def method_missing(method_name, *args, &block)
Rails.logger.info "file got #{method_name} with #{args}.\
Block? #{block_given?} caller? #{caller.first}"
end
end
Still nothing. I see a call to initialize
, my call to rewind
, and my call to read
.
Seems like this file comes pre-wound to the end. I'm not sure why that might be, but rewind
is still the fix for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With