Ruby on rails 如何根据模式检查用户输入?
在我的RubyonRails应用程序中,我需要根据由字母、数字和一些特殊字符(如破折号和下划线)组成的模式检查用户输入,但我不知道如何做 例如,如果模式为Ruby on rails 如何根据模式检查用户输入?,ruby-on-rails,ruby,Ruby On Rails,Ruby,在我的RubyonRails应用程序中,我需要根据由字母、数字和一些特殊字符(如破折号和下划线)组成的模式检查用户输入,但我不知道如何做 例如,如果模式为LL-NNNN,并且用户提交字符串AB-0001,则该模式有效 如果模式为NN-LL,且用户提交77-ABC,则该模式无效 我曾考虑将每个模式转换为正则表达式,但由于每个用户都可以定义自己的模式(这意味着会有很多模式),我担心这可能会导致意外的结果 有谁能告诉我解决这个问题的最佳方法吗?您可以在我们的模型中使用这个方法 validates_fo
LL-NNNN
,并且用户提交字符串AB-0001
,则该模式有效
如果模式为NN-LL
,且用户提交77-ABC
,则该模式无效
我曾考虑将每个模式转换为正则表达式,但由于每个用户都可以定义自己的模式(这意味着会有很多模式),我担心这可能会导致意外的结果
有谁能告诉我解决这个问题的最佳方法吗?您可以在我们的模型中使用这个方法
validates_format_of :your_field_name, with: /(your regex)/i, on: :create
在循环中,检查输入字符串中的每个字符是否满足相应的模式字符
def match?(pattern, input)
return false if pattern.length != input.length
pattern.each_char.with_index.all? do |char, i|
case char
when 'L' then input[i] =~ /[A-Z]/
when 'N' then input[i] =~ /[0-9]/
when '-' then input[i] == '-'
else raise 'invalid pattern'
end
end
end
match?('LL-NNNN', 'AB-1234') #=> true
match?('NN-LL', '77-ABC') #=> false
match?('NN-LL', '77-99') #=> false
match?('NN-LL', '77-AB') #=> true
因为我们非常喜欢Ruby中的一行程序,这里有一个快速的破解 用相应的模式字符替换输入字符:
'AB-1234'.gsub(/[A-Z]/, 'N') #=> "NN-1234"
.gsub(/[0-9]/, 'L') #=> "NN-LLLL"
并将结果与模式进行比较:
'AB-1234'.gsub(/[A-Z]/, 'N').gsub(/[0-9]/, 'L') == 'NN-LLLL'
#=> true
如果模式总是由字母、
N=>number
和-
组合而成,则可以使用regex.new(value)
将其转换为正则表达式
无论哪种情况,整个事情都是这样
def match(pattern, value)
/\A#{pattern.gsub(/[LN]/, 'L' => '[a-zA-Z]', 'N' => '\d')}\z/.match(value)
end
这只适用于大写字母
def match(pattern, value)
/\A#{pattern.gsub(/[LN]/, 'L' => '[A-Z]', 'N' => '\d')}\z/.match(value)
end
您甚至可以尽早将正则表达式转换为正则表达式格式,并将正则表达式存储在数据库中,而不是存储在模式中,以优化处理时间
def regex_from_pattern(pattern)
"\\A#{pattern.gsub(/[LN]/, 'L' => '[a-zA-Z]', 'N' => '\d')}\\z"
end
def match(regex_string, value)
Regexp.new(regex_string).match(value)
end
您可以创建regexp生成器和
regexp.escape
将对您有所帮助。
假设您已经设置了用户定义的模式字母表:
ALPHABET = 'LN-_:=.\\'
然后,您可以检查用户的模式是否正确:
PATTERN_REGEXP = Regexp.new('\A[%s]+\z' % Regexp.escape(ALPHABET))
def is_pattern_ok?(pattern)
PATTERN_REGEXP =~ pattern
end
下一步是根据他的模式创建用户定义的输入regexp字符串:
def regexp_str_from(pattern)
('\A%s\z' % Regexp.escape(pattern))
.gsub('N', '\d')
.gsub('L', '[a-zA-Z]'))
end
并将其保存在数据库的用户设置中的某个位置。
因此,您可以使用用户定义的模式验证用户输入:
Regexp.new(regexp_str) =~ user_input
已编辑:注意:
Regexp.escape
是必需的,以避免“意外结果”。模式是否特定于用户?每个用户都有自己的模式?@SergioTulentsev:是的。好吧,但是你如何用'LL-NNNN'
构造/(你的正则表达式)/i
?你想根据用户输入的内容创建正则表达式吗?模式也是用户定义的:“每个用户都可以定义自己的模式”,我试图用'AB-0001.tr(“A-z”,“L”)做一些不同的事情.tr(“0-9”,“N”)
。或者/\A#{pattern.gsub(/[LN]/,'L'=>'[A-Z]','N'=>'\d')}\Z/
@Stefan,对于运行时转换选项,它看起来更干净。更新这些。谢谢。\w
匹配包含字母但也包含数字和下划线的单词字符,您需要在regexp\u stru from(pattern)函数中用[a-zA-Z]
或[a-Z]
替换\w
,以适应所描述的模式