Reputation: 479
I need to validate input evidence number as per following formats in my model.
XXX-###
XXX-####
XXX-#####
XXX-######
XXXX-#####
XXXX are alphabets and #### are numeric digits
I have following in my model code.
validates_format_of :evidence_number, :with=> /[A-Z a-z]{3}-\d{3,6}/
It only works for digits less than 3 ie it works for XXX-12 but does not work for digits more than 6 i.e. it does not work for XXX-1234567
Upvotes: 0
Views: 769
Reputation: 33171
Try adding the ^
starts and $
ends with.
validates_format_of :evidence_number, :with=> /^[A-Za-z]{3,4}-\d{3,6}$/
Use mu is too short
's answer though.
Upvotes: 1
Reputation: 434675
You should be using the \A
(beginning of string) and \z
(end of string) anchors, not ^
(beginning of line) and $
(end of line):
validates_format_of :evidence_number, :with=> /\A[A-Z a-z]{3}-\d{3,6}\z/
A simple example will illustrate the difference:
>> "wrong\nXXX-999\nanchors" =~ /^[A-Z a-z]{3}-\d{3,6}$/
=> 6
>> "wrong\nXXX-999\nanchors" =~ /\A[A-Z a-z]{3}-\d{3,6}\z/
=> nil
>> "XXX-999" =~ /^[A-Z a-z]{3}-\d{3,6}$/
=> 0
>> "XXX-999" =~ /\A[A-Z a-z]{3}-\d{3,6}\z/
=> 0
You almost always want to use \A
and \z
instead of ^
and $
in Ruby.
If you need "at least three digits" after the hyphen then you want:
/\A[A-z a-z]{3}-\d{3,}\z/
And Kenny Grant is right, that space in the character class looks odd.
Upvotes: 3
Reputation: 9623
You might be best to set up some test code, and test the regex separately (or ideally set up a unit test and test it that way).
invalid = %w[777-2345 ABCD-12 ABCD-12345678 AB-12345678 ABC-1234567]
valid = %w[ABC-12345 ABCD-123 ABCD-1234 ABCD-12345 ABCD-123456]
def validate codes,regex
codes.each do |code|
if code =~ regex
puts "Valid code #{code}"
else
puts "Invalid code #{code}"
end
end
end
When testing the above with your regex, some problems emerge. From your description, I don't understand why your regex includes a space as an allowed character - for codes this seems unlikely to be a valid code. So you might be better with something like this:
/\A[A-Za-z]{3,4}-\d{3,6}\z/
Which limits the match to a full string, and limits the first match to 3 or 4 alpha characters, and the final match to 3-6 numbers. This is assuming the #### is not a mistake in your examples:
puts "\n\nUSING NEW REGEX"
puts "Validating valid codes"
validate valid,/\A[A-Za-z]{3,4}-\d{3,6}\z/
puts "\nValidating INVALID codes"
validate invalid,/\A[A-Za-z]{3,4}-\d{3,6}\z/
Upvotes: 1
Reputation: 160191
Add beginning- and end-of-string regex chars:
validates_format_of :evidence_number, :with=> /^[A-Z a-z]{3}-\d{3,6}$/
ruby-1.9.3-p125 :000 > "ABC-1234567".match /[A-Z a-z]{3}-\d{3,6}/
=> #<MatchData "ABC-123456">
ruby-1.9.3-p125 :001 > "ABC-1234567".match /^[A-Z a-z]{3}-\d{3,6}$/
=> nil
Upvotes: 0