无需ActionParameters,用Active Storage创建带验证的Banner记录可行吗?
完全可行!Active Storage本来就支持在创建父记录时,直接通过属性赋值的方式关联文件,刚好能满足你“必须在创建时完成图片关联以通过验证”的需求。
先确认你的模型设置
首先要保证Banner模型正确配置了Active Storage的关联,比如你用到了image_fr和image_de两个附件,模型里应该这样写:
class Banner < ApplicationRecord has_one_attached :image_fr has_one_attached :image_de # 你的验证规则(比如必须存在) validates :image_fr, presence: true validates :image_de, presence: true validates :start_at, :location, presence: true # 其他验证逻辑... end
你的代码可以正常工作(附带优化建议)
你写的Banner.create代码本身是有效的,不过有个小细节可以优化:用Rails.root.join来拼接路径,比字符串拼接更安全(能自动适配不同系统的路径分隔符),另外用File.open的块形式能确保文件自动关闭(虽然在种子文件里影响不大,但属于好习惯):
image_file_path = Rails.root.join('db/seeds/images/banners/pdfs/gift_voucher_bottom.png') Banner.create( start_at: Time.now, location: 'site', image_fr: File.open(image_file_path, 'r'), image_de: File.open(image_file_path, 'r'), width: 595, height: nil )
原理说明
当你给has_one_attached定义的属性传入File对象时,Active Storage会在创建Banner记录的同时,自动生成对应的ActiveStorage::Blob(存储文件元数据)和ActiveStorage::Attachment(关联Banner和Blob)记录,一步完成文件上传和关联,完全符合验证要求,不需要事后再调用.attach方法。
注意事项
- 要确保文件路径绝对正确,否则会抛出文件不存在的异常,导致记录创建失败
- 如果你的验证包含文件类型、大小限制,要保证传入的文件符合规则
- 就算是生产环境用云存储(比如AWS S3),这种方式也能正常工作,Active Storage会自动把文件上传到对应的存储服务
总之,你的思路完全正确,这种方式是Active Storage支持的标准用法之一,放心用就好。
内容的提问来源于stack exchange,提问作者Olivier
相关产品推荐
相关产品推荐

