【问题标题】:Add number to regex?将数字添加到正则表达式?
【发布时间】:2012-12-13 16:23:04
【问题描述】:

我们有一个带有 Google 登录/注册功能的 Facebook 应用。一些帐户不提供用户名,因此应用程序必须在将对象保存到数据库之前创建一个。

我们目前是这样解决问题的:

user.username = "#{user.email[/^[^@]*/]}_#{user.id.to_s}"

问题是,我们像database/odm一样使用mongodb/mongoid,生成的用户名太长,比如:

hyperrjas_50ad43d11d41c86b27000066

在这种情况下,我们在hyperrjas 之后添加了user.id

如果用户名已被占用,我们想添加一个唯一编号而不是唯一的 id,例如:

hyperrjas
hyperrjas1
hyperrjas2
hyperrjas3
...

我们该怎么做?

【问题讨论】:

  • 您必须知道您的数据库中有多少具有给定名称的用户,我认为如果不对数据库执行查询就不会发生这种情况。
  • 谢谢,你能添加一个优化查询到数据库的例子来检查用户名是否已经被占用吗?

标签: ruby-on-rails ruby regex ruby-on-rails-3 mongoid


【解决方案1】:

我之前回答了一个类似的问题。这是我想出的:

https://stackoverflow.com/a/13794784/367611

每条评论更新

您可以通过以下方式制作一个方法:

def prevent_collision(user)
  name = "#{user.email[/^[^@]*/]}"
  users = User.where(:username => /^#{name}/).to_a #Return an array and after use length method with users.length. Without .to_a is not working because is returned a mongoid criteria.
  count = users.length

  if count > 0
    count = rand(1000)
    loop do
      break "#{name}#{count}" unless users.any? { |u| u.name == "#{name}#{count}" }
      count += rand(10)
    end
  else
    name
  end
end

返回值将是最初生成的名称或附加了计数的名称。然后你可以这样做,例如:

@user.username = prevent_collision(@user)
@user.save

【讨论】:

  • 谢谢我用mongoid 2.4.12。对 mongoid 2.4.12 有效吗?
  • 优秀。我知道这就是我使用它的方式,但我一直在使用旧版本的 Mongoid。很高兴知道它仍然以这种方式工作。
  • 谢谢,但我很抱歉,但我已经检查了帐户 hyperrjas@gmail.com 和 hyperrjas@hotmail.com,我收到了错误 Validation failed - Username is already taken。错误在哪里?
  • 这里出现竞争条件的可能性很小,两条记录可能认为相同的一条可用并跳过它。您可能希望选择随机的 3 或 4 位数字来避免这种情况,或者使用某种重试逻辑来避免不可避免的异常。如果对创建用户过程的两个同时调用启动,则可能会发生这种情况。
  • 现在所有电子邮件帐户使用相同的用户名都可以正常工作。我已经检查了与 gmx.com、gmail.com、hotmail.com、yahoo.com 等相同的别名,并且代码为每个电子邮件帐户生成了一个唯一的用户名。非常感谢!
【解决方案2】:

也许这是一个有用的想法:

username = "hyperrjas001"
try_name = username.dup
10.times do
  raise "username maximum reached: #{username}." if try_name.end_with('999')
  try_name = try_name.next
  puts try_name
end

# Output:
#hyperrjas002
#hyperrjas003
#hyperrjas004
#hyperrjas005
#hyperrjas006
#hyperrjas007
#hyperrjas008
#hyperrjas009
#hyperrjas010
#hyperrjas011

【讨论】:

  • 谢谢 你能写一个在数据库中查询的例子来检查用户名是否已经被占用吗?非常感谢!
【解决方案3】:

这样的东西可能适合递增:

username.sub(/^(.*\D)(\d*)$/) { "%s%d" % [ $1, $2.to_i + 1 ] }

举个例子:

username = 'hyperrjas'
username2 = username.sub(/^(.*\D)(\d*)$/) { "%s%d" % [ $1, $2.to_i + 1 ] }
# => "hyperrjas1"
username3 = username2.sub(/^(.*\D)(\d*)$/) { "%s%d" % [ $1, $2.to_i + 1 ] }
# => "hyperrjas2"

这可以根据需要重复,直到您获得一个唯一的名称。请注意,它会将 lucky99 之类的名称混淆为 lucky100,但不会将 lucky991 混淆。

【讨论】:

  • 谢谢,但我需要知道它是如何对数据库进行查询的!
  • 你现在如何访问你的数据库?
  • 感谢@tadman 的帮助。 SeanHill 的答案是正确的。
猜你喜欢
  • 1970-01-01
  • 2012-11-26
  • 2012-07-05
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
  • 2013-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多