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:

end

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


Rails Wheels - Find Plugins, List & Sell Plugins -
http://railswheels.com

On Sep 24, 2:52 pm, Mark J. [email protected] wrote:

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
#
# Allow validates_presence_of :target on belongs_to
associations
# before the target has been saved.
def set_belongs_to_association_for(record)
record[“#{@reflection.options[:as]}type"] =
@owner.class.base_class.name.to_s if @reflection.options[:as]
if @owner.new_record?
set_proxy_target_method = "set
#{@reflection.options[:as] ||
@reflection.primary_key_name.chomp(‘_id’)}_target”
record.send(set_proxy_target_method, @owner)
elsif @reflection.options[:as]
record[“#{@reflection.options[:as]}_id”] = @owner.id
else
record[@reflection.primary_key_name] = @owner.id
end
end
end
end
end

Now I can do:

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

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

c.valid?
=> true

Now I wonder: Why doesn’t ActiveRecord do this by default?

Christian

On Sep 24, 8:22 pm, Christian Rishøj [email protected] wrote:

  protected
      record.send(set_proxy_target_method, @owner)

Now I can do:

Now I wonder: Why doesn’t ActiveRecord do this by default?

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.


Rails Wheels - Find Plugins, List & Sell Plugins -
http://railswheels.com