I have run into a problem with Rails "validates_uniqueness_of". The evidence indicates that this method does not get attribute values set in the model but rather uses raw data passed from the view. I have traced through the process with the debugger but my knowledge of rails internals is too sketchy for me to pinpoint where and how the value initialization is taking place.
The symptom of the difficulty is demonstrated below. Given an input string for @entity.entity_name of "A TEST CLIENT" the model invokes an override on the default accessors to produce a final string of entity.entity_name = "a test client". The validates_uniqueness_of :entity_name for the above situation passes even if "a test client" is already on file but the subsequent SQL INSERT statement generated fails because the value passed is "a test client" and this triggers an SQL exception because of an INDEX UNIQUE constraint on that column.
My questions are these:
Why does the validation_uniqueness_of NOT use the value that is going to be inserted into the database for its check?
Is this a feature or a bug?
Where is this value passed to validate_uniqueness_of if not from the model; from the controller?
Do I have to replicate model code in the controller to achieve the effect desired, a validation check using the values that will be used for insertion?
X-Posted to Ruby-Forum
I found the source of my confusion. I had redefined the getter method for entity_name to provide a titlecase display to the view. It was this value that the validates_uniqueness_of is using, which was different then the value I was providing from the overloaded setter method.
I am still not sure why the validates would use one value from one source for validation and another for the actual update but at least I can now get this to work.
I am not sure If I could understand your problem but The way to validates uniqueness is to try to find the record with the specified value. Do you mean that the value for validation is the value you get by the getter method while insert or did You mean "insert statement" use the raw data instead of the date get by the getter method ?
The problem is one of ignorance on my part. That, and being caught up with solving the problem of forcing the indexed value to a normalized form but wishing to display it in a human friendly fashion.
There is nothing wrong with the way the validator gets its value. It does that via the getter method for the attribute. There is nothing wrong with the way the updated gets the INSERT value, it does that from the setter method of the attribute. My problem was that I had over-written both in the model and the return values of each differed. Essentially the getter was doing attribute.titlecase and the setter was doing attribute.downcase. Naturally enough this did not generate the same string for the validator as for the updater.
Now that I have learned my lesson and reconciled both accessors the validates_uniqueness_on works as advertised. I do not use VUO to enforce DB integrity, I have an INDEX UNIQUE on the attribute for that, but this does provide a neater warning to the user and requires far less code.