预先放置UUID进行路由以确保子弹的唯一性

时间:2018-10-09 19:04:28

标签: ruby-on-rails routing friendly-id

我正在使用friendly_id向我的模型及其相应的url添加自定义块。目前,我有一个Post属于Board的设置。毫无疑问,在某些情况下,某个职位的标题与另一个职位相同,但董事会成员不同。通常,我注意到网站(包括SO)在投放之前会添加一组唯一的数字,以确保不存在唯一性问题:

https://stackoverflow.com/questions/123456/my-example-question

我想知道实现这一目标的最佳方法是什么?不能仅通过路由文件来完成此操作,因为仍然存在创建两个或更多相同帖子的可能性。会改变我的模型,路线文件和friendly_id gem的配置吗?

我的最终目标是为我的帖子生成一个这样的网址:

https://example.com/boards/example-board/123456/example-post

class Board < ApplicationRecord
  extend FriendlyId

  has_many :posts

  friendly_id :name, use: :slugged
end


class Post < ApplicationRecord
  extend FriendlyId

  belongs_to :board

  friendly_id :title, use: :slugged
end

resources :boards do
  scope module: :boards do
    resources :posts
  end
end

2 个答案:

答案 0 :(得分:1)

编辑

您可以在路线中执行以下操作:

resources :boards do
  resources :posts, path: ':board_real_id'
end

并将params[:board_real_id]添加到您的查询中。

OLD

我认为您不需要为此的UUID(除非您愿意)。您可以使用candidates,如果两个帖子具有相同的名称,并且它们属于同一板,只需插入帖子的ID,就可以了,您将得到类似https://example.com/boards/example-board/123456-example-post

发件人:http://norman.github.io/friendly_id/file.Guide.html

  

由于UUID丑陋,因此FriendlyId提供了“子弹候选”   功能,可让您指定在事件中使用的备用弹头   您要使用的已被使用。例如:

friendly_id :slug_candidates, use: :slugged

  # Try building a slug based on the following fields in
  # increasing order of specificity.
  def slug_candidates
    [
      :name,
      [:id, :name]
    ]
  end

答案 1 :(得分:0)

您需要使用slug_candidates,请参阅文档here

在您的情况下,您所需要的只是在子段的末尾/开头添加一个uuid,您可以使用增量uuid来实现。如果您有当前子弹的记录,请获取最大uuid并将其增加1,然后保存!

class Post < ApplicationRecord
  extend FriendlyId

  belongs_to :board

  friendly_id :slug_candidates, use: :slugged


  def slug_url
    name
  end

  def slug_candidates
    [:slug_url, [:slug_url, :slug_uuid]]
  end

  def slug_uuid
    result = Post.select("COUNT(REGEXP_SUBSTR(name, '[0-9]+$')) AS cnt, MAX(REGEXP_SUBSTR(title, '[0-9]+$')) + 1 AS mx_uuid")
    result.cnt == 0 ? "" : result.mx_uuid + 1
  end
end
  

我正在使用MYSQL语法来匹配正则表达式模式。