Rails validates_length_of and Fixnum

Unless I'm missing something, ActiveRecord's validates_length_of doesn't really work as expected with numeric attributes. For example:

validates_length_of  :zipcode,
                     :is => 5,
                     :message => "should be 5 digits"

                    
In my experiments, this always raises an error. By glancing at the source, I think this is because the validation routine is using value.size, which apparently returns the storage size in bytes. My solution was to not use the validates_length_of method and use this instead:

def validate
  unless self.zipcode.to_s.size == 5
    errors.add("zipcode", "should be 5 digits")
  end
end


I didn't find any discussion about this by Googling, which makes me wonder if I haven't seen a relevant part of the api.
Design Element
Rails validates_length_of and Fixnum
Posted Nov 1, 2005 — 13 comments below




 

Lee N — Nov 01, 05 493

The validates_* rules are applied to the models, not the controllers, so they deal with the model types of the data, not with the input text.

Also, it's pretty traditional to make a telephone or zip a string anyway, since you're not likely to be doing numeric calculations on it, but are likely to reformat it. Do you have a reason for going numeric here?

noell — Nov 01, 05 494

For string zipcodes you can also use a regexp to validate:

unless zipcode =~ /^([^\d]*?\d){5}$/
puts "No"
else
puts "Yes"
end

Btw, you also can use a construct like /^(regexp1|regexp2)$/ to match two different numbers.

ben — Nov 01, 05 496

The zipcode regexp should have a second [^\d]*? after \d to match zipcode strings that end with a space or any other non-digit!

Scott Stevenson — Nov 01, 05 497 Scotty the Leopard

Wouldn't using a regex to validate be unnecessary as Rail provides me with a fixnum as an input value anyway?

Scott Stevenson — Nov 01, 05 498 Scotty the Leopard

Lee N says: The validates_* rules are applied to the models, not the controllers, so they deal with the model types of the data, not with the input text.

I'm not really sure what you mean by this. The validates_* are not limited to type checking. For example, look at validates_format_of. How could data objects get values if they don't interact with (and therefore, validate) user input?

Also, it's pretty traditional to make a telephone or zip a string anyway

Hmmm... well it's possible, but I'm not sure I'd say it's traditional. Unless you mean traditional for Rails?

since you're not likely to be doing numeric calculations on it, but are likely to reformat it.

I don't think I'd be doing reformatting at the controller or model level. The source data should be just a number and the view can massage it as necessary.

Do you have a reason for going numeric here?

Easier formatting, for one. It's guaranteed to be a number by the time it gets to the db.

ben — Nov 02, 05 501

To validate a fixnum zipcode you may use case:

zipcode = 12345

case zipcode
when 10000..99999 then puts "Ok!"
else puts "No five digits!"
end

phil — Nov 07, 05 515

Quite a nifty example of how to code Easy ActiveRecord Scripts can be found (as a recent Ruby post) at jamis.jamisbuck.org. And an ActiveRecord cheatsheet can be downloaded from www.slash7.com (a good Rails intro site anyway).

phil — Nov 12, 05 538

Another interesting resource for RoR & ActiveRecord scripts is www.bigbold.com/snippets/. Go and check out if you like!

Delayed Green — Apr 17, 06 1107

You realize, of course, that many ZIP codes start with a zero? Using a numeric field here is not a good idea.

Scott Stevenson — Apr 17, 06 1108 Scotty the Leopard

You realize, of course, that many ZIP codes start with a zero?

Nope, sure didn't. Even in the US?

izzad — Jun 20, 06 1377

scott,
i had the same problem with
validates_length on numbers... but when i work it out your way it work!!

Any ideas why?

John Sturgeon — Oct 09, 07 4724

I know it's an old thread, but zips can be validating using the following:
validates_format_of :zipcode, :with=>/\A[0-9]{5}\Z/, :if=>:zipcode?

Jers — Aug 03, 08 6225

Yes, many zipcodes do start with 0 - in Connecticut for example.




 

Comments Temporarily Disabled

I had to temporarily disable comments due to spam. I'll re-enable them soon.





Copyright © Scott Stevenson 2004-2015