Это плохой паттерн, поскольку find_by_name чувствителен к регистру, а create! — нет [1], из-за чего возникает ошибка ActiveRecord::RecordInvalid : Validation failed: Name has already been taken.
Следовало бы использовать что-то вроде:
tag = Tag.where('name ILIKE ?', tag_name).first || Tag.create!(name: tag_name)
потому что validates :name, presence: true, uniqueness: { case_sensitive: false }↩︎
Спасибо за отчет, поставьте метку pr-welcome на этот запрос. Похоже, нам нужно изменить метод find_by_name, чтобы он выполнял поиск без учета регистра.
Учитывая, что у нас есть:
Исправление будет следующим:
tag = Tag.where('lower(name) = ?', tag_name.downcase).first
В TagGroup отсутствует индекс, поэтому нам нужно добавить его, а затем сделать то же самое там.
Действительно, воспроизвести проблему только по тегу не удалось.
Я допустил небольшую ошибку в своём первом сообщении:
Tag.find_by_name регистронезависим (хорошо), а Tag.find_by(name: ) регистрозависим (плохо).
Это связано с тем, что Дэвид уже исправил это для тегов 7 лет назад, переопределив метод find_by_name.
Для TagGroup это исправление так и не было применено.