将正则表达式存储在数据库

时间:2012-10-25 11:26:26

标签: ruby-on-rails regex activerecord eval

我需要使用ActiveRecord存储与数据库表中其他字段相关的正则表达式。

我发现Regexp类中的to_s方法表明了

  

返回包含正则表达式及其选项的字符串   (使用(?opts:source)表示法。这个字符串可以反馈到   Regexp :: new到正则表达式,其语义与   原版的。 (但是,比较时,Regexp#==可能不会返回true   二,正则表达式本身的来源可能不同,如   示例显示)。 Regexp#inspect通常更具可读性   版本的rxp。

所以它似乎是一个有效的解决方案,但它将使用不寻常的语法存储exp,为了获得要存储的字符串,我需要使用/my-exp/.to_s手动构建它。此外,我可能无法直接编辑到regexp。例如,一个简单的正则表达式产生:

/foo/i.to_s # => "(?i-mx:foo)" 

另一个选项是评估字段内容,以便我可以将简单表达式存储在db列中,然后执行eval(record.pattern)以获得实际的正则表达式。这是有效的,因为我是唯一一个负责管理正则表达式记录的人,除了应用程序错误之外,应该没有问题; - )

我还有其他选择吗?我不喜欢在db字段上做eval,但另一方面我不想使用我不知道的语法。

3 个答案:

答案 0 :(得分:4)

使用serialize按原样存储正则表达式

class Foo < ActiveRecord::Base
  serialize :my_regex, Regexp
end

请参阅API doc了解详情。

答案 1 :(得分:2)

不确定我是否完全理解你的约束。

如果在db中存储字符串,可以从中创建一个Regexp:

a = 'foo'
=> "foo" 
/#{a}/
=> /foo/
Regexp.new('dog', Regexp::EXTENDED + Regexp::MULTILINE + Regexp::IGNORECASE) 
=> /dog/mix

还有其他构造函数,see doc

不使用eval'd代码的最佳解决方案是将regexp部分存储在字符串列中,并将标记存储在单独的整数列中。通过这种方式,可以使用以下内容构建正则表达式:

record = Record.new pattern: 'foo', flags: Regexp::IGNORECASE
Regexp.new record.pattern, record.flags # => /foo/i

答案 2 :(得分:2)

您可以在正则表达式中使用#{}来插入变量,因此您可以通过将“foo”作为字符串存储在record.pattern下的db中来插入经过仔细清理的regexp,然后使用以下命令对其进行评估:

/#{record.pattern}/

所以,在db中,你会存储:

"pattern"

在您的代码中,您可以这样做:

if record.other_field =~ /#{record.pattern}/
  # do something
end

这将从您可以更改的数据库中的动态字符串编译正则表达式,并允许您在代码中使用它。出于安全考虑,我不会推荐它,见下文:

显然这可能很危险,因为正则表达式可以包含ruby代码,所以这更简单,但就危险而言,它类似于eval:

a = "foo"
puts a
=> foo
b = "#{a = 'bar'}"
a =~ /#{b}/ 
puts a 
=> bar

您可能最好考虑是否为了安全性,将您的正则表达式测试分解为可以映射到您在代码中编写的方法的内容,因此您可以在数据库中存储键以获取约束,例如:

'alpha,numeric'等

然后根据存储的密钥进行硬编码测试。也许在这里查看有关提示的rails验证,虽然它们存储在代码中,但它可能是最好的方法(概括您的需求,并将代码保留在db之外)。即使你现在不认为你需要安全性,你可能会在以后想要它,或者忘记这一点并授予恶意访问权限。