Shrine项目ActiveRecord插件深度解析:文件上传与模型集成指南

Shrine项目ActiveRecord插件深度解析:文件上传与模型集成指南

shrine File Attachment toolkit for Ruby applications shrine 项目地址: https://gitcode.com/gh_mirrors/shr/shrine

前言

在现代Web开发中,文件上传是一个常见需求。Shrine作为一个灵活的文件上传库,提供了与ActiveRecord无缝集成的能力。本文将深入探讨Shrine的ActiveRecord插件,帮助开发者理解如何将文件上传功能优雅地整合到Rails应用中。

插件基础

要启用ActiveRecord集成,只需在Shrine配置中添加以下代码:

Shrine.plugin :activerecord

这个插件建立在model插件之上,为ActiveRecord模型添加了完整的附件处理能力。

模型附件集成

基本用法

在ActiveRecord模型中集成Shrine附件非常简单:

class Photo < ActiveRecord::Base # 假设有image_data列
  include ImageUploader::Attachment(:image) # 添加方法、回调和验证
end

这种集成方式为模型添加了完整的附件生命周期管理:

photo = Photo.new

# 缓存附件
photo.image = file 

# 访问附件
photo.image      #=> #<Shrine::UploadedFile id="bc2e13.jpg" storage=:cache ...>
photo.image_data #=> '{"id":"bc2e13.jpg","storage":"cache","metadata":{...}}'

# 持久化:提升附件并再次持久化
photo.save 

# 附件已提升到永久存储
photo.image      #=> #<Shrine::UploadedFile id="397eca.jpg" storage=:store ...>
photo.image_data #=> '{"id":"397eca.jpg","storage":"store","metadata":{...}}'

# 删除记录时同时删除附件
photo.destroy 

# 验证附件是否存在
photo.image.exists? #=> false

回调机制

保存后回调

当记录被保存且事务提交后,会触发Attacher#finalize方法,该方法负责:

  1. 将缓存文件提升到永久存储
  2. 删除之前的文件(如果有)
photo = Photo.new
photo.image = file
photo.image.storage_key #=> :cache

photo.save
photo.image.storage_key #=> :store

销毁后回调

记录被销毁且事务提交后,会调用Attacher#destroy_attached方法删除关联的存储文件。

photo = Photo.find(photo_id)
photo.image.exists? #=> true

photo.destroy
photo.image.exists? #=> false

回调注意事项

  1. 执行顺序:ActiveRecord存在一个已知的事务回调bug,因此确保在定义完所有"after commit"回调后再引入Shrine的附件模块。

  2. 自定义回调:可以覆盖以下方法来修改回调行为:

    • Attacher#activerecord_before_save
    • Attacher#activerecord_after_save
    • Attacher#activerecord_after_destroy
class Shrine::Attacher
  def activerecord_after_save
    super
    # 自定义逻辑
  end
end
  1. 禁用回调:如果不希望添加任何回调,可以配置:
plugin :activerecord, callbacks: false

验证集成

当使用validation插件时,附件模块会自动将验证错误合并到模型错误中。

基本验证

class ImageUploader < Shrine
  plugin :validation_helpers

  Attacher.validate do
    validate_max_size 10 * 1024 * 1024
  end
end
photo = Photo.new
photo.image = file
photo.valid?
photo.errors #=> { image: ["size must not be greater than 10.0 MB"] }

附件存在性验证

使用ActiveRecord的原生验证器:

class Photo < ActiveRecord::Base
  include ImageUploader::Attachment(:image)

  validates_presence_of :image
end

国际化支持

Shrine支持ActiveRecord的错误消息国际化:

class ImageUploader < Shrine
  plugin :validation_helpers

  Attacher.validate do
    validate_max_size 10 * 1024 * 1024, message: -> (max) { [:too_large, max: max] }
    validate_mime_type %w[image/jpeg image/png], message: :not_image
  end
end

对应的国际化文件配置:

en:
  activerecord:
    errors:
      models:
        photo:
          attributes:
            image:
              too_large: "must not be larger than %{max} bytes"
              not_image: "must be a common image format"

禁用验证

plugin :activerecord, validations: false

直接使用Attacher

除了通过Shrine::Attachment模块,也可以直接使用Shrine::Attacher

class Photo < ActiveRecord::Base # 有image_data列
end
photo    = Photo.new
attacher = ImageUploader::Attacher.from_model(photo, :image)

attacher.assign(file) # 缓存

attacher.file    #=> #<Shrine::UploadedFile id="bc2e13.jpg" storage=:cache ...>
photo.image_data #=> '{"id":"bc2e13.jpg","storage":"cache","metadata":{...}}'

photo.save        # 持久化
attacher.finalize # 提升
photo.save        # 再次持久化

attacher.file    #=> #<Shrine::UploadedFile id="397eca.jpg" storage=:store ...>
photo.image_data #=> '{"id":"397eca.jpg","storage":"store","metadata":{...}}'

持久化方法

Shrine::Attacher添加了以下持久化方法:

| 方法 | 描述 | | :----- | :---------- | | atomic_promote | 提升附件并在附件未更改时持久化 | | atomic_persist | 在附件未更改时保存变更 | | persist | 将任何变更保存到底层记录 |

最佳实践

  1. 事务安全:所有文件操作都在数据库事务完成后执行,确保数据一致性
  2. 错误处理:合理处理验证错误,提供用户友好的反馈
  3. 性能考虑:大文件上传时考虑使用后台任务处理文件提升操作
  4. 测试策略:同时测试模型和附件的交互,确保回调按预期工作

通过合理配置Shrine的ActiveRecord插件,开发者可以轻松实现强大而灵活的文件上传功能,同时保持代码的整洁和可维护性。

shrine File Attachment toolkit for Ruby applications shrine 项目地址: https://gitcode.com/gh_mirrors/shr/shrine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

常樱沙Vigour

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值