validates_numericality_of will accept anything which is non-nil and
which can convert to a float and not return an error. It does it by
converting the value to a string and sending it to Kernel.Float. So
whatever Ruby's Kernel.Float can handle will pass validation.
Kernel.Float("123.45")
=> 123.45 # success
Kernel.Float("1,234.56")
=> ArgumentError # failure
Kernel.Float("123,45")
=> ArgumentError # failure
Kernel.Float("1.234,56")
=> ArgumentError # failure
So if you want to use validates_numericality_of you'll have to remove
the commas and/or replace them with periods. The best place to do that
is probably the before_validation callback. Off the top of my head,
maybe something like:
def before_validation
# remove any commas or periods that preceed 3 digits
self.some_value.gsub!(/[\.\,](\d{3})/, '\1')
# replace any comma that preceeds the final 2 digits with a period
self.some_value.gsub!(/\,(\d{2})$/, '.\1')
end
As others suggested, your other choice is to go with
validates_format_of or to write your own custom validation. Keep in
mind that this depends on what your database will accept too. If your
database won't accept the "foreign-format" then you'd be better off
converting it before you validate.
One possible regular expression might be:
(^\d{1,3}(\,\d{3})*(\.\d{2})?$|^\d{1,3}(\.\d{3})*(\,\d{2})?$|^\d+([\.
\,]\d{2})?$|^[\.\,]\d{2}$)
It allows for:
- comma-separated digits optionally ending in a period and 2 digits
(1,234,567.89)
- period-separated digits optionally ending in a comma and 2 digits
(1.234.567,89)
- non-separated digits optionally ending in a period or comma and 2
digits (1234567.89 or 1234567,89)
- a comma or period followed by 2 digits (.75 or ,75)
Writing good regular expressions is tricky, so test them extensively
before relying on them.
HTH,
Kevin Skoglund