Ответ 1
Я использую это:)
def generate_token(column, length = 64)
begin
self[column] = SecureRandom.urlsafe_base64 length
end while Model.exists?(column => self[column])
end
Замените Model
на свое имя модели
В приложении Ruby on Rails я работаю над тем, чтобы разрешить пользователям загружать файлы и хотеть дать этим файлам короткое, случайное буквенно-цифровое имя. (Например, 'g7jf8' или '3bp76'). Каков наилучший способ сделать это?
Я думал о создании хэш/зашифрованной строки из исходного имени файла и метки времени. Затем запросите базу данных, чтобы проверить, не существует. Если это так, создайте другое и повторите.
Проблема, которую я вижу при таком подходе, заключается в том, что существует высокая вероятность дублирования строк, она может добавить довольно большую нагрузку datbase.
Я использую это:)
def generate_token(column, length = 64)
begin
self[column] = SecureRandom.urlsafe_base64 length
end while Model.exists?(column => self[column])
end
Замените Model
на свое имя модели
SecureRandom.uuid
Дает вам уникальную в мире String. http://en.m.wikipedia.org/wiki/Universally_unique_identifier
SecureRandom.hex 32
Дает случайный String, но алгоритм не оптимизирован для уникальности. Конечно, вероятность столкновения с 32 цифрами, предполагая истинную случайность, в основном теоретическая. Вы можете сделать 1 миллиард в секунду в течение 100 лет и иметь только 50% -ный шанс столкновения.
Используйте функцию Ruby SecureRandom.hex с дополнительным количеством символов, которое вы хотели создать.
Вы можете назначить уникальный идентификатор, увеличивая его каждый раз при добавлении нового файла и преобразовывая его в зашифрованную строку, используя OpenSSL::Cipher
с постоянным ключом, который вы где-то сохраняете.
Если вы закончите генерировать шестнадцатеричный или цифровой дайджест, вы можете сохранить код короче, указав номер, например. База 62:
# This is a lightweight base62 encoding for Ruby integers.
B62CHARS = ('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a
def base62_string nbr
b62 = ''
while nbr > 0
b62 << B62CHARS[nbr % 62]
nbr /= 62
end
b62.reverse
end
Если вам важно ограничить используемый набор символов (например, не иметь заглавных букв в именах файлов), тогда этот код можно легко адаптировать, если вы можете найти способ подачи подходящего случайного числа.
Если ваши имена файлов должны быть полузащищенными, вам необходимо учесть, что в хранилище имеется гораздо больше возможных имен, чем фактические имена.
Это всегда будет производить новую альфа-цифровую строку размера uniq 40, так как она также имеет отметку времени.
loop do
random_token = Digest::SHA1.hexdigest([Time.now, rand(111..999)].join)
break random_token unless Model.exists?(column_name: random_token)
конец
Примечание. Замените модель на имя модели и имя_каталога любым существующим столбцом вашей модели.
Самый простой способ - использовать string_pattern gem https://github.com/MarioRuiz/string_pattern
Это будет генерировать 1000 уникальных строк от 6 до 20 символов, включая буквы, и заставить включать специальные символы и цифры
require 'string_pattern'
1000.times {
puts :"6-20:L/$N/&".gen
}
Похоже, вам действительно нужны уникальные имена файлов, не так ли? Почему бы не забыть о сложных решениях и просто использовать Время # nsec?
t = Time.now #=> 2007-11-17 15:18:03 +0900
"%10.9f" % t.to_f #=> "1195280283.536151409"