How to validate presence of associated?

On Rails 2.1.1, I have this simple case:

class Post < ActiveRecord::Base   has_many :comments end

class Comment < ActiveRecord::Base   belongs_to :post   validates_presence_of :post_id end

Now, when building associated comments to an unsaved post, the validation fails:

p = Post.new => #<Post id: nil, name: nil, created_at: nil, updated_at: nil>

c = p.comments.build => #<Comment id: nil, text: nil, comment_id: nil, created_at: nil, updated_at: nil>

c.valid? => false

c.errors => #<ActiveRecord::Errors:0x23f8d18 @base=#<Comment id: nil, text: nil, comment_id: nil, created_at: nil, updated_at: nil>, @errors={"post_id"=>["can't be blank"]}>

According to http://dev.rubyonrails.org/ticket/4147, validates_presence_of the foreign key is the proper way to validate the presence associated objects. However, the documentation warning regarding this was later removed.

So, question is: How do I validate the presence of associated objects, while still allowing the building of associated objects to an unsaved model?

Regards,

Christian

Christian Rishøj wrote:

On Rails 2.1.1, I have this simple case:

class Post < ActiveRecord::Base   has_many :comments end

class Comment < ActiveRecord::Base   belongs_to :post   validates_presence_of :post_id end

Now, when building associated comments to an unsaved post, the validation fails:

p = Post.new => #<Post id: nil, name: nil, created_at: nil, updated_at: nil>

c = p.comments.build => #<Comment id: nil, text: nil, comment_id: nil, created_at: nil, updated_at: nil>

c.valid? => false

c.errors => #<ActiveRecord::Errors:0x23f8d18 @base=#<Comment id: nil, text: nil, comment_id: nil, created_at: nil, updated_at: nil>, @errors={"post_id"=>["can't be blank"]}>

According to http://dev.rubyonrails.org/ticket/4147, validates_presence_of the foreign key is the proper way to validate the presence associated objects. However, the documentation warning regarding this was later removed.

So, question is: How do I validate the presence of associated objects, while still allowing the building of associated objects to an unsaved model?

Christian, this comes up quite often. I'm glad the incorrect warning has been removed from the API, but I would dispute the validity of that old ticket [the blog post explaining the ticket-creator's reasoning is no longer available].

Here's my most recent post on this topic: http://groups.google.com/group/rubyonrails-talk/msg/3c01e9b320604dc8

Thank you for this, Mark.

I was able to make the association proxy set the target object on unsaved associations with the following monkey patch:

module ActiveRecord   module Associations     class AssociationProxy       protected

Seems I'm not the first to get this idea: http://www.nabble.com/-set_belongs_to_association_for-doesn’t---td11423337.html

Problem is that setting the (unsaved) owner object on an associated object causes a lot of tests to break. Namely, validations go into a recursion of e.g. validate_associated_records_for_developer and validate_associated_records_for_audit_logs back and forth ad infinitum.

This could really be working a lot better.

Any clues on how to deal with this?

Christian

Christian Rishøj wrote:

Problem is that setting the (unsaved) owner object on an associated object causes a lot of tests to break. Namely, validations go into a recursion of e.g. validate_associated_records_for_developer and validate_associated_records_for_audit_logs back and forth ad infinitum.

I guess it's the tests that require fixing. And AR should be detecting loopy validations and raising an error.