1 2 3 4 5
class String def postal? self.match(/[a-zA-Z]{1}\d{1}[a-zA-Z]{1}([\x20-])*\d{1}[a-zA-Z]{1}\d{1}/) ? true : false end end
Refactorings
No refactoring yet !
danielharan
October 30, 2007, October 30, 2007 15:40, permalink
That ternary operator is not strictly necessary, since any MatchData object will evaluate to true. If no match exists, nil is returned. Another option is to use =~
1 2 3 4 5
class String def postal? self =~ /[a-zA-Z]{1}\d{1}[a-zA-Z]{1}([\x20-])*\d{1}[a-zA-Z]{1}\d{1}/ end end
macournoyer
October 30, 2007, October 30, 2007 15:53, permalink
I think {1} are useless, we also can make it case insensitive
1 2 3 4 5
class String def postal? self =~ /[a-z]\d[a-z]([\s-])*\d[a-z]\d/i end end
Frankie
October 30, 2007, October 30, 2007 15:58, permalink
thx everyone here for refactoring this. gary had posted this for me. Very helpful.
danielharan
October 30, 2007, October 30, 2007 16:08, permalink
Now that I'm looking at that regexp, I notice the () that aren't necessary. Also wondering if it helps to add ^ and $, and whether the * should be replaced by a ?
In any case, to answer your initial question: this seems like a good direction. It's easy to go too far, or use this type of code where ActiveRecord Validations are more appropriate. If it helps capture a common pattern and makes your code more readable, I say go for it!
1 2 3 4 5
class String def postal_code? self.strip =~ /^[a-z]\d[a-z][ -]?\d[a-z]\d$/i end end
Paul Kemper
November 5, 2007, November 05, 2007 09:55, permalink
Note that Canadian postal codes cannot start with any letter. Only [ABCEGHJKLMNPRSTVXY] are allowed as starting letters. So your regex would turn into /^[ABCEGHJKLMNPRSTVXY]\d[a-z][ -]?\d[a-z]\d$/i
Dan Kubb
December 2, 2007, December 02, 2007 16:29, permalink
According to http://en.wikipedia.org/wiki/Canadian_postal_code the letters D, F, I, O, Q, or U are excluded because OCR equipment used for automatic mail sorting confuses them with other letters and digits. The letters W and Z are also used, just not in the first character.
If you're storing this in a DB or anything, I would suggest normalizing it so that all the characters are uppercase, leading/trailing spaces are stripped, and a space (not a hyphen) is used between the first 3 characters and the last 3 characters.
1 2 3 4 5
class String def postal? self.strip.upcase =~ /\A[A-CEGHJ-NPR-TVXY]\d[A-CEGHJ-NPR-TV-Z][ -]?\d[A-CEGHJ-NPR-TV-Z]\d\z/ end end
We've had the debate over wether it was a good idea or not to do this.