使用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
相关产品推荐
相关产品推荐

