viatropos/tower — pull request #160 by edubkendo (2012-06-12 09:15:34+00:00)
Title: Fix length validations

This pull-request brings the length validations in line with how they work in Rails, and how the documentation suggests it should work. Before, it was working as a simple number validation, testing whether a number met a simple boolean test. Used on fields that contained a string simply failed every time.

However, in rails the length validation is primarily used to measure the length of a string, ie. to count against the number of characters used and reject, for instance, a password that is too short, or a text entry that is too long.

To give a short example of how they work now, take the case of a tweet on twitter which can't be longer than 140 characters. So, in your "messages model" you might have:

```coffeescript
class App.Message extends Tower.Model
@field "userId", type: "Integer"
@field "tweet", type: "String"

@validates 'tweet', length: { max: 140 }

@belongsTo "user"

@timestamps()
```

Now, tweets longer than 140 characters will fail. If you logged the user.errors in your controller, you'd see the message:

'tweet must be a maximum of 140'

You could easily show these messages to your user, using the flash, once that is available, although as you can see, the current error messages need a little tweaking.

Instead of simply changing the length validation to expect a string, I gave it a simple test, so that something like:

@validates 'age', length: { min: 21 }

will still work on a number. Also, simply using 'length' by itself does an equals check so that:

@validates 'tweet', length: 140

would expect a tweet of exactly 140 characters long.

The easiest solution I currently see to the clumsiness of the error messages would be to fall back on the fact that max/min and gte/lte are redundant, so we could word the max/min errors with language talking about the number of characters and the gte/lte errors with language talking about numbers. The documentation actually refers to a "numericality" class of validations which would handle all the number stuff, including gte/lte, etc, leaving 'length' to work solely with strings, which is how rails does it. Once that is implemented, they would each have their own default error message and this wouldn't be a problem either.

Also, currently there is no easy way for the developer to alter the error message from the default, though the documentation suggests its as simple as setting:

@validates 'tweet', length: { max: 140, message: '%{count} characters is the maximum allowed' }

I'm not sure if the implementation of this has been attempted and just isn't working properly or not. But, the ability to do this would be another potential solution to the clumsy error messages. For now, though, the length validations will do the correct thing and the error messages, though a bit clumsy, will describe the problem.