I want a rails model to exclude certain patterns: runs of two or more spaces.
User.name = "Harry Junior Potter"
is valid, but User.name = "Harry Junior Potter"
is not (two spaces between Harry and Junior).
This to avoid identity theft, where those two names are displayed the same (HTML compresses runs of whitespace).
In other words: Allowed is: [0-9A-z_-]
and '\s
only in series of one'.
My regular-expression is too poor to craft such a regexp, this is what I have (with a negative lookahead, but it does not match correctly.
/([0-9A-z_\-])(\s(?!\s))?/
Note: a before_validation hook already s开发者_运维问答trip()s all the elements, so spaces at begin or end of the string are not a problem.
First off, [A-z]
is an error. It's equivalent to
[A-Z\[\\\]^_`a-z]
...and I'm pretty sure that's not what you had in mind. You have to spell out the two ranges separately: [A-Za-z]
. But in this case you're also matching digits and underscore, so you can use \w
like @Sjuul did: [\w-]+
. That makes your regex
/^[\w-]+(?: [\w-])*$/
Of course, that will match silly things like -- - ---
, and it won't match a lot of real names. I'm just answering your question about allowing only a single space between names.
Isn't it a lot easier just to replace "__" with "_"
? (Using underscores to show the spaces)
My Ruby isn't that fluent but it should be something like
User.name.replace!(" ", " ") while User.name.contains(" ")
Then you could use this regex to check for the rest
([\w\-]+\s?)+
I would suggest an alternate route.. a very weird one in fact. If you are on a time crunch and would not bother having an extra column in your existing table then i would suggest creating a slug of the user-name. I know its an overkill for your problem. But i prefer doing my checks that way. Instead of checking the new user-name against the already stored one(and breaking my head over all those messy regexs), i just check the new slug against the stored slug(which by the way, handle all those messy regexs for you). You can check out to_slug: http://github.com/ludo/to_slug
Slugs are used primarily to filter out dangerous characters from URLs. Why not utilize the same for checking user-names? It handles unicode characters too.
This is not a direct answer to your problem. But i faced the same situation as you did and since i was on a time crunch i decided to use slugs.
A simple check in my console yields:
>> "Harry Junior Potter".to_slug
=> "harry-junior-potter"
>> "Harry Junior Potter".to_slug
=> "harry-junior-potter"
>> "Harry Junior Potter".to_slug
=> "harry-junior-potter"
>> "Harry(junior(potter))".to_slug
=> "harry-junior-potter"
>> "Harry_Junior_Potter".to_slug
=> "harry_junior_potter"
So, now if and only if the slug validates the user is allowed to store his name.
精彩评论