This project is archived and is in readonly mode.
nested_attributes: validates_uniqueness_of fails
-
mo
hmm.. this only happens with "@product.categorizations.build" in the products_controller.
I noticed something else. If I create/edit a product, choose a category and, lets say, type in an invalid product title, i get an "missing product_id" error for the chosen category.
All these bugs were not in 2.3-RC1.. that's really annoying. :/
-
Eloy Duran
- Assigned user set to Eloy Duran
- State changed from new to open
Could you please try to distill a failing test for the exact problem you are having? That would be greatly appreciated.
Thanks
-
Eloy Duran
Any news on this?
-
Eloy Duran
- State changed from open to incomplete
-
Ed Lebert
This is really a problem with a core rails philosophy. It assumes that, no matter what, if "valid?" returns true, then it will save successfully. That is a false presumption.
I think rails needs to completely rethink validation and incorporate database constraint detection. And it should go on the assumption that it might return true for "valid?", but not for "save". This is obviously beyond the scope of this ticket, but this is a pretty big problem.
-
bterkuile
I have the same problems. Shortly said: validations are not taken into account when accept_nested_attributes_for is used. I will give my problem, since I use a dirty trick on the column. I think it is not the cause, but good to add anyway: My 'short' situation:
class Employee < ActiveRecord::Base
require 'digest/sha1' attr_protected :id, :salt attr_accessor :password, :password_confirmationbelongs_to :address accepts_nested_attributes_for :address # Always have an address as employee alias :old_address :address def address
{mkd-extraction-e5528c92a92dba8e9a7c761cf9e2a0a4}end
def validate_on_create
{mkd-extraction-97fed57be83556b54a4f5d7e75b7a4a0}end ... end
When a hash containing :address_attributes => {.....} is given to Employee.new, and no password or password_confirmation, it will save => true. Without the
:address_attri butesthe validations work. -
Andrew France
- Tag changed from 2.3.x to nested attributes, 2.3.x, accepts_nested_attributes_for, validates_uniqueness_of
No one seems to have said this explicitly but I believe the problem is simply that validates_uniqueness_of cannot work with nested attributes because the validation only checks against saved records. I am currently handling this problem by doing an in-memory uniqueness check during the validation phase on the parent object.
-
Eloy Duran
@Andrew Thanks for your comment. I'm still thinking about if and how we could fix this as simple as possible, but it might also be handy for people if you could document your workaround in either the NestedAttributes or validates_uniqueness_of docs.
Care to write such a doc patch and do you think it's a valid approach?
-
Andrew France
Hi Eloy, I think my workaround is a bit of a kludge:
class Author has_many :books # Could easily be made a validation-style class method of course validate :validate_unique_books def validate_unique_books validate_uniqueness_of_in_memory( books, [:title, :isbn], 'Duplicate book.') end end module ActiveRecord class Base # Validate that the the objects in +collection+ are unique # when compared against all their non-blank +attrs+. If not # add +message+ to the base errors. def validate_uniqueness_of_in_memory(collection, attrs, message) hashes = collection.inject({}) do |hash, record| key = attrs.map {|a| record.send(a).to_s }.join if key.blank? || record.marked_for_destruction? key = record.object_id end hash[key] = record unless hash[key] hash end if collection.length > hashes.length self.errors.add_to_base(message) end end end endIf this is useful to people I'd be happy to tidy it up and document it somewhere, not really worth making a plugin out of it, I just put it in my initializers. It moves the validation responsibility to the parent object, which is probably bad too, but I don't think there's any way for a new instance to find out about its other unsaved instances.
Best of luck finding an elegant solution though, its got me stumped!
-
Andrew France
OMG Lighthouse is so shit, sorry about the mess.
-
Pratik
I've fixed the formatting there.
-
Eloy Duran
- State changed from incomplete to invalid
Going to close this ticket now. Though, if people keep running into this, I'd love to see Andrew's solution integrated in ActiveRecord.
-
Hervé Tatche
Same problem on rails (2.3.2), validates_uniqueness_of is bypassed.
-
Tamer Salama
Yes! People are still running into problem. Why would the status be "invalid" if a validation is not working as it is supposed to be?
-
Eloy Duran
Why would the status be "invalid" if a validation is not working as it is supposed to be?
How about reading the comments? (that's rhetorical btw.)
It works as it currently should:
“the problem is simply that validates_uniqueness_of cannot work with nested attributes because the validation only checks against saved records”
If you have a good solution/patch to your own problem, please share it with us. But your message as is, doesn't add much, sorry.
-
Piotr Mąsior
I run into similar BUT not SAME problem. Fully explained here: http://railsforum.com/viewtopic.php?id=38343 , I attached there quick fix, but I think it is not elegant. Basing on Eloy summary I assume that is not already any "built in" solution, to use validates_uniqueness_of at model which is used like "dictionary" in context of accepts_nested_attributes_for? I think that filter could somehow discover from what context is it fired up and then check given data against DB and decide is @new_record or not.
-
Roel van der Hoorn
Ran into exactly the same problem. Had a uniqueness constraint on a date of a ProductRate, scoped for a Product, but it wasn't validated. Andrew's patch works like a charm.
