首页 > 解决方案 > 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/versions/3.0.2/lib/ruby/gems/3.0.0/gems/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/versions/3.0.2/lib/ruby/gems/3.0.0/gems/activestorage-6.1.4.1/lib/active_storage/attached/changes/create_one.rb:74:in `find_or_build_blob': 找不到或构建 blob:预期可附加,得到 #File:/Users/fernando.guillen/Development/PlaycocolaBackend/test/fixtures/files/video.webm (ArgumentError)

标签: ruby-on-railsrubyrails-activestorage

解决方案


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

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

就效率或 LOC 而言,它与 call 相比并没有任何优势.attach。虽然对于处理在 JSON 中作为 base64 编码字符串传递的文件来说,这是一个绝妙的技巧。


推荐阅读