簡體   English   中英

我將如何在 Ruby 中生成一個隨機且唯一的字符串?

[英]How would i generate a random and unique string in Ruby?

在我正在開發的 Ruby on Rails 應用程序中,我允許用戶上傳文件並希望為這些文件提供一個簡短的隨機字母數字名稱。 (例如“g7jf8”或“3bp76”)。 做這個的最好方式是什么?

我想從原始文件名和時間戳生成哈希/加密字符串。 然后查詢數據庫以仔細檢查它不存在。 如果是這樣,請生成另一個並重復。

我用這種方法看到的問題是,如果重復字符串的概率很高,它可能會增加相當多的數據庫負載。

我用這個:)

def generate_token(column, length = 64)
  begin
    self[column] = SecureRandom.urlsafe_base64 length
  end while Model.exists?(column => self[column])
end

Model替換為您的模型名稱

SecureRandom.uuid

會給你一個全球唯一的字符串。http://en.m.wikipedia.org/wiki/Universally_unique_identifier

SecureRandom.hex 32

會給出一個隨機字符串,但它的算法沒有針對唯一性進行優化。 當然,假設真正的隨機性,與 32 位發生沖突的可能性基本上是理論上的。 你可以每秒賺 10 億美元,持續 100 年,但發生碰撞的幾率只有 50%。

將 Ruby 的SecureRandom.hex函數與您想要生成的可選字符數一起使用。

這將始終產生新的 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)
end

注意:將模型替換為您的模型名稱,將列名稱替換為模型的任何現有列。

您可以通過在每次添加新文件時遞增它來分配唯一 id,並使用OpenSSL::Cipher將該 id 轉換為加密字符串,並使用您保存在某處的常量密鑰。

如果您最終生成一個十六進制或數字摘要,您可以通過將數字表示為例如 Base 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

如果限制使用的字符集對您很重要(例如,文件名中沒有大寫字符),那么只要您能找到一種輸入合適隨機數的方法,就可以輕松修改此代碼。

如果您的文件名應該是半安全的,那么您需要安排比存儲中的實際名稱更多的可能名稱。

看起來您實際上需要一個唯一的文件名,對嗎? 為什么不忘記復雜的解決方案並簡單地使用Time#nsec

t = Time.now        #=> 2007-11-17 15:18:03 +0900
"%10.9f" % t.to_f   #=> "1195280283.536151409"

您可以使用以毫秒為單位的時間,然后將其轉換為基數 36 以減少其長度。 並且由於它取決於時間,它將非常獨特。

示例: Time.now.to_f.to_s.gsub('.', '').ljust(17, '0').to_i.to_s(36) # => "4j26lna7g62"

看看這個答案: https ://stackoverflow.com/a/72738840/7365329

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM