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}>
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?
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.
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.
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}>
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
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.