Under the covers, this relationship is implemented as a has_many
association to a ActiveStorage::Attachment record
and a has_many-through association to a ActiveStorage::Blob record. These
associations are available as photos_attachments and
photos_blobs. But you shouldn’t need to work with these
associations directly in most circumstances.
The system has been designed to having you go through the ActiveStorage::Attached::Many
proxy that provides the dynamic proxy to the associations and factory
methods, like #attach.
If the :dependent option isn’t set, all the attachments will be
purged (i.e. destroyed) whenever the record is destroyed.
# File activestorage/lib/active_storage/attached/model.rb, line 89
def has_many_attached(name, dependent: :purge_later)
generated_association_methods.class_eval def #{name} @active_storage_attached_#{name} ||= ActiveStorage::Attached::Many.new("#{name}", self) end def #{name}=(attachables) if ActiveStorage.replace_on_assign_to_many attachment_changes["#{name}"] = if attachables.nil? || Array(attachables).none? ActiveStorage::Attached::Changes::DeleteMany.new("#{name}", self) else ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, attachables) end else if !attachables.nil? || Array(attachables).any? attachment_changes["#{name}"] = ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, #{name}.blobs + attachables) end end end, __FILE__, __LINE__ + 1
has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "ActiveStorage::Attachment", inverse_of: :record, dependent: :destroy do
def purge
each(&:purge)
reset
end
def purge_later
each(&:purge_later)
reset
end
end
has_many :"#{name}_blobs", through: :"#{name}_attachments", class_name: "ActiveStorage::Blob", source: :blob
scope :"with_attached_#{name}", -> { includes("#{name}_attachments": :blob) }
after_save { attachment_changes[name.to_s]&.save }
after_commit(on: %[ create update ]) { attachment_changes.delete(name.to_s).try(:upload) }
ActiveRecord::Reflection.add_attachment_reflection(
self,
name,
ActiveRecord::Reflection.create(:has_many_attached, name, nil, { dependent: dependent }, self)
)
end