在 active_storage_attachments 上设置 record_type 的 ActiveStorage 问题

ActiveStorage issue to set record_type on active_storage_attachments

我对 ActiveStorage 有疑问

情况是我有一个名为 Setting::Profile 的模型和 Admin table 的名称以及附件 :avatar 上传过程成功,但何时获取图片无法找到,因为在 table active_storage_attachments 属性 record_type 中存储了名称 Setting::Profile,假设名称为 Admin

如何添加一行为record_type属性做准备? 谢谢

这是我的演示:https://github.com/SunDi3yansyah-forks/AppActiveStorage

我发现了这个问题(在控制台中尝试)。

如果您设置 profile = Account::Profile.last 然后调用 profile.avatar.attached? 它 returns false。这是因为 ActiveStorage::Attachment 中的列 record_type 设置为用户。

因此,您无法访问 blob,因为 profile.avatar.blob returns 以下查询:

SELECT  "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 1], ["record_type", "Account::Profile"], ["name", "avatar"], ["LIMIT", 1]]

错误:Module::DelegationError: blob delegated to attachment, but attachment is nil

我发现的一种可能的解决方法 是定义 Account::Profile 如下:

class Account::Profile < ApplicationRecord
    self.table_name = "users"
    # has_one_attached :avatar # remove this

  def avatar
    ActiveStorage::Attachment.where(name: :avatar, record_type: 'User', record_id: self.id).last
  end

end

这适用于显示图像,但问题是 profile.avatar.class 不是 ActiveStorage::Attached::One(如 User.last.avatar.class)而是 ActiveStorage::Attachment

因此,您不能在其上调用例如 .attached? 方法。您必须使用 profile.avatar.present? 检查头像是否存在。

一个可能更好的解决方案是这样定义实例方法头像:

def avatar
  ActiveStorage::Attached::One.new('avatar', User.find(id), dependent: :purge_later)
end

需要实例化一个ActiveStorage::Attached::One的对象但是record必须是Userclass(才能匹配record_type),所以User.find(id) . 现在所有方法都可用:profile.avatar.methods.