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 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
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 -- Rails Wheels - Find Plugins, List & Sell Plugins - http://railswheels.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On Sep 24, 2:52 pm, Mark James <m...-bzGI/hKkdgQnC9Muvcwxkw@public.gmane.org> 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/3c01e9b320604dc8Thank 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 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On Sep 24, 8:22 pm, Christian Rishøj <christ...-xVFlH9Wu1uCsTnJN9+BGXg@public.gmane.org> wrote:> On Sep 24, 2:52 pm, Mark James <m...-bzGI/hKkdgQnC9Muvcwxkw@public.gmane.org> 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...-hE1HR0YQ/hukCc1+iwrdw/8+0UxHXcjY@public.gmane.orgs[: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?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 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
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 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---