#ruby-on-rails #activerecord #ruby-on-rails-6 #rails-activestorage
#ruby-on-rails #activerecord #ruby-on-rails-6 #rails-activestorage
Вопрос:
У меня есть функция для клонирования записей в приложении rails. В дополнение к данным формы я хотел бы скопировать / прикрепить к новому объекту любые загруженные файлы активного хранилища, которые прикреплены к исходному объекту. Есть идеи, как это сделать? Вот мое действие:
def copy
@source = Compitem.find(params[:id])
@compitem = @source.dup
render 'new'
end
class Compitem < ApplicationRecord
belongs_to :user
has_many_attached :uploads, dependent: :destroy
end
Комментарии:
1. Вложения ActiveStorage хранятся в таблице больших двоичных объектов. Таким образом, «клонирование» записи, по крайней мере, будет означать, что вам нужно дублировать эти строки. Но вы также должны учитывать, должны ли большие двоичные объекты дублируемого объекта указывать на один и тот же сохраненный файл (например, на s3) или он должен дублировать файл. Что вы на самом деле исследовали? Я вижу здесь только самые смутные попытки.
2. Спасибо за ответ. Файлы хранятся в локальном хранилище. Я хотел бы создавать новые вложения и дублировать объекты, а не сохранять одни и те же вложения и просто связывать их с одним и тем же. Имеет ли это смысл? Я огляделся и увидел несколько вариантов копирования поверх одного файла в случае has_one, но не смог заставить его работать с has_many копировать все вложения.
Ответ №1:
В итоге я получил эту работу, используя https://github.com/moiristo/deep_cloneable драгоценный камень. Заключительное действие:
def copy
@source = Compitem.find(params[:id])
@compitem = @source.deep_clone(include: :uploads_blobs)
@compitem.save
render 'new'
end
Ответ №2:
Просто сделал это в одном из моих приложений — это был has_one, а не has_many, но я думаю, что что-то подобное должно работать для вас, без добавления каких-либо дополнительных зависимостей, в Rails 6 :
@compitem = @source.dup
@source.uploads.each do |original_file|
@compitem.uploads.attach(io: StringIO.new(original_file.download),
filename: original_file.filename,
content_type: original_file.content_type)
end
@compitem.save