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.