最初问有关用户名正则表达式的问题:Usernames that cannot start or end with characters
如何使用Ruby on Rails的正确语法实现这一目标?
这是我当前的User.rb验证:
validates_format_of :username, with: /\A[\w\._]{3,28}\z/i
此验证允许使用下划线和下划线,但目标是不允许在用户名的开头或结尾使用下划线和。
我正在尝试通过Rails regex实现这些规则:
有效:
Spicy_Pizza
97Indigos
Infinity.Beyond
无效:
_yahoo
powerup.
un__real
no..way
答案 0 :(得分:3)
您可以使用
/\A(?=.{3,28}\z)[a-zA-Z0-9]+(?:[._][a-zA-Z0-9]+)*\z/
请参见Rubular demo。
详细信息
\A
-字符串的开头(?=.{3,28}\z)
-允许/要求到字符串末尾的换行符以外的3到28个字符[a-zA-Z0-9]+
-一个或多个ASCII字母/数字(?:[._][a-zA-Z0-9]+)*
-0个以上的序列:
[._]
-一个.
或_
[a-zA-Z0-9]+
-一个或多个ASCII字母/数字\z
-字符串的结尾。答案 1 :(得分:2)
尽管完全有可能,如Wiktor的答案所示,我的建议是不要在单个正则表达式中定义它,因为:
"Invalid Format"
,它不能解释为什么无效。然后,练习留给用户重新阅读非平凡的格式规则并了解原因。相反,我建议您定义一个custom validation class,它可以分别执行这些检查(通过易于理解的方法),并在每次检查失败时添加不同的错误消息。
类似的东西:
# app/models/user.rb
class User < ApplicationRecord
validates :username, presence: true, username: true
end
# app/validators/username_validator.rb
class UsernameValidator < ActiveModel::EachValidator
def validate(record, attribute, value)
validate_length(record, attribute, value)
validate_allowed_chars(record, attribute, value)
validate_sequential_chars(record, attribute, value)
validate_first_and_last_chars(record, attribute, value)
end
private
def validate_length(record, attribute, value)
unless value.length >= 3 && value.length <= 28
record.errors[attribute] << "must be between 3 and 28 characters long"
end
end
def validate_allowed_chars(record, attribute, value)
unless value =~ /\A[._a-zA-Z0-9]*\z/
record.errors[attribute] << "must only contain periods, underscores, a-z, A-Z or 0-9"
end
end
def validate_sequential_chars(record, attribute, value)
if value =~ /[._]{2}/
record.errors[attribute] << "cannot contain two consecutive periods or underscores"
end
end
def validate_first_and_last_chars(record, attribute, value)
if value =~ /\A[._]/ || value =~ /[._]\z/
record.errors[attribute] << "cannot start/end with a period or underscore"
end
end
end
例如,您在上面问:“如果我需要扩展它以仅允许小写字母怎么办?”我认为现在很明显如何更新代码以适应这种行为,但是要明确一点-您需要做的只是:
def validate_allowed_chars(record, attribute, value)
unless value =~ /\A[._a-z0-9]*\z/
record.errors[attribute] << "must only contain periods, underscores, a-z or 0-9"
end
end
您现在还可以很容易地为这些验证检查编写测试,并断言通过对错误消息的内容进行验证来正确执行验证。 ;当所有验证失败都导致相同的错误时,这是不可能的,
此方法的另一个好处是可以轻松共享代码(也许会有一些细微的行为差异)。您可以对多个属性或多个模型执行相同的验证,也许具有不同的允许长度或格式。