Сначала большое спасибо за вашу помощь! Это, тем не менее, интересный баг.
Дело в том, что мне, возможно, придется изменить имя пользователя через базу данных, так как маршрут недоступен
Не могли бы вы предоставить мне запрос?
Я думаю, это невозможно, потому что тогда я запретлю множество имен, начинающихся с Σ в Греции (и по сути сломаю вход через Facebook для этих пользователей). Могу ли я запретить конкретный шаблон регулярного выражения? Чтобы убедиться, что Σ стоит хотя бы в конце?
Ещё один участник зарегистрировался с точно такой же проблемой. Мой смысл в том, что для нас это не частный случай. Буквально тысячи греческих имён заканчиваются на Σ (или ς).
И, к сожалению, учитывая нашу основную возрастную группу (> 40), у многих участников имя в Facebook написано ЗАГЛАВНЫМИ БУКВАМИ (), поэтому при входе через Facebook их имя копируется в поле имени пользователя…
Не стоит беспокоиться из-за PostgreSQL. В SQL мы всегда должны сравнивать с username_lower, а не полагаться на LOWER(), потому что username_lower — это не просто версия имени пользователя в нижнем регистре. Мы также применяем нормализацию Unicode.
Я согласен. Добавление обходного пути в User.normalize_username пока должно быть достаточно. В баге Ruby уже есть некоторые обсуждения, и похоже, что простого решения нет. Однако нам повезло, потому что нам нужно лишь проверить последний символ в имени пользователя. Это гораздо проще, чем делать это для целого предложения.
Верно. Тем не менее, это должно быть гораздо проще, чем полная реализация, так как нам нужно беспокоиться только о некоторых символах, таких как нижнее подчеркивание, дефис и, возможно, цифры? Это должно быть выполнимо.
Я знаю, что отхожу от обсуждения конкретной ошибки, но, думая об этой проблеме, я не могу игнорировать тот факт, что её можно избежать.
Я обнаружил, что в Discourse есть некоторые API-маршруты, которые ссылаются на пользователя по userId, а другие — по username. Разве это не должно быть более последовательным (в пользу userId)?
Может быть, стоит реализовать что-то вроде того, что сейчас работает с категориями/тегами? Например, указывать и username, и userId в URL: https://meta.discourse.org/u/chrispanag/4387.
Ещё в 2016 году @eviltrout был против этого, не уверен, как он относится к этому сейчас.
В любом случае, у меня есть обходное решение в Discourse в этом PR:
Оно решит проблему с новой регистрацией в Facebook, приводя к нижнему регистру любое имя пользователя, начинающееся с сигмы. Это означает, что вам нужно только исправить имя пользователя Spiros и любых других пользователей с конечной сигмой, приведя их к нижнему регистру, и проблема должна исчезнуть в долгосрочной перспективе.
Я всё ещё не люблю использовать id повсюду, но понимаю, что есть много случаев, когда это имеет смысл.
В таких ситуациях я бы предпочёл что-то вроде id-username, где username — это любое значение, которое можно поместить в URL. Его даже можно игнорировать маршрутизатору. Но хотя бы при обмене ссылкой вы будете понимать, на что ведёте ссылку.
Лично я большой поклонник маршрутизации пользователей в стиле Stack Overflow:
https://stackoverflow.com/users/17174/sam-saffron
В мире Discourse это выглядело бы так:
https://meta.discourse.org/u/17174/sam-saffron
Это позволяет получить лучшее из обоих миров. Хотя я полностью понимаю возражения: «Мне не нравится, что 17174 фигурирует в URL; имена пользователей стабильны».
Тем не менее, мы уже давно живём с нашими текущими маршрутами; просто раз в несколько лет возникают какие-то пограничные случаи.
Я думаю, было бы полезно использовать идентификатор (id) вместо имени пользователя (или оба, но с опорой только на id, как описано выше) по крайней мере на странице профиля пользователя, чтобы администратор мог изменить имя пользователя через интерфейс Discourse, не прибегая к выполнению команд в консоли Rails, если с именем пользователя возникнут проблемы.
Нам нужно беспокоиться только о тех символах, где реализация преобразования в нижний регистр в JavaScript и Ruby различается. Не наоборот.
Не существует единого правила, как немецкая строчная буква «ß» преобразуется в верхний регистр. Это может быть «SS», «SZ» или даже новая заглавная буква «ẞ» (да, есть тонкое различие). Обратное преобразование возможно только для «ẞ», и это корректно работает как в Ruby, так и в JavaScript.
Я думаю, нам стоит сделать следующее:
Внести исправление @sam для решения текущей проблемы.
Удалить LOWER(username) из SQL-запросов, так как это просто плохая ™ практика (например, отсутствие нормализации Unicode).
Надеяться, что Ruby исправит корневую проблему.
В долгосрочной перспективе: подумать о добавлении идентификаторов пользователей в маршруты. Скорее всего, самая сложная часть — понять, как обрабатывать кавычки и упоминания.