Difference between validates_presence_of and validates_length_of

Today I had a pretty frustrating moment. I made some new changes in the morning, which included the addition of a new column in the database. This field wasn't required, but I needed to limit the amount of characters a user could enter in that string. So I did the proper thing and set this in my model:

validateslengthof :locations, :maximum => 200

I did a quick test, and the validations worked great. So I promptly committed the code to our repository. A few minutes later, our Continuous Integration system sent me a nasty E-Mail: I broke the build.

I frantically searched the errors in the test, and it seemed that the tests were expecting that field I just added to have something. I was stumped, thinking that unless you specify validatespresenceof, set a range of characters in the validateslengthof or perhaps some regular expression validations in the model, that would be the only time a model would require the field to be there. I hadn't done any of these.

Frustrated, I added a simple string to the fixtures and the test code for this field, and the tests passed. Not content in just making something work, I needed to know what was up. So I started digging around, and found something that now seems obvious, but I totally ignored before.

Whenever you submit a form for a model in Rails to insert a new record in an ActiveRecord model, all the fields you have set in the view are passed in the POST request. However, if you didn't enter anything in a field, the parameters for that field would simply be sent blank. In this case, validateslengthof doesn't bitch about the missing field, because it's there. As long as the number of characters - in this case, zero - isn't more than what I specified in the model, it's all good. However, the tests were failing because since I hadn't specified that new field in the fixtures, the parameters were sending that field as nil, which caused the previously mentioned validation to scream out.

So just as a quick review:

validates_length_of - Verifies if the field is within the amount of characters specified in the validation code. If no minimum is set, it won't mind blank fields, but it will mind nil fields.

validates_presence_of - Verifies if the field is nil or blank.

Like I said, it's obvious now, but not so much when I was getting alerts that the build failed for some silly reason.