Ruby中StringIO的未定义方法'path'

8
我将在一个Rails应用程序中使用以下代码片段: ```ruby ```
require 'open-uri'
url = "http://..."
uri = URI.parse(self.url)
file = open(uri)
puts "path: #{file.path}"

有些来自Web的文件可以正常工作,而其他文件则会出现以下错误:

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

有什么办法可以解决这个奇怪的、间歇性的问题吗?


1
你能否提供有和没有这个错误的示例URL? - Daniel O'Hara
@floatless 谢谢,看起来是极小文件无法创建备份文件的问题。 - Kevin Sylvestre
4个回答

14

我肯定是来晚了,但是...

这个问题的根源在于如果你对一个小于10kb的文件使用open(url),它会自动地将其转换为一个StringIO对象,而不是使用Tempfile。正如大家指出的那样,StringIO对象没有定义path方法。

默认值(10kb)由StringMax常量设置...

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

问题解决了!

p.s. 确保使用#send,否则无法访问#remove_const和#cont_set方法。 p.p.s. 如果你经常进行小的IO操作,我不建议将其设置为零,因为创建的临时文件可能比更改代码以正确地使用StringIO还要糟糕。一切都取决于你的用例。


你真是救了我的一命! - Cameron
除非我将片段中的所有StringMax常量更改为字符串,否则这对我没有用。 - max pleaner

7
不要像那样使用Open::URI。只需执行以下操作:
file = open(url)

然后,因为您拥有一个IO类型的对象,所以可以读取文件:
body = file.read

或者

body = open(url).read

如果您需要路径,请使用URI解析URL并以这种方式获取路径。

3
根据文档,StringIO没有名为path的函数。

它确实有:https://apidock.com/ruby/v1_9_1_378/StringIO/path - Nakilon

0

对我来说,在open()方法之后调用#read方法的解决方案是不可接受的。

因此,我在config/initializers中添加了这段代码。

Rails.application.config.after_initialize do
  if defined?(OpenURI) && OpenURI::Buffer::StringMax
    OpenURI::Buffer.send(:remove_const, 'StringMax')
    # default value is 10240 (nearly 10Kb)
    OpenURI::Buffer.const_set('StringMax', 1000)
  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接