class ActiveRecord::Associations::CollectionAssociation

def replace(other_array)

and delete/add only records that have changed.
Replace this collection with +other_array+. This will perform a diff
def replace(other_array)
  other_array.each { |val| raise_on_type_mismatch!(val) }
  original_target = load_target.dup
  if owner.new_record?
    replace_records(other_array, original_target)
  else
    replace_common_records_in_memory(other_array, original_target)
    if other_array != original_target
      transaction { replace_records(other_array, original_target) }
    else
      other_array
    end
  end
end