Rails和Active Storage,如何在创建调用上直接分配附件?



我有MyModel:

has_one_attached :video

我知道我可以这样做:

my_model = MyModel.create!()
my_model.video.attach(io: File.open("path/my_video.webm"), filename: "video.webm")

工作正常

但我想知道是否有一种方法可以将附件分配到create()调用中,如:

MyModel.create!(
video: File.read("path/my_video.webm")
)

如果我这样做,我看到这个错误:

/.rbenv/版本/3.0.2/lib/ruby/珠宝/3.0.0/珠宝/activesupport-6.1.4.1/lib/active_support/message_verifier。rb:176:in ' verify': ActiveSupport::MessageVerifier::InvalidSignature (ActiveSupport::MessageVerifier::InvalidSignature)

我试过了:

MyModel.create!(
video: File.open("path/my_video.webm")
)

我得到这个错误:

/.rbenv/版本/3.0.2/lib/ruby/珠宝/3.0.0/珠宝/activestorage-6.1.4.1/lib/active_storage//变化/create_one。rb:74:在' find_or_build_blob'中:无法找到或构建blob:预期可附加,得到#File:/Users/fernando.guillen/Development/PlaycocolaBackend/test/fixtures/files/video。webm (ArgumentError)

您可以通过创建ActionDispatch::Http::UploadedFile的实例来实现。这基本上只是对一个tempfile实例的包装,Rails在处理文件上传时在内部使用它。

MyModel.create!(
video: ActionDispatch::Http::UploadedFile.new(
tempfile: File.open("path/my_video.webm"), 
filename: "video.webm",
content_type: 'video/webm'
)
)

在效率或LOC方面,它实际上没有调用.attach的任何优势。对于处理JSON中作为base64编码字符串传递的文件来说,这是一个很好的技巧。

也可以MyModel.create!(video: { io: File.open('some/path'), filename: 'video.webm' })

A "real"用例:使用工厂创建记录,在创建时验证附件的存在。

您可以使用Rack::Test::UploadedFile:

FactoryBot.define do
factory :my_model do
video { Rack::Test::UploadedFile.new(Rails.root.join("path", "my_video.webm"), "video/webm") }
end
end

最新更新