Brian
2007-Mar-18 22:13 UTC
has_one prematurely nullifies existing association when assigned an invalid object
Like a number of other Rails newbies, I''m seeing some unexpected behavior with the has_one relationship. I attempted to search for a solution or explanation here and on Rails Trac, but came up short. I''m using Rails 1.2.2. Here are some simplified models: class Order < ActiveRecord::Base has_one :invoice validates_associated :invoice end class Invoice < ActiveRecord::Base belongs_to :order validates_presence_of :description end The following works as expected (with output edited for brevity):>> order = Order.create=> #<Order:0x3506fb0 ... @attributes={"id"=>1}>>> invoice = Invoice.create(:description => "Foo")=> #<Invoice:0x34f24e8 ... @attributes={"order_id"=>nil, "id"=>1, "description"=>"Foo"}>>> order.invoice = invoice=> #<Invoice:0x34f24e8 ... @attributes={"order_id"=>1, "id"=>1, "description"=>"Foo"}>>> Order.find(1).invoice=> #<Invoice:0x34e7688 @attributes={"order_id"=>"1", "id"=>"1", "description"=>"Foo"}> However, when I assign an invalid Invoice to the has_one association, the valid association is nullified in the database:>> order.invoice = Invoice.new=> #<Invoice:0x34e5810 ... @errors={"description"=>["can''t be blank"]} ... >>> Order.find(1).invoice=> nil This behavior is surprising. Here''s another example (starting by reassigning the valid Invoice)>> order.invoice = invoice >> order.build_invoice=> #<Invoice:0x34bbd08 @new_record=true, @attributes={"order_id"=>1, "description"=>nil}>>> Order.find(1).invoice=> nil I realize that understanding how and when things are saved can be confusing, especially with the has_one relationship. I''m also aware of several ways to work around this, either by adding special code to Order, or just assigning to the belongs_to association instead. But can someone explain why ActiveRecord seems to be nullifying a valid association before the new association is validated or saved? Thanks, Brian --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Brian Rutledge
2007-Mar-19 19:38 UTC
Re: has_one prematurely nullifies existing association when assigned an invalid object
Anyone? Watching the development log show that ActiveRecord is setting the order_id to null when the assignment is made. On Mar 18, 6:13 pm, "Brian" <bhrutle...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Like a number of other Rails newbies, I''m seeing some unexpected > behavior with the has_one relationship. I attempted to search for a > solution or explanation here and on Rails Trac, but came up short. > I''m using Rails 1.2.2. Here are some simplified models: > > class Order < ActiveRecord::Base > has_one :invoice > validates_associated :invoice > end > > class Invoice < ActiveRecord::Base > belongs_to :order > validates_presence_of :description > end > > The following works as expected (with output edited for brevity): > > >> order = Order.create > > => #<Order:0x3506fb0 ... @attributes={"id"=>1}>>> invoice = Invoice.create(:description => "Foo") > > => #<Invoice:0x34f24e8 ... @attributes={"order_id"=>nil, "id"=>1, > "description"=>"Foo"}>>> order.invoice = invoice > > => #<Invoice:0x34f24e8 ... @attributes={"order_id"=>1, "id"=>1, > "description"=>"Foo"}>>> Order.find(1).invoice > > => #<Invoice:0x34e7688 @attributes={"order_id"=>"1", "id"=>"1", > "description"=>"Foo"}> > > However, when I assign an invalid Invoice to the has_one association, > the valid association is nullified in the database: > > >> order.invoice = Invoice.new > > => #<Invoice:0x34e5810 ... @errors={"description"=>["can''t be > blank"]} ... >>> Order.find(1).invoice > > => nil > > This behavior is surprising. Here''s another example (starting by > reassigning the valid Invoice) > > >> order.invoice = invoice > >> order.build_invoice > > => #<Invoice:0x34bbd08 @new_record=true, @attributes={"order_id"=>1, > "description"=>nil}>>> Order.find(1).invoice > > => nil > > I realize that understanding how and when things are saved can be > confusing, especially with the has_one relationship. I''m also aware > of several ways to work around this, either by adding special code to > Order, or just assigning to the belongs_to association instead. But > can someone explain why ActiveRecord seems to be nullifying a valid > association before the new association is validated or saved? > > Thanks, > Brian--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Jonathan Viney
2007-Mar-19 21:13 UTC
Re: has_one prematurely nullifies existing association when assigned an invalid object
Save the invoice after associating it with the order. -Jonathan. On 3/20/07, Brian Rutledge <bhrutledge-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > > Anyone? Watching the development log show that ActiveRecord is > setting the order_id to null when the assignment is made. > > On Mar 18, 6:13 pm, "Brian" <bhrutle...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > Like a number of other Rails newbies, I''m seeing some unexpected > > behavior with the has_one relationship. I attempted to search for a > > solution or explanation here and on Rails Trac, but came up short. > > I''m using Rails 1.2.2. Here are some simplified models: > > > > class Order < ActiveRecord::Base > > has_one :invoice > > validates_associated :invoice > > end > > > > class Invoice < ActiveRecord::Base > > belongs_to :order > > validates_presence_of :description > > end > > > > The following works as expected (with output edited for brevity): > > > > >> order = Order.create > > > > => #<Order:0x3506fb0 ... @attributes={"id"=>1}>>> invoice > Invoice.create(:description => "Foo") > > > > => #<Invoice:0x34f24e8 ... @attributes={"order_id"=>nil, "id"=>1, > > "description"=>"Foo"}>>> order.invoice = invoice > > > > => #<Invoice:0x34f24e8 ... @attributes={"order_id"=>1, "id"=>1, > > "description"=>"Foo"}>>> Order.find(1).invoice > > > > => #<Invoice:0x34e7688 @attributes={"order_id"=>"1", "id"=>"1", > > "description"=>"Foo"}> > > > > However, when I assign an invalid Invoice to the has_one association, > > the valid association is nullified in the database: > > > > >> order.invoice = Invoice.new > > > > => #<Invoice:0x34e5810 ... @errors={"description"=>["can''t be > > blank"]} ... >>> Order.find(1).invoice > > > > => nil > > > > This behavior is surprising. Here''s another example (starting by > > reassigning the valid Invoice) > > > > >> order.invoice = invoice > > >> order.build_invoice > > > > => #<Invoice:0x34bbd08 @new_record=true, @attributes={"order_id"=>1, > > "description"=>nil}>>> Order.find(1).invoice > > > > => nil > > > > I realize that understanding how and when things are saved can be > > confusing, especially with the has_one relationship. I''m also aware > > of several ways to work around this, either by adding special code to > > Order, or just assigning to the belongs_to association instead. But > > can someone explain why ActiveRecord seems to be nullifying a valid > > association before the new association is validated or saved? > > > > Thanks, > > Brian > > > > >--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Brian Rutledge
2007-Mar-20 19:33 UTC
Re: has_one prematurely nullifies existing association when assigned an invalid object
I''m not sure what you''re trying to say...yes, if I just assigned the the order to the invoice, then saved the invoice, that would workaround this issue. But that doesn''t answer my question. While playing around with this, it also looks like AR is nullifying the association in the Invoice object, as well. So, for example:>> order = Order.create=> #<Order:0x3506fb0 ... @attributes={"id"=>1}>>> invoice = invoice.create(:description => "Foo")=> #<Invoice:0x34f24e8 ... @attributes={"order_id"=>nil, "id"=>1, "description"=>"Foo"}>>> order.invoice = invoice=> #<Invoice:0x34f24e8 ... @attributes={"order_id"=>1, "id"=>1, "description"=>"Foo"}>>> Order.find_first.invoice=> #<Invoice:0x34e79f8 @attributes={"order_id"=>"1", "id"=>"1", "description"=>"Foo"}>>> Invoice.find_first.order=> #<Order:0x34e2cc8 @attributes={"id"=>"1"}>>> order.build_invoice=> #<Invoice:0x34e1a58 @new_record=true, @attributes={"order_id"=>1, "description"=>nil}>>> invoice.order=> nil>> Invoice.find_first.order=> nil Why is the Invoice with id = 1 no longer referencing order with id 1? All I''ve done is build a new invoice...I haven''t tried to save it, and it''s not even valid. And I can''t just re-save the original Invoice object, because it also no longer references the order. This seems like a bad side-effect to me. As I''ve said, I''m a Rails newbie, and it seems like the general wisdom is to assign to the belongs_to side of an association, instead of the has_one side. But it would be nice if the has_one side didn''t have surprising side-effects. Is this a well-known bug that I just didn''t search for long enough before I posted to this group? Brian On Mar 19, 5:13 pm, "Jonathan Viney" <jonathan.vi...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Save the invoice after associating it with the order. > > -Jonathan. > > On 3/20/07, Brian Rutledge <bhrutle...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > Anyone? Watching the development log show that ActiveRecord is > > setting the order_id to null when the assignment is made. > > > On Mar 18, 6:13 pm, "Brian" <bhrutle...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Like a number of other Rails newbies, I''m seeing some unexpected > > > behavior with the has_one relationship. I attempted to search for a > > > solution or explanation here and on Rails Trac, but came up short. > > > I''m using Rails 1.2.2. Here are some simplified models: > > > > class Order < ActiveRecord::Base > > > has_one :invoice > > > validates_associated :invoice > > > end > > > > class Invoice < ActiveRecord::Base > > > belongs_to :order > > > validates_presence_of :description > > > end > > > > The following works as expected (with output edited for brevity): > > > > >> order = Order.create > > > > => #<Order:0x3506fb0 ... @attributes={"id"=>1}>>> invoice > > Invoice.create(:description => "Foo") > > > > => #<Invoice:0x34f24e8 ... @attributes={"order_id"=>nil, "id"=>1, > > > "description"=>"Foo"}>>> order.invoice = invoice > > > > => #<Invoice:0x34f24e8 ... @attributes={"order_id"=>1, "id"=>1, > > > "description"=>"Foo"}>>> Order.find(1).invoice > > > > => #<Invoice:0x34e7688 @attributes={"order_id"=>"1", "id"=>"1", > > > "description"=>"Foo"}> > > > > However, when I assign an invalid Invoice to the has_one association, > > > the valid association is nullified in the database: > > > > >> order.invoice = Invoice.new > > > > => #<Invoice:0x34e5810 ... @errors={"description"=>["can''t be > > > blank"]} ... >>> Order.find(1).invoice > > > > => nil > > > > This behavior is surprising. Here''s another example (starting by > > > reassigning the valid Invoice) > > > > >> order.invoice = invoice > > > >> order.build_invoice > > > > => #<Invoice:0x34bbd08 @new_record=true, @attributes={"order_id"=>1, > > > "description"=>nil}>>> Order.find(1).invoice > > > > => nil > > > > I realize that understanding how and when things are saved can be > > > confusing, especially with the has_one relationship. I''m also aware > > > of several ways to work around this, either by adding special code to > > > Order, or just assigning to the belongs_to association instead. But > > > can someone explain why ActiveRecord seems to be nullifying a valid > > > association before the new association is validated or saved? > > > > Thanks, > > > Brian--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Conrad Taylor
2007-Mar-20 20:05 UTC
Re: has_one prematurely nullifies existing association when assigned an invalid object
Hi, if the invoice is invalid, it isn''t saved to the database. Therefore, you''re overwriting the previous value of the invoice associated to the order. Thus, invoking find returns nil. Well, I wish that this helps. Good luck, -Conrad On 3/18/07, Brian <bhrutledge-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Like a number of other Rails newbies, I''m seeing some unexpected > behavior with the has_one relationship. I attempted to search for a > solution or explanation here and on Rails Trac, but came up short. > I''m using Rails 1.2.2. Here are some simplified models: > > class Order < ActiveRecord::Base > has_one :invoice > validates_associated :invoice > end > > class Invoice < ActiveRecord::Base > belongs_to :order > validates_presence_of :description > end > > The following works as expected (with output edited for brevity): > > >> order = Order.create > => #<Order:0x3506fb0 ... @attributes={"id"=>1}> > >> invoice = Invoice.create(:description => "Foo") > => #<Invoice:0x34f24e8 ... @attributes={"order_id"=>nil, "id"=>1, > "description"=>"Foo"}> > >> order.invoice = invoice > => #<Invoice:0x34f24e8 ... @attributes={"order_id"=>1, "id"=>1, > "description"=>"Foo"}> > >> Order.find(1).invoice > => #<Invoice:0x34e7688 @attributes={"order_id"=>"1", "id"=>"1", > "description"=>"Foo"}> > > However, when I assign an invalid Invoice to the has_one association, > the valid association is nullified in the database: > > >> order.invoice = Invoice.new > => #<Invoice:0x34e5810 ... @errors={"description"=>["can''t be > blank"]} ... > > >> Order.find(1).invoice > => nil > > This behavior is surprising. Here''s another example (starting by > reassigning the valid Invoice) > > >> order.invoice = invoice > >> order.build_invoice > => #<Invoice:0x34bbd08 @new_record=true, @attributes={"order_id"=>1, > "description"=>nil}> > >> Order.find(1).invoice > => nil > > I realize that understanding how and when things are saved can be > confusing, especially with the has_one relationship. I''m also aware > of several ways to work around this, either by adding special code to > Order, or just assigning to the belongs_to association instead. But > can someone explain why ActiveRecord seems to be nullifying a valid > association before the new association is validated or saved? > > Thanks, > Brian > > > > >--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Conrad Taylor
2007-Mar-21 06:01 UTC
Re: has_one prematurely nullifies existing association when assigned an invalid object
Hi, here''s a better explaination with the relevant code that you have posted: 1) >> order.invoice = Invoice.new => #<Invoice:0x34e5810 ... @errors={"description"=>["can''t be blank"]} ... > 2) >> Order.find(1).invoice => nil Line 1 => We''re assigning the result or ''Invoice.new'' where all field are initialized to their respective default values. Also, the validations are not invoked until you attempt to invoke save or save! methods. Thus, you''re assigning an invalid invoice instance to the order.invoice Line 2 => Now, we''re trying to find an invoice instance that results in nil being returned because the invoice instance in (1) was never saved the database. Finally, I would recommend taking a look at the relevant chapters in AWDwRv2 for additional information. Good luck, -Conrad On 3/20/07, Conrad Taylor <conradwt-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Hi, if the invoice is invalid, it isn''t saved to the database. > Therefore, you''re overwriting the previous value of the invoice > associated to the order. Thus, invoking find returns nil. Well, I > wish that this helps. > > Good luck, > > -Conrad > > > On 3/18/07, Brian <bhrutledge-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > Like a number of other Rails newbies, I''m seeing some unexpected > > behavior with the has_one relationship. I attempted to search for a > > solution or explanation here and on Rails Trac, but came up short. > > I''m using Rails 1.2.2. Here are some simplified models: > > > > class Order < ActiveRecord::Base > > has_one :invoice > > validates_associated :invoice > > end > > > > class Invoice < ActiveRecord::Base > > belongs_to :order > > validates_presence_of :description > > end > > > > The following works as expected (with output edited for brevity): > > > > >> order = Order.create > > => #<Order:0x3506fb0 ... @attributes={"id"=>1}> > > >> invoice = Invoice.create(:description => "Foo") > > => #<Invoice:0x34f24e8 ... @attributes={"order_id"=>nil, "id"=>1, > > "description"=>"Foo"}> > > >> order.invoice = invoice > > => #<Invoice:0x34f24e8 ... @attributes={"order_id"=>1, "id"=>1, > > "description"=>"Foo"}> > > >> Order.find(1).invoice > > => #<Invoice:0x34e7688 @attributes={"order_id"=>"1", "id"=>"1", > > "description"=>"Foo"}> > > > > However, when I assign an invalid Invoice to the has_one association, > > the valid association is nullified in the database: > > > > >> order.invoice = Invoice.new > > => #<Invoice:0x34e5810 ... @errors={"description"=>["can''t be > > blank"]} ... > > > >> Order.find(1).invoice > > => nil > > > > This behavior is surprising. Here''s another example (starting by > > reassigning the valid Invoice) > > > > >> order.invoice = invoice > > >> order.build_invoice > > => #<Invoice:0x34bbd08 @new_record=true, @attributes={"order_id"=>1, > > "description"=>nil}> > > >> Order.find(1).invoice > > => nil > > > > I realize that understanding how and when things are saved can be > > confusing, especially with the has_one relationship. I''m also aware > > of several ways to work around this, either by adding special code to > > Order, or just assigning to the belongs_to association instead. But > > can someone explain why ActiveRecord seems to be nullifying a valid > > association before the new association is validated or saved? > > > > Thanks, > > Brian > > > > > > > > > > >--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---