Имя пользователя с символом Σ в конце вызывает ошибку при загрузке страницы профиля

Сначала большое спасибо за вашу помощь! Это, тем не менее, интересный баг.

Дело в том, что мне, возможно, придется изменить имя пользователя через базу данных, так как маршрут недоступен :sweat_smile:

Не могли бы вы предоставить мне запрос?

Я думаю, это невозможно, потому что тогда я запретлю множество имен, начинающихся с Σ в Греции (и по сути сломаю вход через Facebook для этих пользователей). Могу ли я запретить конкретный шаблон регулярного выражения? Чтобы убедиться, что Σ стоит хотя бы в конце?

1 лайк

Ещё один участник зарегистрировался с точно такой же проблемой. Мой смысл в том, что для нас это не частный случай. Буквально тысячи греческих имён заканчиваются на Σ (или ς).

И, к сожалению, учитывая нашу основную возрастную группу (> 40), у многих участников имя в Facebook написано ЗАГЛАВНЫМИ БУКВАМИ (:sweat_smile:), поэтому при входе через Facebook их имя копируется в поле имени пользователя…

4 лайка

Не стоит беспокоиться из-за PostgreSQL. В SQL мы всегда должны сравнивать с username_lower, а не полагаться на LOWER(), потому что username_lower — это не просто версия имени пользователя в нижнем регистре. Мы также применяем нормализацию Unicode.

Я согласен. Добавление обходного пути в User.normalize_username пока должно быть достаточно. В баге Ruby уже есть некоторые обсуждения, и похоже, что простого решения нет. Однако нам повезло, потому что нам нужно лишь проверить последний символ в имени пользователя. Это гораздо проще, чем делать это для целого предложения.

4 лайка

Что ж… как будет обработано это имя пользователя?

Заглавные: ΧΡΗΣΤΟΣ_ΠΑΝΑΓΙΩΤΑΚΟΠΟΥΛΟΣ
Строчные: χρηστος_παναγιωτακοπουλος или χρηστοσ_παναγιωτακοπουλος

NodeJs обрабатывает это корректно, но если проверять только последний символ имени пользователя, проблема сохранится.


(Почти все мужские имена в греческом языке — как первые, так и фамилии — заканчиваются на Σ)

3 лайка

Верно. Тем не менее, это должно быть гораздо проще, чем полная реализация, так как нам нужно беспокоиться только о некоторых символах, таких как нижнее подчеркивание, дефис и, возможно, цифры? Это должно быть выполнимо.

2 лайка

Я знаю, что отхожу от обсуждения конкретной ошибки, но, думая об этой проблеме, я не могу игнорировать тот факт, что её можно избежать.

Я обнаружил, что в Discourse есть некоторые API-маршруты, которые ссылаются на пользователя по userId, а другие — по username. Разве это не должно быть более последовательным (в пользу userId)?

Может быть, стоит реализовать что-то вроде того, что сейчас работает с категориями/тегами? Например, указывать и username, и userId в URL: https://meta.discourse.org/u/chrispanag/4387.

Просто мысль :sweat_smile:

2 лайка

Это потребует усилий по очистке, я точно видел некоторые вызовы LOWER().

4 лайка

Этот вопрос поднимался на протяжении многих лет: Update quotes and mentions when username is changed - #10 by sam

Ещё в 2016 году @eviltrout был против этого, не уверен, как он относится к этому сейчас.

В любом случае, у меня есть обходное решение в Discourse в этом PR:

Оно решит проблему с новой регистрацией в Facebook, приводя к нижнему регистру любое имя пользователя, начинающееся с сигмы. Это означает, что вам нужно только исправить имя пользователя Spiros и любых других пользователей с конечной сигмой, приведя их к нижнему регистру, и проблема должна исчезнуть в долгосрочной перспективе.

(Ожидается слияние PR)

4 лайка

Огромное спасибо, @sam! Ваша помощь была неоценима.

