user1570144
user1570144

Reputation: 479

Ruby Regex to validate format xxx-####

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

Answers (4)

nowk
nowk

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

mu is too short
mu is too short

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

Kenny Grant
Kenny Grant

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

Dave Newton
Dave Newton

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

Related Questions