1

在我的用户模型中,我有以下方法:

def confirmation_token
    self.confirmation = loop do
        random_token = SecureRandom.urlsafe_base64(16, false)
        break random_token unless User.exists?(confirmation: random_token)
    end
end

此方法只会创建一个随机令牌来确认用户的电子邮件...

如您所见,它在 User.exists?(confirmation:random_token) 时循环,这意味着它验证用户表中是否已经没有类似的令牌。

我的问题是:如果我在“用户表”中有很多行,我需要在这个(确认)列中添加索引以获得更高的性能?

注意(这个方法每个用户只执行一次......当用户第一次注册时)

4

2 回答 2

1

是的。如果您对任何特定列(在本例中confirmation)进行多次搜索,则应为该列编制索引。

于 2013-10-08T22:37:29.030 回答
0

如果您只是按该值进行搜索,则会向您提供简短的答案。

虽然有些事情需要考虑。首先,您可能希望该索引是唯一的,随着表的增长,这将大大提高性能。

add_index :users, :confirmation_token, unique: true

此外,您可能想要一个唯一值,而不仅仅是随机值。尽管它不太可能生成重复,但它仍然是random,而不是唯一值。其中一个选项是使用您知道该表唯一的某个用户列中的 Digest 类生成和 SHA,如下所示:

Digest::SHA1.hexdigest(user.email)

UPD: Asker 担心如果有人知道他使用电子邮件作为密钥并使用它来生成令牌的情况。

这通常通过在加密之前向电子邮件附加一些唯一密钥来解决。您可以使用安全随机生成此类密钥并将其存储在环境变量中。在您的 .bashrc/.profile/.bash_profile 或您使用的任何其他文件中,执行以下操作:

export EMAIL_TOKEN_SECRET="M9SyIuuOPhakX0b6gjvcRnsRHY="

然后这样做:

Digest::SHA1.hexdigest("#{user.email}-#{ENV['EMAIL_TOKEN_SECRET'}")
于 2013-10-09T18:56:18.577 回答