Мой метод клонирования заключается в краже детей из оригинальной модели
Я проверил несколько вопросов по этому вопросу, в том числе здесь, здесь и здесь. Я не могу понять, что здесь происходит не так.
Вот мой метод копирования:
def copy(new_period)
copy = self.dup
copy.report_id = Report.maximum(:report_id).next
copy.period_id = new_period
copy.responses = self.responses.dup
copy.save
end
Этот метод правильно делает копию модели отчета и назначает ее новому периоду, как и ожидалось. Он также перемещает всех детей из исходного отчета в новый отчет без дублирования, что не ожидается. Я не понимаю, почему это происходит.
У кого-нибудь есть идеи?
2 ответа
Я считаю, виновным является следующая строка
copy.responses = self.responses.dup
Возвращаемое значение из self.responses
является ActiveRecord::Relation
, Когда вы вызываете dup, вы дублируете экземпляр отношения, а не ресурсы, указанные областью действия.
Если вы хотите продублировать объекты ответа, вам сначала нужно их загрузить.
copy.responses = self.responses.map { |response| response.dup }
или же
copy.responses = self.responses.map(&:dup)
dup делает мелкую копию. Он также не копирует все свои дочерние объекты. Это важно отметить и с массивами и хэшами.
Решение состоит в том, чтобы написать метод клонирования для вашей модели:
def clone(new_period)
copy = self.class.new self.attributes.slice(*%w{attributes to copy})
copy.report_id = Report.maximum(:report_id).next
copy.period_id = new_period
copy.responses = Response.clone_multiple(self.responses)
copy.save
end
Аналогично с ответом добавьте метод класса для клонирования коллекции:
class << self
def clone_multiple(collection)
collection.map do |response|
copy = self.new(response.attributes.slice(*%w{attributes to clone})
copy.save
copy
end
end
end