Fabio
Fabio

Reputation: 19176

Store regular expression in database

I need to store a regular expression related to other fields in a database table with ActiveRecord.

I found the to_s method in Regexp class which states

Returns a string containing the regular expression and its options (using the (?opts:source) notation. This string can be fed back in to Regexp::new to a regular expression with the same semantics as the original. (However, Regexp#== may not return true when comparing the two, as the source of the regular expression itself may differ, as the example shows). Regexp#inspect produces a generally more readable version of rxp.

So it seems a working solution, but it will store the exp with an unusual syntax and in order to get the string to store I need to build it manually with /my-exp/.to_s. Also I may not be able to edit to regexp directly. For instance a simple regexp produces:

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

The other option is to eval the field content so I might store the plain expression in the db column and then doing an eval(record.pattern) to get the actual regexp. This is working and since I'm the only one who will be responsible to manage the regexp records there should be no issues in doing that, except application bugs ;-)

Do I have other options? I'd prefer to not doing eval on db fields but on the other side I don't want to work with a syntax which I don't know.

Upvotes: 2

Views: 4591

Answers (2)

apneadiving
apneadiving

Reputation: 115521

Not sure I understand your constraints exactly.

If you store a string in db, you could make a Regexp from it:

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

There are other constructors, see doc.

The very best solution to not use eval'd code is to store the regexp part in a string column and flags in a separate integer column. In this way the regexp can be built with:

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

Upvotes: 3

m_x
m_x

Reputation: 12554

use serialize to store your regex 'as-is'

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

see the API doc to learn more about this.

Upvotes: 5

Related Questions