1

我想在表格中添加一个新字段。

我的用户模型中的新“secret_code”字段应该等于 Digest::SHA1.hexdigest([Time.now, rand].join)[1..12]。

我要做的是生成一个迁移,该迁移会将字段添加到表中,并使用(某种)唯一的“secret_code”填充我现有的用户。

class AddSecretCodeToUsers < ActiveRecord::Migration
  def self.up
    add_column :users, :secret_code, :string
    User.update_all ["secret_code =?", Digest::SHA1.hexdigest([Time.now, rand].join)[1..12]]
  end

  def self.down
    remove_column :users, :secret_code
  end
end

问题在于,此迁移使用相同的密码填充所有现有用户!

一种解决方案是不使用 update_all 并运行一个循环来获取每个用户并向每个用户发送更新,但在这种情况下,我的迁移将非常缓慢。

有没有办法将“唯一”随机值发送到 update_all 方法?

谢谢,奥古斯托

4

2 回答 2

4

尝试将其更改为,Digest::SHA1.hexdigest([Time.now, rand].to_s)但我个人会为上述创建一个 rake 任务,因为它并不是真正的迁移。

你的 rake 任务会做

User.all.each do |u|
  u.update_attribute(:secret_code, Digest::SHA1.hexdigest([Time.now, rand].to_s))
end

但是,对于您的迁移,我还将添加t.string :secret_code, :default => Digest::SHA1.hexdigest([Time.now, rand].to_s) 到属性中,以便将其添加到新创建的记录中。

于 2011-09-30T09:37:35.500 回答
3

对于 MySQL,您可以将其直接放入您的self.up:

connection.execute(%Q{
    update users
    set secret_code = substring(sha1(rand()) from 1 for 12)
})

PostgreSQL 默认不支持 SHA1,但它有 MD5,这可能已经足够了:

connection.execute(%Q{
    update users
    set secret_code = substring(md5(random()::varchar) from 1 for 12)
})

如果你安装了pgcrypto包,那么你可以同时使用 SHA1。

两者都将让数据库完成所有工作,并避免往返整个表的所有开销。如果您想混合时间,您也可以使用您的哈希值:

md5(random()::varchar || now()::varchar) -- PostgreSQL
sha(rand()            || now()         ) -- MySQL
于 2011-09-30T10:23:46.680 回答