我们在Ruby on Rails 4.2项目中使用此代码来生成唯一的用户名。下面的方法是User类的实例方法,并接收名称字符串,如果需要避免冲突,则附加一个整数。然后它返回一个唯一的登录名,例如用于像
self.login = self.generate_unique_sane_login(self.name)
在before_save挂钩或控制器中。特别是,在注册后创建新用户实例时会调用此方法。
然而,偶尔这个功能失败了。此方法返回已存在的登录名,然后数据库驱动程序抛出唯一性违规异常(在本例中为Postgres),并且应用程序抛出HTTP / 1.1 500.或者它甚至没有这样做,我们在数据库中有几个重复项这绝对是使用此代码创建的,但不会再次加载验证。那些用户无法编辑他们的个人资料。
当发生这种情况时,我们没有在我们的日志中看到多个同时(或几乎同时)的用户注册尝试,因此我认为这不是竞争条件问题。
所以:为什么会这样?我错过了什么吗?什么是生成唯一用户登录字符串的更好的解决方案?
def self.generate_unique_sane_login(l)
l = l.gsub(/\@.*$/, '')
l = l.gsub(/[^A-Za-z0-9äöüÄÖÜß]/, '_')
c = 1
login = l
conflicting_logins = self.where("LOWER(login) = LOWER(?)", login)
until conflicting_logins.empty?
login = "#{l}#{c}"
conflicting_logins = self.where("LOWER(login) = LOWER(?)", login)
c = c+1
end
login
end
感谢您的评论。这是我的答案。