At my wits end ! Controlling passed in negative values from a form


I am trying to validate a numeric value passed in from a form, which is saved in a MySQL db as decimal(9,2)

Now problem is I need to ensure people don't enter a form value like -. 003. In my validations, I have a validates_numericality_of check being done. Furthermore, in validate method, I have a check using an if statement such as :

((an_object[n].nil? or an_object[n] < 0) and !an_object[n].blank?)

While testing, Rails validation can catch -0.003. However, it just does not catch -.003 (without leading zero). In fact, in case of -. 003, the value gets saved as 0; if form value is -.008 let's say, it gets saved as .01 in db (gets rounded off). Anything like -1.23 works ok - meaning it is trapped as error.

I have a before_validation method which assigns 0 to undefined values like so: = 0 unless (where xxx is name of attribute)

I have tried checking for a minus sign in before_validation & validate method using xxx.to_s.include?("-"). I have also tried using :greater_than and :minimum options in the validates_numericality_of call. I also tried validates_inclusion_of, giving a range from 0..9999999.99.

Nothing seems to work.

Would appreciate any insight into this ! ? What am I missing ??

Thank you

I am guessing a bit here but I assume what is happening here is that the -.003 is being rounded to 0 because you have specified decimal 9,2. Then the validation is run, but as the value is now zero, which is not negative, then the validation passes. Using before_validation does not help as this is probably after the rounding. I have little doubt that there is a better way but it you could do this check in the controller before it is rounded.


Dear Colin

Thank you for your insight... indeed you are right the conversion is happening before the validation - hence I thought before_validation would catch it.

Anyways, I did move the checking to the controller and found something interesting.

In the controller, the rounding takes place at the time of the model's create call e.g. @person =[:person]) or when saving. This I found by looking at the screen log and noting the attribute value in the params hash vs the db table's insert call on the model. Hence one needs to check this at earlier stage in the controller when the raw params values come in via the post request.

Furthermore, at this stage, prior to @person = definition, one has to be sure one has checked params is not nil, which is the simple if statement like:

if and params[:person]

So, yes it worked finally - thank you indeed so much for your insight ! :slight_smile:

I am certain there has to be a better way to do this no ... since it opens up an entire bunch of 'check validation' fears for me in the controller at the params level.

Thanks Colin and best regards