扩展 ActiveStorage::Attachment - 添加自定义字段

Pat*_*rey 10 ruby-on-rails attachment

我想扩展类 ActiveStorage::Attachment 并添加一个枚举属性以查看附件。

我最初的方法是在 \app\models 目录中创建一个新文件attachment.rb,如下所示。

class ActiveStorage::Attachment < ActiveRecord::Base
    enum visibility: [ :privately_visible, :publicly_visible]
end
Run Code Online (Sandbox Code Playgroud)

这不起作用。

欢迎任何建议。Rails 扩展类的方法是什么?

更新

我有一个现在部分有效的解决方案。为此,我创建了一个扩展 active_storage_attachment_extension.rb 并将其放置在 \lib

module ActiveStorageAttachmentExtension

  extend ActiveSupport::Concern

  included do
    enum visibility: [ :privately_visible, :publicly_visible]

    def describe_me
      puts "I am part of the extension"
    end

  end
end
Run Code Online (Sandbox Code Playgroud)

扩展在 extensions.rb 中的初始化期间加载

ActiveStorage::Attachment.send(:include, ::ActiveStorageAttachmentExtension)
Run Code Online (Sandbox Code Playgroud)

不幸的是,它只是部分工作:虽然枚举方法public_visible?和privately_visible?在视图中可用,但在控制器中不可用。当调用控制器中的任何方法时,枚举似乎已经消失了。我收到“NoMethodError - 未定义方法”错误。令人惊讶的是,一旦枚举方法在控制器中被调用一次,它们在视图中也不再可用。我假设 ActiveStorage::Attachment 类会动态重新加载,并且扩展会丢失,因为它们仅在初始化期间添加。

有任何想法吗?

Geo*_*orn 6

我假设 ActiveStorage::Attachment 类会动态重新加载,并且扩展会丢失,因为它们仅在初始化期间添加。

你是对的。用于Rails.configuration.to_prepare在应用程序启动后和每次重新加载代码时混合模块:

Rails.configuration.to_prepare do
  ActiveStorage::Attachment.send :include, ::ActiveStorageAttachmentExtension
end
Run Code Online (Sandbox Code Playgroud)


iGi*_*ian 3

app/models/active_storage_attachment.rb正如我的评论中提到的,它需要包含以下内容的文件:

class ActiveStorageAttachment < ApplicationRecord
  enum visibility: [ :privately_visible, :publicly_visible]
end
Run Code Online (Sandbox Code Playgroud)

然后您还需要向表中添加整数类型的列可见性active_storage_attachments

class AddVisibilityToActiveStorageAttachments < ActiveRecord::Migration[5.2]
  def change
    add_column :active_storage_attachments, :visibility, :integer

  end
end
Run Code Online (Sandbox Code Playgroud)

访问 ActiveStorageAttachment 的新列

我使用我的模型举了一个例子:我有一个 has_one_attached 的用户:avatar。

我可以访问 active_storage_attachments 表,通过user.avatar.attachment.inspect它返回例如#<ActiveStorage::Attachment id: 1, name: "avatar", record_type: "User", record_id: 1, blob_id: 3, created_at: "2018-06-03 13:26:20", visibility: 0>

请注意,列的值visibility是纯整数,没有由visibility数组转换(我仍然想知道为什么)。

一种可能的解决方法是在用户模型中定义一个方法,avatar_attachment如下所示:

class User < ApplicationRecord
  has_one_attached :avatar

  def avatar_attachment
    ActiveStorageAttachment.find_by(name: 'avatar', record_type: 'User', record_id: self.id)
  end
end
Run Code Online (Sandbox Code Playgroud)

现在user.avatar_attachment.inspect返回#<ActiveStorageAttachment id: 1, name: "avatar", record_type: "User", record_id: 1, blob_id: 3, created_at: "2018-06-03 13:26:20", visibility: "privately_visible">

现在与可见性数组相关的所有方法都可用。记录更新也有效:

user.avatar_attachment.publicly_visible! # => true
Run Code Online (Sandbox Code Playgroud)