【问题标题】:Prepending a UUID to route to ensure uniqueness of slug在路由前添加 UUID 以确保 slug 的唯一性
【发布时间】:2019-03-14 15:06:14
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:

    编辑

    你可以在你的路由中做这样的事情:

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

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

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

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

    由于 UUID 很难看,FriendlyId 提供了一个“slug Candidates” 让您指定在事件中使用的备用 slug 的功能 您要使用的已被占用。例如:

    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
    

    【讨论】:

    • 我碰巧遇到了这个选项,但想知道是否有一种方法可以创建模拟目录而不是添加到 slug 之前。再次查看我的帖子以获得我想要的输出。
    【解决方案2】:

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

    在您的情况下,您只需要在 slug 的末尾/开头添加一个 uuid,您可以通过使用增量 uuid 来实现这一点。如果你有当前 slug 的记录,获取最大 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 语法来匹配正则表达式模式。

    【讨论】:

    • 如果您不关心 uuid,@luisenrike 的答案会更好,它不会进行额外查询来生成我的 uuid,但如果您需要增量,您将需要我的。
    猜你喜欢
    • 2017-04-16
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多