Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

floating point precision in ruby on rails model validations

I am trying to validate a dollar amount using a regex: ^[0-9]+\.[0-9]{2}$

This works fine, but whenever a user submits the form and the dollar amount ends in 0(zero), ruby(or rails?) chops the 0 off. So 500.00 turns into 500.0 thus failing the regex validation.

Is there any way to make ruby/rails keep the format entered by the user, regardless of trailing zeros?

like image 386
Chris Allison Avatar asked May 04 '10 16:05

Chris Allison


1 Answers

I presume your dollar amount is of decimal type. So, any value user enters in the field is being cast from string to appropriate type before saving to the database. Validation applies to the values already converted to numeric types, so regex is not really a suitable validation filter in your case.

You have couple of possibilities to solve this, though:

  1. Use validates_numericality_of. That way you leave the conversion completely to Rails, and just check whether the amount is within a given range.
  2. Use validate_each method and code your validation logic yourself (e.g. check whether the value has more than 2 decimal digits).
  3. Validate the attribute before it's been typecasted:

This is especially useful in validation situations where the user might supply a string for an integer field and you want to display the original string back in an error message. Accessing the attribute normally would typecast the string to 0, which isn‘t what you want.

So, in your case, you should be able to use:

validates_format_of :amount_before_type_cast, :with => /^[0-9]+\.[0-9]{2}$/, :message => "must contain dollars and cents, seperated by a period"

Note, however, that users might find it tedious to follow your rigid entry rules (I would really prefer being able to type 500 instead 500.00, for example), and that in some locales period is not a decimal separator (if you ever plan to internationalize your app).

like image 91
Mladen Jablanović Avatar answered Sep 19 '22 00:09

Mladen Jablanović