复制mongo映射器关联以在内存中进行操作

时间:2012-03-09 16:40:18

标签: ruby mongomapper

我想 1.从数据库中抓取一个对象1和对象2(每个都有2个has_many关联) 2.创建对象3,它是对象1的克隆,因此还没有关联 2.复制对象2的关联并将它们添加到对象3的关联 3.将新对象3用于内存中的操作 4.退出流程而不对数据库进行永久更改 - 对象1和对象2在流程退出时仍具有原始关联

正在发生什么

  1. 我从数据库中抓取一个对象1和对象2(每个都有2个has_many关联)
  2. 我创建了对象3,它是对象1的克隆,因此没有关联
  3. 我复制了对象2的关联,并将它们添加到对象3的关联
  4. 我将新对象3用于内存中的操作
  5. 我退出流程但是现在对数据库进行了永久性更改 - 对象2不再具有关联,因为它们的键已更改为(临时)对象3 id。
  6. 这是我的代码。请注意,all包含一个数组,其中包含任意数量的对象

    object1 = all.last.clone #we take the most recently created object
    all.each do |instance|
      instance_association1 = (instance.association1).dup
      object1.association1 += instance_association1 #BUG this moves the association
      object1.association1.uniq!
      instance_association2 = (instance.association2).dup
      object1.association2 += instance_association2
      object1.association2.uniq!
    end
    

    请注意,现在当我说: all.last.association1,我得到一个空数组。

    帮助!!

1 个答案:

答案 0 :(得分:1)

MongoMapper的关联可能对保存有点过分热心。我想在某个时候对它进行大修,但这不是一个简单的问题。

保存发生时会告诉您的代码是many_documents_proxy.rb。执行my_association = [...]时,replace是被调用的方法。

唯一不进行任何保存的方法是build,因此您可以像这样构建临时对象:

tmp = all.last.clone
all.each do |instance|
  instance.association1.each { |doc| tmp.association1.build(doc.attributes) }
  tmp.association1.uniq!
  # ...
end

更一般地说,您可以将所有关联文档转换为数组,而不必担心保存...

associations1 = []
associations2 = []
all.each do |doc|
  associations1 += doc.associations1.to_a
  associations2 += doc.associations2.to_a
end
assocations1.uniq!
assocations2.uniq!

然而,小心! Ruby的uniq方法看起来像使用Ruby的#hash方法来计算相等性,这可能无法在这种情况下为您提供所需的结果。做一些测试以确保my_obj.hash == my_obj2.hash如果my_obj == my_obj2。有关实施您自己的#hash方法的策略,请参阅this discussion,如果这是您需要的路线。