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

問題は、この移行によって既存のすべてのユーザーに同じシークレットコードが入力されることです。

1つの解決策は、update_allを使用せず、ループを実行してすべてのユーザーをフェッチし、各ユーザーに更新を送信することですが、この場合、移行は非常に遅くなります。

「一意の」ランダムな値をupdate_allメソッドに送信する方法はありますか?

ありがとう、アウグスト

4

2 に答える 2

4

に変更してみてください。Digest::SHA1.hexdigest([Time.now, rand].to_s)ただし、実際には移行ではないため、個人的には上記の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

self.upMySQLの場合、これを自分の:に正しく投げることができます。

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 に答える