我是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
,但它从未被触发。我错过了什么?
normalize_friendly_id
仅在使用slugged
模块使用slug
列来存储和查找该列时调用:
friendly_id :code, use: :slugged
使用这个你可以重写normalize_friendly_id
方法。
Sunny的方式可能是一般的方式,因为slugged
模块需要编辑内部方法,如normalize_friendly_id
。
在我的例子中,我已经有一个唯一的code
属性。使用slugged
模块将创建一个名为slug
的新属性,该属性将是,与我的code
完全相同。我想避免重复。
最后,我决定避开friendly_id
gem并直接覆盖我的模型中的to_param
方法(受此要点的启发):
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
如果我遇到任何副作用,我会编辑这个答案,但现在它是有效的。