Есть ли способ сделать это через консоль Rails? (Так как пользователь «сломан», сделать это через панель администратора невозможно…)

1 лайк

Да, это должно помочь

./launcher enter app
rails c
u = User.find_by(username: 'ΣΠΥΡΟΣ')
u.username = 'σπυρος'
u.username_lower = 'σπυρος'
u.save!
4 лайка

Я всё ещё не люблю использовать id повсюду, но понимаю, что есть много случаев, когда это имеет смысл.

В таких ситуациях я бы предпочёл что-то вроде id-username, где username — это любое значение, которое можно поместить в URL. Его даже можно игнорировать маршрутизатору. Но хотя бы при обмене ссылкой вы будете понимать, на что ведёте ссылку.

6 лайков

Что касается PostgreSQL, похоже, что правильная настройка коллокаций решает проблему:

➜  discoursesmall git:(master) psql -d discourse_development
psql (13.1 (Ubuntu 13.1-1.pgdg20.10+1))
Type "help" for help.

discourse_development=# SELECT lower('ΣΠΥΡΟΣ');
 lower  
--------
 σπυροσ
(1 row)

discourse_development=# SELECT lower('ΣΠΥΡΟΣ' COLLATE "und-x-icu"); 
 lower  
--------
 σπυρος
(1 row)

Источник: https://www.postgresql.org/message-id/5d80ac2d-3f1f-4d60-88a8-5602eb9978a3%40manitou-mail.org

7 лайков

Похоже, существуют и другие символы Unicode с аналогичными преобразованиями, например: ‘ß’ → ‘SS’ (немецкий язык).

Интересно исследовать, как они обрабатываются в Discourse…

Также вы можете ознакомиться с этим ресурсом:

Лично я большой поклонник маршрутизации пользователей в стиле Stack Overflow:

https://stackoverflow.com/users/17174/sam-saffron

В мире Discourse это выглядело бы так:

https://meta.discourse.org/u/17174/sam-saffron

Это позволяет получить лучшее из обоих миров. Хотя я полностью понимаю возражения: «Мне не нравится, что 17174 фигурирует в URL; имена пользователей стабильны».

Тем не менее, мы уже давно живём с нашими текущими маршрутами; просто раз в несколько лет возникают какие-то пограничные случаи.

5 лайков

Я думаю, было бы полезно использовать идентификатор (id) вместо имени пользователя (или оба, но с опорой только на id, как описано выше) по крайней мере на странице профиля пользователя, чтобы администратор мог изменить имя пользователя через интерфейс Discourse, не прибегая к выполнению команд в консоли Rails, если с именем пользователя возникнут проблемы.

Нам нужно беспокоиться только о тех символах, где реализация преобразования в нижний регистр в JavaScript и Ruby различается. Не наоборот.

Не существует единого правила, как немецкая строчная буква «ß» преобразуется в верхний регистр. Это может быть «SS», «SZ» или даже новая заглавная буква «ẞ» (да, есть тонкое различие). Обратное преобразование возможно только для «ẞ», и это корректно работает как в Ruby, так и в JavaScript.


Я думаю, нам стоит сделать следующее:

  1. Внести исправление @sam для решения текущей проблемы.
  2. Удалить LOWER(username) из SQL-запросов, так как это просто плохая ™ практика (например, отсутствие нормализации Unicode).
  3. Надеяться, что Ruby исправит корневую проблему.
  4. В долгосрочной перспективе: подумать о добавлении идентификаторов пользователей в маршруты. Скорее всего, самая сложная часть — понять, как обрабатывать кавычки и упоминания.
3 лайка

Не уверен, связано ли это, но у нас есть несколько пользователей с именами в кодировке Unicode, и они разбросаны по файлу /log.

ActionView::Template::Error (Нет маршрута, соответствующего {:action=>"show", :controller=>"users", :username=>"ζηεδψ"}, возможные несоответствующие ограничения: [:username])