1

I need to remove duplicated record on A table and if A table have relation with B table, I should find on B table to record which have removed from duplicated to change other record.

I follow this Remove duplicate records based on multiple columns? that link. This link is works successfully and removed all duplicated records and keep first records on table.

My problem is that when we removed record, that record may used in B table so, I need to find record which is removed and update with the kept record.

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

Thanks in advance!

leylakapi
  • 71
  • 9

1 Answers1

0

A couple of things:

  • you should use .pop and not .last, otherwise all your records will be destroyed. (pop is a destructive method on the array, which is what you want, as you want to keep one record)
  • If A has_many B, you should use .where instead of find_by on this line:

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

I guess the code could use AR associations, but not knowing your exact situation, here is my proposed code:

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 

Note that if your A table is very big, it's quite inefficient to group_by in ruby, you should rather use the DB grouping.

norydev
  • 123
  • 3
  • 8