我试图删除表中重复的记录。我的目标是总是删除旧的记录。这是一个rake任务。
主要部分与下图相似,
TableName.order(updated_at: :asc).each do |record|
next if record.valid?
record.destroy!
end
如果存在2个以上的重复行,则此循环仅删除其中一个并存在。
为了理解它,我调试了循环并逐行观察,嗒哒!一切正常。可能在销毁!操作没有执行之前循环迭代。可能,它只删除最后一条记录(不是每个重复组的最后一项)
无论如何,我可以通过生成一个数组来一次性销毁所有数据或smth来修复它,但我很好奇为什么ruby/ActiveRecord会这样做。
作为回答,请详细解释发生了什么。谢谢🙌🏻🙌🏻🙌🏻
2条答案
按热度按时间yftpprvb1#
一旦调用record.destroy!,其他重复记录的updated_at属性不会更新,因此它们在数据库中保持当前顺序。因此,循环只能删除遇到的第一个重复记录,而不能删除其他记录。
7uhlpewt2#
您遇到的问题似乎与修改正在迭代的集合有关。当您在迭代期间销毁记录时,集合会被修改,迭代器会丢失其位置,可能会跳过某些元素。
这不是Ruby或ActiveRecord特有的,而是一个通用的编程概念。
在Ruby中,当你迭代一个集合时,迭代器会保留一个当前位置的内部索引。如果集合被修改(例如,一个元素被删除),索引可能指向一个不正确的位置,导致意外的行为。
要解决此问题,您可以在迭代期间收集要销毁的记录的ID,然后在循环结束后一次性销毁它们。下面是一个示例:
这段代码首先收集数组
duplicate_record_ids
中无效记录的ID。循环结束后,它使用where查询获取所有具有这些ID的记录,并在一个批处理中销毁它们。通过将ID集合与实际删除分离,可以避免在迭代集合时修改集合,从而避免任何意外行为。
希望这个有用。