This project is archived and is in readonly mode.
nested models: build should directly assign the parent
Reported by sarah (at ultrasaurus) | June 18th, 2009 @ 09:55 PM | in 2.3.6
As noted in https://rails.lighthouseapp.com/projects/8994/tickets/1943 sometimes you want to validate the presence of the parent from the child (to handle the case where the child could be independently created for an existing parent)
Example:
class Person < ActiveRecord::Base
has_many :children accepts_nested_attributes_for :children end
class Child < ActiveRecord::Base
belongs_to :person
#Validating that a child has a parent validates_presence_of :person # as opposed to person_id, if the person is a new_record? w/o id yet end
p = Person.new(:name => "Smith", :children_attributes =>
[{:name => "John"}] )
p.valid? #=> false (should be true)
p.save #false (should be true)
p.children.first.errors.on(:person_id) #=> "can't be blank"
Comments and changes to this ticket
-
sarah (at ultrasaurus) June 18th, 2009 @ 10:11 PM
We were thinking that the fix could be something like...
in nested_attributes.rb, assign_nested_attributes_for_one_to_one_association (around line 250) and like methods to add the reference to the parent:
assn = send("build_#{association_name}", attributes.except(*UNASSIGNABLE_KEYS)) assn.send("#{parentname}=", self)
not sure how to get the 'parentname' ...
-
Wolfram Arnold June 29th, 2009 @ 10:40 PM
- Tag changed from nested accepts_nested_attributes_for, validates_presence_of to 2.3.4, accepts_nested_attributes_for, inverse_of, validates_presence_of
I've just discovered the object identify work by Murray Steele and the new :inverse_of option for associations.
Using this, the problem described above can be solved, i.e.
class Person < ActiveRecord::Base
has_many :children accepts_nested_attributes_for :children, :inverse_of => :person
end
class Child < ActiveRecord::Base
belongs_to :person, :inverse_of => :children validates_presence_of :person
end
p = Person.new(:name => "Smith", :children_attributes => [{:name => "John"}] ) p.valid? # ==> true
I'm attaching a patch that adds test coverage for these cases; it turns out with the latest edge Rails all the pieces are in place for this to work out of the box. :inverse_of contributes this magic. Many thanks to Murray
-
Wolfram Arnold June 30th, 2009 @ 03:33 AM
For now, the temporary workaround until Rails 2.3.4 is released would be:
@@@ruby p = Person.new(...) p.save(false) # save without validation if p.valid?
#...
else
#...
end
-
Eloy Duran June 30th, 2009 @ 08:19 AM
Very nice Wolfram!
Would you mind moving the last test, which tests nested attributes, to the nested_attributes_test.rb file?
Thanks
-
Wolfram Arnold July 12th, 2009 @ 12:12 PM
Done. Thanks for the suggestion and sorry for the slow turn-around.
-
Eloy Duran July 12th, 2009 @ 12:53 PM
@Wolfram: Unfortunately I'm unable to see your patch atm. It seems there's an issue with LH. If you could try again or maybe add a pastie/gist, I can verify it on the master branch.
@Bodaniel: The problem is that the :inverse_of patch hasn't been applied to the 2-3 branch, and won't be in the near future as I understand. So until then, this will stay an issue. Feel free to ask on the mailing list if the :inverse_of patch can be applied on the 2-3 branch, or why it isn't being applied.
-
Wolfram Arnold July 13th, 2009 @ 06:50 AM
@Eloy: OK, here I'm trying the attachment again, and here is a pastie link: http://pastie.org/543837 Thanks, Wolf
-
Murray Steele July 13th, 2009 @ 09:09 AM
As the author of the :inverse_of patch, I have to say I agree with it not slipping into a 2.3.x release when it didn't make 2.3.0. That said, all is not lost, you could instead use the plugin that I extracted the :inverse_of code from: http://github.com/h-lame/parental_control/.
-
Eloy Duran July 13th, 2009 @ 10:09 AM
- Milestone cleared.
@Wolfram: Thanks, I'll verify it against master.
@Murray: Thanks for chiming in.
-
Wolfram Arnold July 14th, 2009 @ 09:02 AM
@Myrray: Thanks for the pointer to the plugin; that'll solve our problem. I agree with you that given the fundamental nature of the background of :inverse_of with object mapping and identity this is probably not adequate for a dot release.
-
Repository August 8th, 2009 @ 02:01 PM
(from [73f2d37505025a446bb5314a090f412d0fceb8ca]) Add test to verify that the new :inverse_of association option will indeed fix the validation problem for a belongs_to relationship that validates_presence_of the parent, when both the parent and the child are new (in-memory) records. Also check that this works when the parents adds child via nested_attributes_for.
Lastly, add a require 'models/pet' to association_validation_test.rb, so that test can be run independently (was failing due to that missing dependency). [#2815 status:resolved]
Signed-off-by: José Valim jose.valim@gmail.com
http://github.com/rails/rails/commit/73f2d37505025a446bb5314a090f41... -
Ari Epstein August 18th, 2009 @ 08:23 PM
The following workaround has been fine for me:
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
-
Sai Emrys December 16th, 2009 @ 10:02 PM
Bug #3588 is related to this - :autosave => true + accepts_nested_attributes_for = circular validation & blown stack.
-
Eloy Duran December 17th, 2009 @ 02:47 PM
- Milestone set to 2.3.6
Hey all, could you please verify that this 2.3.x branch fixes the problems? http://github.com/Fingertips/rails/tree/2-3-stable
It contains all the :inverse_of patches applied to master, plus a few.
-
Eloy Duran December 28th, 2009 @ 08:52 PM
- State changed from new to resolved
The :inverse_of patches have been pushed to 2-3-stable, closing for now.
-
Trevor Turk August 19th, 2010 @ 08:51 PM
- Importance changed from to
FYI - I added some info about this in docrails. Please feel free to change/remove this new section, but I think having this documented somewhere is a good idea. It took me a couple of hours to sort out what my problem was and how to fix it today ;)
http://github.com/lifo/docrails/commit/99c092d4e875856502946c29a1ae...
-
Evgeniy Dolzhenko August 20th, 2010 @ 09:55 AM
+1 for that being documented. One point though here http://guides.rubyonrails.org/activerecord_validations_callbacks.ht... its said "If you want to be sure that an association is present, you’ll need to test whether the foreign key used to map the association is present, and not the associated object itself." which contradicts your "validates_presence_of :member"
-
Timothy Jones November 12th, 2010 @ 05:15 AM
This bug is not resolved in the 2.x branch (at least as of 2.3.10).
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>
People watching this ticket
Attachments
Referenced by
- 2815 nested models: build should directly assign the parent Lastly, add a require 'models/pet' to association_validat...
- 3588 :autosave => true + accepts_nested_attributes_for = circular validation & blown stack This can also be prevented by turning off inverse (runnin...
- 3533 Backport :inverse_of from 3.0 to 2.3.x I clearly meant #2815.
- 2578 accepts_nested_attributes_for causes stack level too deep Aha: In my situation, the child model wants to validate_p...
- 2578 accepts_nested_attributes_for causes stack level too deep In my case, I'd tried to work around it using a before_va...
- 2578 accepts_nested_attributes_for causes stack level too deep From reading #2815, it sounds like I should be able to in...
- 2578 accepts_nested_attributes_for causes stack level too deep From reading #2815, it sounds like I should be able to in...
- 4269 build through an association does not set the back-reference in Rails 3.0.0 Make sure you're setting :inverse_of option on your assoc...
- 1619 Support for :inverse option in associations The following fix depends on it, and it would be great if...