# Delaying initialization of associations until first access

**URL:** <https://www.ruby-forum.com/t/delaying-initialization-of-associations-until-first-access/53465>\
**Category:** Rails\
**Created:** [February 6, 2006, 9:24pm UTC](https://www.ruby-forum.com/t/delaying-initialization-of-associations-until-first-access/53465 "2006-02-06T21:24:12Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [February 6, 2006, 9:24pm UTC](https://www.ruby-forum.com/t/delaying-initialization-of-associations-until-first-access/53465/1 "2006-02-06T21:24:12Z")

</div>

Guys,

## Say I have the following:

class Person \< ActiveRecord::Base  
has\_one :house  
end

## class House \< ActiveRecord::Base belongs\_to :person attr\_accessor :color end

## Then I have the following code:

## john = Person.new john.house.color = “Blue” john.save

What I would like to have happen, is that on first call to john.house,  
if  
house hadn’t been initialized a House object would be created and  
assigned  
to the house field.

I’ve struggled to get this to work. Some have suggested overriding  
Person#save to make sure a House record was created everytime I created  
a  
Person record, but I really, really don’t want to do this. If I have  
100000 Person objects, and only 20% of them own a house, all those empty  
House records in the database is a lot of waste.

I’ve tried variations on the below code, each of which has failed to  
work.  
It _seemed_ to work, but it doesn’t persist to the database properly:

class Person \< ActiveRecord::Base  
has\_one :house

def house  
if !read\_attribute(:house)  
h = House.new  
h.save  
write\_attribute(:house, h)  
end  
read\_attribute(:house)  
end  
end

Can anyone tell me the proper way to accomplish this behavior?

Thanks!  
John

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [February 6, 2006, 9:33pm UTC](https://www.ruby-forum.com/t/delaying-initialization-of-associations-until-first-access/53465/2 "2006-02-06T21:33:29Z")

</div>

What exactly doesn’t get saved properly? From the looks of it you are  
not setting the house’s person property, which leads me to think that  
the person\_id isn’t getting set in the database? Yes? No?

So, before your h.save call, just add a h.person = self. Or you could  
just create and save all in one step. Your total method would be:  
def house  
return House.create(:person\_id =\> self.id) if !read\_attribute(:house)  
read\_attribute(:house)  
end

Just have the create call, no need to write the attribute or assign it  
anything else, everything should work just fine like that.

I think this will work, but its untested 😉

-Nick

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [February 6, 2006, 10:25pm UTC](https://www.ruby-forum.com/t/delaying-initialization-of-associations-until-first-access/53465/3 "2006-02-06T22:25:52Z")

</div>

Nick S. said:

> So, before your h.save call, just add a h.person = self. Or you could  
> just create and save all in one step. Your total method would be:  
> def house  
> return House.create(:person\_id =\> self.id) if !read\_attribute(:house)  
> read\_attribute(:house)  
> end

Yes, I’ve tried this in two forms:

def house  
if !read\_attribute(:house)  
h = House.new  
h.person = self

# second form tried was

# h.person\_id = self.id

h.save  
write\_attribute(:house, h)  
end  
read\_attribute(:house)  
end

Both “seem” to work, and the House record is created. However, if I then  
do:

someperson.house.color = “Red”  
someperson.save

I look in my logs, and the person record is being updated but the house  
record is not. Then, if I reload the person:

> > someperson = Person.find(1)  
> > someperson.house.color  
> > =\> nil

Examining the logs, it seems that in “if !read\_attribute(:house)”,  
read\_attribute(:house) never tests to true, _even_ if the record already  
exists. This is counter intuitive and bewildering.

Any ideas what I may be doing wrong?

Thanks!

John

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [February 6, 2006, 10:29pm UTC](https://www.ruby-forum.com/t/delaying-initialization-of-associations-until-first-access/53465/4 "2006-02-06T22:29:00Z")

</div>

Nick S. said:

> So, before your h.save call, just add a h.person = self. Or you could  
> just create and save all in one step. Your total method would be:  
> def house  
> return House.create(:person\_id =\> self.id) if !read\_attribute(:house)  
> read\_attribute(:house)  
> end

Yes, I’ve tried this in two forms:

def house  
if !read\_attribute(:house)  
h = House.new  
h.person = self

# second form tried was

# h.person\_id = self.id

h.save  
write\_attribute(:house, h)  
end  
read\_attribute(:house)  
end

Both “seem” to work, and the House record is created. However, if I then  
do:

someperson.house.color = “Red”  
someperson.save

I look in my logs, and the person record is being updated but the house  
record is not. Then, if I reload the person:

> > someperson = Person.find(1)  
> > someperson.house.color  
> > =\> nil

Examining the logs, it seems that in “if !read\_attribute(:house)”,  
read\_attribute(:house) never tests to true, _even_ if the record already  
exists. This is counter intuitive and bewildering.

Any ideas what I may be doing wrong?

Thanks!

John

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [February 7, 2006, 2:47am UTC](https://www.ruby-forum.com/t/delaying-initialization-of-associations-until-first-access/53465/5 "2006-02-07T02:47:10Z")

</div>

On 2/6/06, John W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> def house
> 
> Both “seem” to work, and the House record is created. However, if I then do:
> 
> someperson.house.color = “Red”  
> someperson.save

You are going to need to save your house model seperatly from your  
person model. But! If you always want to do this, through in a  
before\_save filter for the person class that automatically saves the  
house model at the same time. Should be simple enough.

> exists. This is counter intuitive and bewildering.  
> For this, try using `attribute_present?` instead. Seems to be built  
> for what you are trying to do. Haven’t used it personally so not sure.  
> Just dug it out of the API.

Hope this helps!  
-Nick

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [February 7, 2006, 3:41pm UTC](https://www.ruby-forum.com/t/delaying-initialization-of-associations-until-first-access/53465/6 "2006-02-07T15:41:02Z")

</div>

On Monday, February 06, 2006, at 8:44 PM, Nick S. wrote:

> You are going to need to save your house model seperatly from your  
> person model. But! If you always want to do this, through in a  
> before\_save filter for the person class that automatically saves the  
> house model at the same time. Should be simple enough.

This part works…when I set the before\_save filter, the House is indeed  
saved to the database. However:

> For this, try using `attribute_present?` instead. Seems to be built  
> for what you are trying to do. Haven’t used it personally so not sure.  
> Just dug it out of the API.

Switched it to attribute\_present?..same behavior. Isn’t surprising  
since attribute\_present? uses read\_attribute under the covers. So, while  
we’re successful in writing to the database, when you reload the Person  
object ActiveRecord for some reason doesn’t see the connection and  
attribute\_present? resolves false, therefore creating another entry in  
the table.

I am at a complete loss.

The code now looks like this:

def before\_save  
self.house.save  
end

def part\_count  
if !attribute\_present?(“house”)  
h = House.new  
h.color = “blue”  
h.person = self  
write\_attribute(“house”, h)  
end  
read\_attribute(“house”)  
end

Any other thoughts?

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [February 7, 2006, 3:41pm UTC](https://www.ruby-forum.com/t/delaying-initialization-of-associations-until-first-access/53465/7 "2006-02-07T15:41:03Z")

</div>

On Monday, February 06, 2006, at 8:44 PM, Nick S. wrote:

> You are going to need to save your house model seperatly from your  
> person model. But! If you always want to do this, through in a  
> before\_save filter for the person class that automatically saves the  
> house model at the same time. Should be simple enough.

This part works…when I set the before\_save filter, the House is indeed  
saved to the database. However:

> For this, try using `attribute_present?` instead. Seems to be built  
> for what you are trying to do. Haven’t used it personally so not sure.  
> Just dug it out of the API.

Switched it to attribute\_present?..same behavior. Isn’t surprising  
since attribute\_present? uses read\_attribute under the covers. So, while  
we’re successful in writing to the database, when you reload the Person  
object ActiveRecord for some reason doesn’t see the connection and  
attribute\_present? resolves false, therefore creating another entry in  
the table.

I am at a complete loss.

The code now looks like this:

def before\_save  
self.house.save  
end

def part\_count  
if !attribute\_present?(“house”)  
h = House.new  
h.color = “blue”  
h.person = self  
write\_attribute(“house”, h)  
end  
read\_attribute(“house”)  
end

Any other thoughts?

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [February 7, 2006, 3:44pm UTC](https://www.ruby-forum.com/t/delaying-initialization-of-associations-until-first-access/53465/8 "2006-02-07T15:44:06Z")

</div>

Update…I have it working!

I’m not sure why this works and our previous attempts didn’t (would love  
the explanation). greendale at [rails.technoweenie.net](http://rails.technoweenie.net) provided this  
code, which worked:

alias :\_house :house

def house  
\_house or self.house = House.new  
end

Now, that’s simple. I can’t understand when this worked and  
read\_attribute didn’t?
