ruby-on-rails Ruby中StringIO的未定义方法'path'

anhgbhbe  于 2023-03-24  发布在  Ruby
关注(0)|答案(4)|浏览(182)

我在Rails应用程序中使用了以下代码片段:

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

它可以在网络上的一些文件上工作,然后在其他文件上崩溃:
未定义的方法`path' for #< StringIO:0x00000102a47240 >
有什么方法可以解决这个奇怪的间歇性问题吗?

uxh89sit

uxh89sit1#

我肯定要迟到了但是...
这个问题的根源是,如果你在一个小于10 kb的文件上使用open(url),它会自动将它转换成一个字符串IO对象,而不是使用Tempfile。正如大家所指出的,StringIO对象没有在它上面定义path方法。
默认值(10 kb)由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.p.s.确保使用#send,否则您无法访问#remove_const和#cont_set方法。p.p.s.如果您执行大量小IO,我不建议将其设置为零,因为创建的临时文件可能比更改代码以正确使用StringIO更糟糕。这完全取决于您的用例。

332nm8kg

332nm8kg2#

不要这样使用Open::URI。
只需:

file = open(url)

然后你可以read这个文件,因为你有一个IO类型的对象:

body = file.read

body = open(url).read

如果你需要路径,解析带有URI的URL,并通过这种方式获取路径。

k10s72fa

k10s72fa3#

根据docs,SrtingIO没有函数名路径。

bakd9h0s

bakd9h0s4#

对我来说,在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

相关问题