This project is archived and is in readonly mode.
Nested attributes validations circular dependency
-
Eloy Duran
- Assigned user set to Eloy Duran
-
Eloy Duran
- State changed from new to wontfix
I wonder how we could actually handle this. It would mean you'd have to save the parent before the children in order to be able to validate the children. So simply calling parent.valid? would save it and then run the validations on the children. That all seems very complicated to me.
Also, this should already be tested in the framework and not something the developer should need to worry about. However, if you feel there are tests for scenarios missing let me know.
If you still feel a strong need to validate that after creation the foreign key is set, I would suggest adding an after_save callback which verifies this and if not rolls back the transaction.
-
Stephen Touset
This could be resolved by validates_presence_of :parent, rather than validates_presence_of :parent_id. Unfortunately, Rails doesn't set the parent on building the association. Could that be changed?
Either that, or making validates_associated not be completely useless, and do what is implied by its name.
-
Eloy Duran
This could be resolved by validates_presence_of :parent, rather than validates_presence_of :parent_id. Unfortunately, Rails doesn't set the parent on building the association. Could that be changed?
Hmm, having #build directly assign the parent sounds like a good idea in general. Maybe open a separate ticket for it or ask on the ML if there are any known issues with this?
Either that, or making validates_associated not be completely useless, and do what is implied by its name.
Why is validates_associated completely useless?
-
Michael Kintzer
Is there any update regarding the previous suggestion? (Having #build_child directly assign the parent to satisfy a 'validates_presence_of :parent without the need for the parent to already be saved?)
I looked around on the mailing lists and did not see a ticket on this. It seems like a promising approach, and it would allow for a resolution to this issue.
Based on the blog feedback, it seems more than a handful of people do use validates_presence_of :parent_id in their belongs_to relationship models (I recall it being recommended in Dan Chak's excellent Enterprise Rails book) and it seems a shame to ask them to remove or recode that with an after_save callback just so this new feature can work.
-
Eloy Duran
Is there any update regarding the previous suggestion? (Having #build_child directly assign the parent to satisfy a 'validates_presence_of :parent without the need for the parent to already be saved?) I looked around on the mailing lists and did not see a ticket on this. It seems like a promising approach, and it would allow for a resolution to this issue.
Nope, not that I know of. As I already suggested, open up a new ticket which requests this, or better yet, attach a patch.
Based on the blog feedback, it seems more than a handful of people do use validates_presence_of :parent_id in their belongs_to relationship models (I recall it being recommended in Dan Chak's excellent Enterprise Rails book) and it seems a shame to ask them to remove or recode that with an after_save callback just so this new feature can work.
This has nothing to do with any new feature, it just doesn't work this way.
-
Chris Bartlett
- Tag set to code
There might also be uniqueness conditions that you want to enforce, but these fail as per the discussion above. For example, if you were trying to save a course and enrolments and had a uniqueness condition on enrolments to prevent a student from enrolling in a course more than once:
validates_uniqueness_of :student_id, :scope => :course_idThis validation does not work when creating a new course (say, the user has accidentally added the same student twice on the course form they are submitting). This is an old issue - see: http://dev.rubyonrails.org/ticke...Basically, it means that accepts_nested_attributes_for is not as nice and tidy as one would perhaps expect. Validations need to be handled by the DBMS.
-
Dmitry Polushkin
What to do? Just use DBMS index :unique => true? Or it's possible to write a patch?
-
Evgeniy Dolzhenko
So it's not in any way related to nested attributes, right?
I was bitten by the same problem ( described here http://railsforum.com/viewtopic.php?pid=96990 ), and still don't get how to build, in the terms of the above example, the Person object with Child object in children association in memory, and then save them with one call.
I.e. get the transaction safety and easier error reporting for building complex objects.
-
Melvin Ram
So what is the convention to solving this problem? Is there a workaround for the validates_presence_of :parent?
-
sarah (at ultrasaurus)
Alright, I wrote up a bug on the suggested approach above: https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets...
-
TMaYaD
I think we still need to fix it.
In case of a nested resource with its own form, we might want to validate that the child does indeed belong to a parent even if its form is not nested in the parent.
At the very least we need to be able to provide a way to tell weather we are in the model from a nested form or individual form, so that we can validate accordingly.
the workaround I currently use in my apps is to assign an attribute ':nest' ( = self, ie, the parent )to each child before validation on parent and check for it in child -
TMaYaD
- Tag changed from code to nested attributes, code, nested_attributes_for
-
Sean Corbett
- Assigned user cleared.
- Importance changed from to
I like Ari Epstine's workaround for this on the related ticket: https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets...
class Person < ActiveRecord::Base has_many :children accepts_nested_attributes_for :children before_validation_on_create :initialize_children def initialize_children children.each { |c| c.parent = self } end end class Child < ActiveRecord::Base belongs_to :person end -
TMaYaD
A variant to Ari Epstine's work around is using before_add callback
class Person < ActiveRecord::Base
has_many :children, :before_add => :set_nest accepts_nested_attributes_for :children private
def set_nest(child)child.person ||= selfend end
class Child < ActiveRecord::Base
belongs_to :person#Validating that a child has a parent validates_presence_of :person_id, :unless => Proc.new { |c| c.parent && c.parent.new_record? } end