Search code examples
rubyregexruby-on-rails-4slug

Rails4 : model validates "format with" regex for slug column


My model has slug with friendly ID gem, and sometimes user inputs only-digit slug and has problem with accessing pages. Then I want to change model validation except only-digit and some special chars.

Here is the current model validates

validates :slug, presence: true, length: { maximum: 200 }, uniqueness: true,
        format: {with: /\A[^\s!#$%^&*()()=+;:'"\[\]\{\}|\\\/<>?,]+\z/, message: :invalid_slug}

How can I add here??

EXAMPLE:

Current:

'123' => valid
'abc' => valid
'adb?&' => invalid

New:

'123' => invalid
'abc' => valid
'adb?&' => invalid

cheers


Solution

  • The current regex:

    /\A[^\s!#$%^&*()()=+;:'"\[\]\{\}|\\\/<>?,]+\z/
    

    Matches any string that only contains 1+ symbols other than those specified in the negated character class [^...]. So, since there are no digits, the digits are allowed in the string, and there can be 1+ digits, and the regex will match that numeric-only slug.

    To restrict this pattern to exclude matching numeric-only slugs, just add a (?!\d+\z) lookahead right after the \A anchor:

    /\A(?!\d+\z)[^\s!#$%^&*()()=+;:'"\[\]\{\}|\\\/<>?,]+\z/
       ^^^^^^^^^
    

    See the regex demo (multiline, thus, using ^ / $ anchors, you need to use \A and \z in ROR)

    This lookahead will be executed once at the beginning of the string, and will return false when it asserts (=matches) only digits (1 or more) up to the end of the string.