0

In my app I store regex in a field (value_regex) - how can I check if the field contains a valid regex?

Is there a ruby function for it or a regex to do it?

Edit

Based on the input below, in my model tag.rb I have added:

validate :valid_regex

and the Method below (which I want to extend for another regex field key_regex too. First how to handle the exceptions/errors. I could not find documentation sofar:

def valid_regex
  unless Regexp.new(value_regex)
    errors.add(:value_regex, "not a valid regular expression")
  end
end

Or easier

def valid_regex
  @valid_regex ||= Regexp.new(self.value_regex)
end

How to catch the RegexpError(s) and output the message as an error (errors.ad?)?

Dimitri de Ruiter
  • 725
  • 2
  • 7
  • 26
  • 1
    What do you define as valid regex? `.\+dac3.+' is valid regex too right? Anyway, the idea of using regex to validate regex is not unheard of. Read here if you are up to it. http://stackoverflow.com/questions/172303/is-there-a-regular-expression-to-detect-a-valid-regular-expression – Jeff Oct 20 '16 at 21:24

3 Answers3

2
@valid_value_regex ||= Regexp.new(self.value_regex)
rescue => exception
errors.add(:value_regex, exception)
Dimitri de Ruiter
  • 725
  • 2
  • 7
  • 26
2

You'll have to rescue the exception and put the message into errors. Try this:

def valid_regex
  Regexp.new(value_regex.to_s)
rescue RegexpError => e
  errors.add(:value_regex, e.message)
end
John Cleary
  • 957
  • 8
  • 9
1

If you have a regular expression stored as a string you can convert it back to a regular regular expression:

string = 'test.*'
Regexp.new(string)
# => /test.*/

You might want to write a wrapper method in your model:

class Example < ActiveRecord::Base
  def matching_regex
    @matching_regex ||= Regexp.new(self.matching)
  end
end

Where matching is the original column with the string value.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • It seems like `Regexp.new` is pretty permissive. If passed `1` it will return `/1/` and if passed `//` it will return `//`. But if passed `{}` it will raise a type error. What I'm trying to say is that I don't see a situation where passing a string to `Regexp.new` will fail - and rescuing these failures is OP's question. – max pleaner Oct 20 '16 at 21:29
  • 1
    `Regexp.new` throws a `RegexpError` if the regular expression is invalid. For example: `Regexp.new("(.*")` – max Oct 20 '16 at 21:34
  • There's two concerns here: One is that the regular expression is blatantly invalid, that is when constructed returns `RegexpError`, which is easily caught. The second is that it's *hostile* and when executed will take forever to run, potentially crashing the service. The second is far harder to detect, and can even happen accidentally. These aren't arbitrary code injection points, but they're not far from it, so be careful who has access to edit these. – tadman Oct 20 '16 at 21:39