我的 normalize_friendly_id 覆盖从未被调用

My normalize_friendly_id override is never called

我是 friendly_id 的新手,它符合我提供友好 URL 的需要

我有一个 Group 模型(即一组用户),我在创建时为其生成了一个唯一的 code。仅供参考,此 code 属性在我的 PostgreSQL 数据库中设置为唯一索引。

class Group < ApplicationRecord
  include FriendlyId
  friendly_id :code

  after_create :generate_group_code

  private

  def normalize_friendly_id(value)
    super.upcase
  end

  def generate_group_code(size = 8)
    allowed_chars = ("a".."z").to_a
    code = (1..size).map { allowed_chars[rand(26)] }.join while Group.exists?(code: code)

    update(code: code)
  end
end

我想我已经正确地遵循了 gem 的指南,我只希望生成的 code 在 URL 中大写(即 /group/ABCDEFGH)。

friendly_id 确实设置为我的 code 属性,但没有大写。我在 normalize_friendly_id 方法中放置了一个 byebug,但它从未被触发。我错过了什么?

只有在使用slugged模块时才调用normalize_friendly_id,使用slug列来存储,通过该列查找:

friendly_id :code, use: :slugged

然后您可以使用它覆盖 normalize_friendly_id 方法。

可能是一般的方法,因为需要 slugged 模块来编辑内部方法,例如 normalize_friendly_id.

在我的例子中,我已经有一个唯一的 code 属性。使用 slugged 模块将创建一个名为 slug 的新属性,它与我的 code 完全 相同。我想避免这种重复。

最后,我决定避开friendly_id gem,直接重写我模型的to_param方法(启发by this gist):

class Group < ApplicationRecord
  validates :code, format: { with: /\A[a-z]{8}\z/ }, uniqueness: true, on: :update

  after_create :generate_group_code
  
  # Override the method to allow '/group/MYGROUPA' paths 
  def to_param
    code.upcase
  end

  # A group code is made of letters exclusively.
  # Converting a String (or nil) to an integer leads to 0.
  # In this case, lookup by code, otherwise, lookup by id.
  # Note the 'downcase', which allows URLs to be case insensitive.
  def self.find(input)
    input.to_i == 0 ? find_by_code!(input.downcase) : super
  end

  private

  def generate_group_code(size = 8)
    allowed_chars = ("a".."z").to_a
    code = (1..size).map { allowed_chars[rand(26)] }.join while Group.exists?(code: code)

    update(code: code)
  end
end

如果我遇到任何副作用,我会编辑这个答案,但现在它有效。