Rails миграция: возможно ли update_all с динамическим кодом?
Я хотел бы добавить новое поле в таблицу.
Мое новое поле "secret_code" в моей модели User должно быть равно Digest::SHA1.hexdigest([Time.now, rand].join)[1..12].
Я пытаюсь сгенерировать миграцию, которая добавит поле в таблицу, а также заполнит моих существующих пользователей (своего рода) уникальным "секретным кодом".
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?
Спасибо, Аугусто
2 ответа
Попробуйте изменить это на Digest::SHA1.hexdigest([Time.now, rand].to_s)
но лично я бы создал грабли для вышеперечисленного, поскольку это не совсем миграция.
Ваша задача с граблями сделает
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)
к атрибуту, чтобы он добавлялся во вновь создаваемые записи.
Для 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