Ruby on Rails - 生成 bit.ly 样式标识符
Posted
技术标签:
【中文标题】Ruby on Rails - 生成 bit.ly 样式标识符【英文标题】:Ruby on Rails - generating bit.ly style identifiers 【发布时间】:2010-07-19 14:42:53 【问题描述】:我正在尝试生成与 bit.ly url 样式相同的 UUID,例如:
http://bit [dot] ly/aUekJP
或 cloudapp 的:
http://cl [dot] ly/1hVU
甚至更小
我该怎么做? 我现在将 UUID gem 用于 ruby,但我不确定是否可以限制长度并获得类似的东西。 我目前正在使用这个:
UUID.generate.split("-")[0] => b9386070
但我想要更小,并且知道它会是独一无二的。
任何帮助将不胜感激:)
编辑说明:用[dot]
替换点字母以获得banned short link 的解决方法
【问题讨论】:
【参考方案1】:你在这里混淆了两个不同的东西。 UUID 是一个通用的唯一标识符。即使全世界同时创造了数百万个,它也很有可能是独一无二的。它通常显示为 36 位字符串。您不能去掉前 8 个字符并期望它是唯一的。
tinyurl 等人存储链接并生成一个短代码来表示该链接。他们不会从他们在数据存储中查找的代码重构 URL 并返回相应的 URL。这些不是 UUIDS。
在不了解您的应用程序的情况下,很难建议您应该使用哪种方法,但是您可以使用数字键将您指向的任何内容存储在数据存储中,然后使用 10 位和 22 位将键重新设置为 base32小写字母,或许可以避免明显的错字问题,如 'o' 'i' 'l' 等
编辑
在进一步调查中,有一个 Ruby base32 gem 可用,它实现了 Douglas Crockford 的 Base 32 implementation
一个 5 个字符的 Base32 字符串可以表示超过 3300 万个整数,一个 6 位字符串可以表示超过 10 亿个。
【讨论】:
感谢史蒂夫的信息,是的,我想我真的误解了 uuid 原则:/ base32 gem 看起来很不错,我只是想找出一种基于记录 id,我之前使用的是字符串 ID 并将 UUID 方法分配给它,但我想现在我可以返回一个整数 ID,然后例如,如果在 363012 处开始 id 计数,我会得到一个 ' B2G4' 字符串表示。我希望这可以与您在上面解释的相同。 @ludicco。这正是我要说的。 @SteveWeet 感谢您推荐的 base32 gem【参考方案2】:如果你正在处理数字,你可以使用内置的 ruby 方法
6175601989.to_s(30)
=> "8e45ttj"
回去
"8e45ttj".to_i(30)
=>6175601989
因此您不必存储任何内容,您可以随时解码传入的短代码。
这适用于概念验证,但您无法避免模棱两可的字符,例如:1lji0o。如果您只是想使用代码来混淆数据库记录 ID,这将正常工作。一般来说,短代码应该很容易记住并从一种媒体转移到另一种媒体,比如在某人的演示幻灯片上阅读它,或者通过电话听到它。如果您需要避免难以阅读或难以“听到”的字符,您可能需要切换到生成可接受代码的过程并将其存储。
【讨论】:
to_i
接受高达 36 的基数,因此您可以将更多信息打包成几个字符。【参考方案3】:
我发现这简短而可靠:
def create_uuid(prefix=nil)
time = (Time.now.to_f * 10_000_000).to_i
jitter = rand(10_000_000)
key = "#jitter#time".to_i.to_s(36)
[prefix, key].compact.join('_')
end
这会输出如下所示的唯一键:'3qaishe3gpp07w2m' 减小“抖动”大小以减小密钥大小。
警告: 这不能保证是唯一的(为此使用 SecureRandom.uuid),但它非常可靠:
10_000_000.times.map create_uuid.uniq.length == 10_000_000
【讨论】:
【参考方案4】:保证唯一性的唯一方法是保持全局计数并为每次使用递增:0000
、0001
等。
【讨论】:
以上是关于Ruby on Rails - 生成 bit.ly 样式标识符的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 ruby on rails 生成人类可读的时间范围