You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Rails 5,如何让FriendlyId为重复slug追加-count+1而非UUID?

把FriendlyId改回数字序列式的slug唯一规则

我之前也踩过这个坑!新版本的FriendlyId确实把默认的重复slug追加数字的逻辑换成UUID了,官方说是为了简化并发场景下的处理,但对于咱们想要简洁URL的需求来说,这个改动反而有点麻烦。不过没关系,咱们可以自定义一个slug生成器来恢复原来的行为。

下面是具体的实现步骤:

  • 第一步:创建自定义slug生成模块
    在你的Rails项目里新建一个concern文件,比如app/models/concerns/sequential_slug_generator.rb,把下面的代码放进去:

    module SequentialSlugGenerator
      extend ActiveSupport::Concern
    
      included do
        # 启用slugged功能,使用我们自定义的sequential_slug方法生成slug
        friendly_id :sequential_slug, use: :slugged
      end
    
      private
    
      def sequential_slug
        # 这里的title替换成你用来生成slug的实际字段(比如name、title等)
        base_slug = normalize_friendly_id(title)
        # 查询所有以base_slug开头的现有slug
        existing_slugs = self.class.where("slug LIKE ?", "#{base_slug}%").pluck(:slug)
    
        if existing_slugs.empty?
          # 没有重复的话直接用base_slug
          base_slug
        else
          # 提取所有带数字后缀的slug,找到最大的数字加1
          max_suffix = existing_slugs.map do |slug|
            suffix = slug.split("-").last
            suffix.match?(/^\d+$/) ? suffix.to_i : 0
          end.max
          "#{base_slug}-#{max_suffix + 1}"
        end
      end
    end
    
  • 第二步:在模型中引入这个模块
    打开你需要使用这个规则的模型(比如Post、Product),引入刚才创建的模块:

    class Post < ApplicationRecord
      include SequentialSlugGenerator
    end
    
  • 第三步:为现有记录重新生成slug(可选)
    如果你的模型已经有数据了,可以在Rails控制台里执行下面的命令,给现有记录更新成数字序列的slug:

    Post.find_each(&:save)
    

一些注意事项:

  • 记得把代码里的title替换成你实际用来生成slug的字段,比如你的模型用name字段就改成name
  • 这个实现的并发处理确实不如官方的UUID方式稳妥,但你说目前不需要并发支持,所以完全够用
  • 如果需要处理特殊字符或者自定义slug的归一化规则,可以调整normalize_friendly_id的逻辑,或者自己实现一个归一化方法

其实官方文档里也提到了自定义slug生成器的扩展方式,只是没有给出数字序列的具体示例,这个方案就是基于官方的扩展机制来做的,完全兼容FriendlyId的其他功能。

内容的提问来源于stack exchange,提问作者chrickso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:58:15