Rails Active Storage如何在调用create方法时直接关联附件?
问题解决方法
报错原因说明
- 第一种写法传入
File.read得到的二进制字符串,Active Storage会误将其识别为附件的签名ID(signed_id),在校验签名时失败,抛出ActiveSupport::MessageVerifier::InvalidSignature错误。 - 第二种写法直接传入File对象,不属于Active Storage支持的「可附加类型」,无法自动构建对应的Blob记录,因此抛出参数错误。
正确实现方式
有两种常用写法都可以实现创建记录时直接绑定附件:
写法1:直接传递附件参数哈希(推荐)
Rails 5.2及以上版本支持直接给关联附件属性传递包含io、filename等参数的哈希,会自动完成Blob创建和关联:
MyModel.create!( video: { io: File.open("path/my_video.webm"), filename: "video.webm", content_type: "video/webm" # 非必填,建议明确指定避免自动识别出错 } )
如果你是在控制器中使用该写法,需要注意调整强参数配置,允许附件对应的参数传入。
写法2:预创建Blob后关联
如果使用的Rails版本较低不支持直接传哈希,可以先手动创建Active Storage Blob,再将Blob实例赋值给属性:
# 先上传文件创建Blob记录 video_blob = ActiveStorage::Blob.create_and_upload!( io: File.open("path/my_video.webm"), filename: "video.webm", content_type: "video/webm" ) # 创建记录时直接关联Blob MyModel.create!(video: video_blob)
补充说明
如果是通过网页表单上传文件,接收到的ActionDispatch::Http::UploadedFile类型的文件对象可以直接赋值给附件属性,不需要额外封装参数,直接写MyModel.create!(video: params[:video])即可正常运行。
内容的提问来源于stack exchange,提问作者fguillen
相关产品推荐
相关产品推荐

