Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined Method 'path' For StringIO in Ruby

I'm using the following snippet in a Rails app:

require 'open-uri'
url = "http://..."
uri = URI.parse(self.url)
file = open(uri)
puts "path: #{file.path}"

Which works on some files from the web, then crashes on others with:

undefined method `path' for #< StringIO:0x00000102a47240 >

Any way to fix this strange, intermittent problem?

like image 304
Kevin Sylvestre Avatar asked Jun 04 '11 05:06

Kevin Sylvestre


2 Answers

I'm definitely late to the party but...

The root of this problem is that if you use open(url) on a file smaller than 10kb it will convert it into a string IO object auto-magically instead of using a Tempfile. The StringIO object as everyone has pointed out does not have the path method defined on it.

The default (10kb) is set by the StringMax constant...

http://yard.ruby-doc.org/stdlib-2.1.0/OpenURI/Buffer.html

if defined?(OpenURI) && OpenURI::Buffer.const_defined?(StringMax)
  OpenURI::Buffer.send('remove_const', StringMax)
  OpenURI::Buffer.send('const_set', StringMax, 0)
end

Boom problem, solved!

p.s. make sure to use #send otherwise you can't access the #remove_const and #cont_set methods. p.p.s. I wouldn't advise setting it to zero if you do a lot of small IO as the tempfiles created will probably be worse than just changing your code to properly use StringIO. It all depends on yer use case.

like image 140
tehprofessor Avatar answered Oct 05 '22 19:10

tehprofessor


Don't use Open::URI like that.

Simply do:

file = open(url)

Then you can read the file because you have an IO-type object:

body = file.read

or

body = open(url).read

If you need the path, parse the URL with URI and get the path that way.

like image 40
the Tin Man Avatar answered Oct 05 '22 20:10

the Tin Man