views:

251

answers:

3

Given three models that are each nested in each other. If I create the top-level object and build_* the other child objects, I can retrieve all child objects through the relationships before and after save() on the original instance. However, if I try to retrieve the 2nd level nested object after find(:id) the original parent it fails. I can retrieve the 1st level nested object, however. This usually happens in a controller, but I'll illustrate it in console output below.

What am I overlooking?

Thanks in advance!
~jpv

>> l = Lead.new :buyer_name => 'Kim Possible', :email => '[email protected]', :phone => '7131231234'
>> l.build_buyer
>> l.buyer.name = 'kim buyer'
>> l.buyer
>> l.buyer.build_contact_detail
>> l.buyer.contact_detail.email = "[email protected]"
>> l.save #returns true
>> l.buyer #THIS WORKS
=> #<Buyer id: 1, name: "kim buyer", lead_id: 1>
>> l.buyer.contact_detail #THIS WORKS
=> #<ContactDetail id: 1, company_id: nil, buyer_id: 1, email: nil, address_line_1: nil, address_line_2: nil, city: nil, state: nil, postal_code: nil>
>> l2 = Lead.find(1)
=> #<Lead id: 1, company_id: nil, buyer_id: nil, public_lead_id: nil, buyer_name: "Kim Possible", company_name: nil, email: "[email protected]", phone: "7131231234">
>> l2.buyer #THIS WORKS AS EXPECTED
=> #<Buyer id: 1, name: "kim buyer", lead_id: 1>
>> l2.buyer.contact_detail #THIS BREAKS
=> nil

All the boilerplate stuff below:

class Lead
  has_one :buyer
  #...
end

class Buyer
  has_one :contact_detail
  belongs_to :lead
  #...
end

class ContactDetail
  belongs_to :buyer
  #...
end

The appropriate foreign keys are in each of the "belongs_to" classes.

class CreateBuyers < ActiveRecord::Migration
  def self.up
    create_table :buyers do |t|
      t.string :name
      t.integer :lead_id
...

class CreateContactDetails < ActiveRecord::Migration
  def self.up
    create_table :contact_details do |t|
      t.integer :buyer_id
A: 

EDIT: NM, had your associations confused.

Ben
I think it works because Buyer `:belongs_to` Lead, so that reference is used instead. (You can see that the Buyer refers to the right Lead.)
John Feminella
A: 

Does this work if you do...

l.buyer.name = 'kim buyer'
l.save
l.buyer.build_contact_detail
...

If so, this could be a rails bug with the ContactDetail object not really knowing who its daddy is at creation time.

Cratchitimo
Yes, it does work for the original object. However, when I instantiate it a 2nd time it loses the relationship. I'm leaning towards rails bug, too.
jpv
A: 

I think you might be getting tripped up because you're expecting the object to eager load nested child objects. In general, you have to explicitly specify it for that to happen in the find. Try adding :include => [:borrower, {:borrower => :contact_detail}] to the options for the find and see if that works.

stan
Thanks! That did the trick. I guess Rails only eager loads the first level of associations.
jpv