为什么我有时会在这里收到类型错误"没有将 StringIO 隐式转换为字符串"?Ruby/Rails



我的一个邮件中有一行代码,用于添加带有用户姓氏和DoB的附件。类型错误";没有StringIO到String的隐式转换";有时出现在CCD_ 1方法中。

attachments["#{@user.last_name.downcase}-#{@user.date_of_birth.strftime('%d%m%y')}.jpeg"] = File.read(URI.parse(@user.profile_picture_url).open)

它在大多数情况下都能工作,但偶尔也会因为这个错误而失败。我正在使用carrierwave将文件上传到远程S3存储桶,如果这有区别的话。

编辑:

我在控制台上做了一些挖掘,坦率地说,这让我更加困惑!我有两个用户记录,都有通过carrierwave上传到S3的个人资料图片。如果我只是隔离File.read方法,并使用两个记录进行尝试,一个有效,另一个无效。检查URI时,它们看起来几乎完全相同。

然而,我发现carrierwave支持读取文件的快捷方式,这解决了这个问题。这是更新后的代码:

attachments["#{@user.last_name.downcase}-#{@user.date_of_birth.strftime('%d%m%y')}.jpeg"] = @user.profile_picture.read

任何小于10kb的内容都将作为StringIO而不是File打开。在文档中找不到实际的参考,所以来源如下:

StringMax = 10240
def <<(str)
@io << str
@size += str.length
# NOTE: once you pass 10kb mark, you get a tempfile.
#                      v
if StringIO === @io && StringMax < @size
require 'tempfile'
io = Tempfile.new('open-uri')
io.binmode
Meta.init io, @io if Meta === @io
io << @io.string
@io = io
end
end

https://github.com/ruby/ruby/blob/v3_2_0/lib/open-uri.rb#L398


让我们测试一下:

>> require "open-uri"
>> File.write("public/small.txt", "a"*10240)
=> 10240
>> URI.open("http://localhost:3000/small.txt").class
=> StringIO
>> File.write("public/large.txt", "a"*(10240+1))
=> 10241
>> URI.open("http://localhost:3000/large.txt").class
=> Tempfile

你可以File.readTempfile,但不能File.readStringIO

修复方法是在URI:上调用File.read0

>> URI.parse("http://localhost:3000/small.txt").read.class
=> String
>> URI.parse("http://localhost:3000/large.txt").read.class
=> String
# also works
>> URI.open("http://localhost:3000/small.txt").read.class
=> String

https://rubyapi.org/3.2/o/openuri/openread#method-i-read

最新更新