代码之家  ›  专栏  ›  技术社区  ›  leylakapi

Rails ActiveRecord删除关系表上的重复项并进行更改

  •  1
  • leylakapi  · 技术社区  · 7 年前

    我需要删除一个表上的重复记录,如果一个表与B表有关系,我应该在B表上找到从重复中删除的记录,以更改其他记录。

    我关注这个 Remove duplicate records based on multiple columns? 那个链接。 此链接工作成功,删除了所有重复记录,并将第一条记录保留在表中。

    我的问题是,当我们删除记录时,该记录可能会在B表中使用,所以,我需要找到被删除的记录,并使用保留的记录进行更新。

    def up
      grouped = A.all.group_by{|model| [model.name] }
      grouped.values.each do |duplicates|
        last_one = duplicates.last #also used pop
        duplicates.each do |double|
         find_in_b = B.find_by(a_id: double.id)
         find_in_b.a_id = last_one.id
         find_in_b.save!(validate: false)
         double.destroy
        end
      end
    end
    

    提前感谢!

    1 回复  |  直到 7 年前
        1
  •  0
  •   norydev    7 年前

    有几件事:

    • 你应该使用 .pop 而不是 .last ,否则将销毁所有记录。(pop是数组上的一种破坏性方法,这是您想要的,因为您想保留一条记录)
    • 如果A有许多B,则应使用 .where 而不是在这一行上查找\u by:

      find_in_b = B.where(a_id: double.id)

    我猜代码可以使用AR关联,但不知道您的确切情况,下面是我建议的代码:

    def up
      grouped = A.all.group_by{ |model| [model.name] }
    
      grouped.values.each do |duplicates|
        last_one = duplicates.pop
    
        duplicates.each do |double|
          find_in_b = B.where(a_id: double.id)
    
          # update_all doesn't run validations
          find_in_b.update_all(a_id: last_one.id) 
    
          double.destroy
        end
      end
    end 
    

    请注意,如果您的A表非常大,那么 group_by 在ruby中,您应该使用DB分组。