在路线中使用字母数字段而不是 id - Rails

Posted

技术标签:

【中文标题】在路线中使用字母数字段而不是 id - Rails【英文标题】:Using alpha-numeric slugs instead of ids in routes - Rails 【发布时间】:2017-07-17 15:33:04 【问题描述】:

我正在构建一个 Rails 5 团队管理应用程序,让用户可以管理组织和用户。我希望能够从在路径中使用 :id 进行更改(例如:/organizations/43)并改用字母数字段(例如:/organizations/H6Y47Nr7)。类似于 Trello 执行此操作的方式(即:https://trello.com/b/M9X71pE6/board-name)。有没有简单的方法可以做到这一点?

我已经看到FriendlyId gem 可以处理路径中的 slugging,但是首先生成 slug 的最佳方法是什么?

理想情况下,为了最物超所值,slug 将包括 AZ、az 和 0-9(据我了解,这是 Base58?)并且为了不破坏 url太多了,最多8个字符。如果我的计算是正确的,这给出了 218 万亿个组合,应该很多。

我在正确的轨道上吗?任何帮助将不胜感激。

谢谢

【问题讨论】:

您可以查看hashids gem,它支持自定义字符数和要包含在 slug 中的字符。我最近为此制作了一个导轨plugin,但我还没有在生产中使用它们。 看看我的旧答案***.com/a/16096646/1297435 【参考方案1】:

如果你走这条路,我会创建一个表,如果你保存你正在生成的 slug 并且即使你删除一个组织也不删除它们。当您创建新组织时,请查询此模型以确保没有重复的 slug。还要在 organizations 表的 slug 列中添加唯一索引。

你不应该放弃带有整数的 id 列,所以在 show 方法中你需要这样做:

org = Organization.where(slug: params[:id]).first

【讨论】:

【参考方案2】:

要创建 slug,最简单的方法是使用 SecureRandom。您可以在模型中添加如下内容

before_create :generate_slug

private

def generate_slug
  begin
    self.slug = SecureRandom.urlsafe_base64(8)
  end while Organization.exists?(slug: slug)
end

关于你想要的一个小警告是,slug 有时会包含下划线或破折号,但这应该没问题。

irb(main):014:0> SecureRandom.urlsafe_base64(8)
=> "HlHHV_6rN3k"
irb(main):015:0> SecureRandom.urlsafe_base64(8)
=> "naRqT-NmYDU"
irb(main):016:0> SecureRandom.urlsafe_base64(8)
=> "9h04l4jEEsM"

【讨论】:

感谢您的回复。我不能只使用SecureRandom.base58(8) 吗?它返回类似KBz4i9ux 另外,如何处理碰撞?或者SecureRandom 会处理它吗?再次感谢! 不熟悉base58。我之所以使用urlsafe_base64 是因为您需要一个 url 安全的字符串。至于碰撞,发生比赛条件的可能性很小,但我不会担心 我明白了。谢谢。据我了解,base58 与 base64 类似,只是它省略了标点符号和模棱两可的字符(即:0 和 O,以及 I 和 l),因此仍然是 URL 安全的。

以上是关于在路线中使用字母数字段而不是 id - Rails的主要内容,如果未能解决你的问题,请参考以下文章

URL 本身而不是之后的 URL 参数?在 Rails 中

rails 6中没有针对多个路线参数的路线匹配

ID 按字母顺序而不是数字顺序

Rails 6 路线 - 简单嵌套路线的正确方法

sequelize.js 中的字母数字 ID

在Rails4的路由资源中更改parent:parent_id参数的名称