Rails 验证 ASCII 近似值的唯一性
Rails validate uniqueness for the ASCII approximation
希望标题不要太不清楚。
我正在制作一个rails 应用程序,我对rails 验证有疑问。考虑 User,rb 模型文件中的这段代码:
validates :name,
presence: true,
length: { maximum: 50 },
uniqueness: { case_sensitive: false }
我正在使用 friendly_id gem 为用户生成 slug。我不会允许用户更改他们的名字。我现在需要的是确保名称是唯一的,如果两个人在 ascii 近似值中转换了相同的名称,则不会有 UUID 附加到 slugs。
当前行为是:
用户 1 使用名称注册并获得这样的 slug:
name: "Jaiel" slug: "jaiel"
用户 2 现在使用相同的名称但有点不同:
name: "Jàìèl" slug: "jaiel-6558c3f1-e6a1-4199-a53e-4ccc565657d4"
如您所见,这里的问题我想要这样的唯一性验证,即用户 2 会被拒绝,因为这两个名称都会为其 friendly_id 的
生成 slug "jaiel"
非常感谢你在这件事上的帮助
谢谢
看看 ActiveSupport::Inflector.transliterate
:
ActiveSupport::Inflector.transliterate('Ærøskøbing')
#=> "AEroskobing"
此外,对于这种类型的验证,您可能希望使用自定义验证(以及您已有的验证):
class User
validate :unique_slug
private
def unique_slug
names = self.class.all.map(&:asci_name)
raise ActiveRecord::RecordInvalid.new(self) if names.include?(asci_name)
end
def asci_name
ActiveSupport::Inflector.transliterate(name)
end
end
显然,在每次验证时查询整个 table 非常低效,但这只是为您指出一个可能的方向。
另一种选择是回调。创建时音译名称:
before_validation: :transliterate_name
def transliterate_name
self.name = ActiveSupport::Inflector.transliterate(name)
end
它将首先音译名称,然后使用您的验证来验证已音译名称的唯一性。看起来像一个解决方案,绝对没有最初的那么重。
希望标题不要太不清楚。
我正在制作一个rails 应用程序,我对rails 验证有疑问。考虑 User,rb 模型文件中的这段代码:
validates :name,
presence: true,
length: { maximum: 50 },
uniqueness: { case_sensitive: false }
我正在使用 friendly_id gem 为用户生成 slug。我不会允许用户更改他们的名字。我现在需要的是确保名称是唯一的,如果两个人在 ascii 近似值中转换了相同的名称,则不会有 UUID 附加到 slugs。
当前行为是:
用户 1 使用名称注册并获得这样的 slug:
name: "Jaiel" slug: "jaiel"
用户 2 现在使用相同的名称但有点不同:
name: "Jàìèl" slug: "jaiel-6558c3f1-e6a1-4199-a53e-4ccc565657d4"
如您所见,这里的问题我想要这样的唯一性验证,即用户 2 会被拒绝,因为这两个名称都会为其 friendly_id 的
生成 slug "jaiel"非常感谢你在这件事上的帮助
谢谢
看看 ActiveSupport::Inflector.transliterate
:
ActiveSupport::Inflector.transliterate('Ærøskøbing')
#=> "AEroskobing"
此外,对于这种类型的验证,您可能希望使用自定义验证(以及您已有的验证):
class User
validate :unique_slug
private
def unique_slug
names = self.class.all.map(&:asci_name)
raise ActiveRecord::RecordInvalid.new(self) if names.include?(asci_name)
end
def asci_name
ActiveSupport::Inflector.transliterate(name)
end
end
显然,在每次验证时查询整个 table 非常低效,但这只是为您指出一个可能的方向。
另一种选择是回调。创建时音译名称:
before_validation: :transliterate_name
def transliterate_name
self.name = ActiveSupport::Inflector.transliterate(name)
end
它将首先音译名称,然后使用您的验证来验证已音译名称的唯一性。看起来像一个解决方案,绝对没有最初的那么重。