我的克隆方法是从原始模型中窃取儿童

时间:2015-08-12 19:19:25

标签: ruby-on-rails

我已就此问题检查过一堆问题,包括hereherehere。我似乎无法弄清楚这里出了什么问题。

这是我的复制方法:

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 个答案:

答案 0 :(得分:3)

我认为有罪的是以下一行

copy.responses = self.responses.dup

self.responses的返回值为ActiveRecord::Relation。当您调用dup时,您将复制关系实例,而不是范围指向的资源。

如果要复制响应对象,则需要先加载它们。

copy.responses = self.responses.map { |response| response.dup }

copy.responses = self.responses.map(&:dup)

答案 1 :(得分:0)

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