# has\_many: unexpected behaviour

**URL:** <https://discuss.rubyonrails.org/t/has-many-unexpected-behaviour/5970>\
**Category:** rubyonrails-talk\
**Created:** [December 17, 2006, 5:18pm UTC](https://discuss.rubyonrails.org/t/has-many-unexpected-behaviour/5970 "2006-12-17T17:18:36Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chris\_T](https://avatars.discourse-cdn.com/v4/letter/c/a8b319/32.png) [@Chris\_T](https://discuss.rubyonrails.org/u/Chris_T)\
**Post date:** [December 17, 2006, 5:18pm UTC](https://discuss.rubyonrails.org/t/has-many-unexpected-behaviour/5970/1 "2006-12-17T17:18:36Z")

</div>

I've been using has\_many for quite a while now and thought I understood it fairly well (I'm on Edge Rails).

But I've come across some unexpected behaviour, and I wonder if anyone could shed some light on it.

If I assign a collection to a variable seems to change as the collection changes. IS that expected?

Quick example

Let's say:

human has\_many :cats cat belongs\_to :human and in this example bob is a Human with id 2 with 1 cat

bob = Human.find(2) bobs\_cats = bob.cats bobs\_cats.size #=\> 1 bob.cats.create(:name =\> "Tibbles") bobs\_cats.size #=\> 2

So, the variable bob\_cats is changing as the collection changes.

However if I replace the second line with bobs\_cats = bob.cats.find(:all) it behaves I would expect, i.e. behaves as an array of Cat objects, and is not affected by changes to the collection.

Can anyone shed any light on this?

---

<div class="post-metadata">

**Author:** ![Chris\_Hall](https://avatars.discourse-cdn.com/v4/letter/c/0ea827/32.png) [@Chris\_Hall](https://discuss.rubyonrails.org/u/Chris_Hall)\
**Post date:** [December 17, 2006, 7:22pm UTC](https://discuss.rubyonrails.org/t/has-many-unexpected-behaviour/5970/2 "2006-12-17T19:22:32Z")

</div>

yes, they are the same because of this line

bobs\_cats = bob.cats

they are the same instance. check the objects id's and you will see

> > bob.cats.object\_id

=\> 18829402

> > bobs\_cats.object\_id

=\> 18829402

> >

you should see something similar.

if you want a separate object, use .dup for duplicate

> > bobs\_cats = bob.cats.dup bobs\_cats.object\_id

=\> 19619092

> > bob.cats.object\_id

=\> 18829402

now there are two distinct objects

---

<div class="post-metadata">

**Author:** ![David\_A\_Black1](https://avatars.discourse-cdn.com/v4/letter/d/bcef8e/32.png) [@David\_A\_Black1](https://discuss.rubyonrails.org/u/David_A_Black1)\
**Post date:** [December 17, 2006, 7:40pm UTC](https://discuss.rubyonrails.org/t/has-many-unexpected-behaviour/5970/3 "2006-12-17T19:40:42Z")

</div>

Hi --

> > I've been using has\_many for quite a while now and thought I understood it fairly well (I'm on Edge Rails).
> > 
> > But I've come across some unexpected behaviour, and I wonder if anyone could shed some light on it.
> > 
> > If I assign a collection to a variable seems to change as the collection changes. IS that expected?
> > 
> > Quick example
> > 
> > Let's say:
> > 
> > human has\_many :cats cat belongs\_to :human and in this example bob is a Human with id 2 with 1 cat
> > 
> > bob = Human.find(2) bobs\_cats = bob.cats bobs\_cats.size #=\> 1 bob.cats.create(:name =\> "Tibbles") bobs\_cats.size #=\> 2
> > 
> > So, the variable bob\_cats is changing as the collection changes.
> > 
> > However if I replace the second line with bobs\_cats = bob.cats.find(:all) it behaves I would expect, i.e. behaves as an array of Cat objects, and is not affected by changes to the collection.
> > 
> > Can anyone shed any light on this?
> 
> yes, they are the same because of this line
> 
> bobs\_cats = bob.cats
> 
> they are the same instance. check the objects id's and you will see
> 
> > > bob.cats.object\_id
> 
> =\> 18829402
> 
> > > bobs\_cats.object\_id
> 
> =\> 18829402
> 
> > >
> 
> you should see something similar.
> 
> if you want a separate object, use .dup for duplicate
> 
> > > bobs\_cats = bob.cats.dup bobs\_cats.object\_id
> 
> =\> 19619092
> 
> > > bob.cats.object\_id
> 
> =\> 18829402
> 
> now there are two distinct objects

Just to elaborate a little further: this is happening because the object in question is an association proxy object. It gets created the first time, and then cached:

=\> #\<Tag:0xb75f6d1c @attributes={"body"=\>"Device", "id"=\>"1"}\>

> > things = tag.things

=\> \<things not loaded yet\> # (Ugh, but that's another story 🙂

> > things.object\_id

=\> -609253418

> > tag.things.object\_id

=\> -609253418

And when you call tag.things again, you get the same object:

> > tag.things.object\_id

=\> -609253418

It gets a little weirder here:

> > tag.things.reload

=\> [#\<Thing:0xb75e99dc @readonly=true, @attributes={"thing\_id"=\>"4", "tag\_id"=\>"1", "id"=\>"4"}\>, #\<Thing:0xb75e99c8 @readonly=true, @attributes={"thing\_id"=\>"1", "tag\_id"=\>"1", "id"=\>"21"}\>, #\<Thing:0xb75e99a0 @readonly=true, @attributes={"thing\_id"=\>"2", "tag\_id"=\>"1", "id"=\>"22"}\>]

> > tag.things.object\_id

=\> -609268288

> > things.object\_id

=\> -609268288

The object\_id of things has changed, though things has not been reassigned. Rather bizarre from the Ruby point of view, and not particularly to my taste; I prefer to know what's going to happen when I assign to a variable, and to be the one who decides if and when the binding will change. But it's unlikely to cause trouble in practice, as far as I can tell.

David

---

<div class="post-metadata">

**Author:** ![Chris\_T](https://avatars.discourse-cdn.com/v4/letter/c/a8b319/32.png) [@Chris\_T](https://discuss.rubyonrails.org/u/Chris_T)\
**Post date:** [December 17, 2006, 8:01pm UTC](https://discuss.rubyonrails.org/t/has-many-unexpected-behaviour/5970/4 "2006-12-17T20:01:21Z")

</div>

OK. That makes sense. Guess I never quite connected (in my mind) the Array of AR objects that is bob.cats and the bob.cats.create or whatever. I'm guess the additional has\_many methods are available to the array through some sort of method\_missing magic?

Thanks for your help. Chris

Chris Hall wrote:

---

<div class="post-metadata">

**Author:** ![Chris\_T](https://avatars.discourse-cdn.com/v4/letter/c/a8b319/32.png) [@Chris\_T](https://discuss.rubyonrails.org/u/Chris_T)\
**Post date:** [December 17, 2006, 8:07pm UTC](https://discuss.rubyonrails.org/t/has-many-unexpected-behaviour/5970/5 "2006-12-17T20:07:17Z")

</div>

dblack@wobblini.net wrote:

> Hi --
> 
> > > I've been using has\_many for quite a while now and thought I understood it fairly well (I'm on Edge Rails).
> > > 
> > > But I've come across some unexpected behaviour, and I wonder if anyone could shed some light on it.
> > > 
> > > If I assign a collection to a variable seems to change as the collection changes. IS that expected?
> > > 
> > > Quick example
> > > 
> > > Let's say:
> > > 
> > > human has\_many :cats cat belongs\_to :human and in this example bob is a Human with id 2 with 1 cat
> > > 
> > > bob = Human.find(2) bobs\_cats = bob.cats bobs\_cats.size #=\> 1 bob.cats.create(:name =\> "Tibbles") bobs\_cats.size #=\> 2
> > > 
> > > So, the variable bob\_cats is changing as the collection changes.
> > > 
> > > However if I replace the second line with bobs\_cats = bob.cats.find(:all) it behaves I would expect, i.e. behaves as an array of Cat objects, and is not affected by changes to the collection.
> > > 
> > > Can anyone shed any light on this? &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> > 
> > yes, they are the same because of this line
> > 
> > bobs\_cats = bob.cats
> > 
> > they are the same instance. check the objects id's and you will see
> > 
> > > > bob.cats.object\_id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> > 
> > =\> 18829402 &nbsp;&nbsp;&nbsp;&nbsp;
> > 
> > > > bobs\_cats.object\_id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> > 
> > =\> 18829402 &nbsp;&nbsp;&nbsp;&nbsp;you should see something similar.
> > 
> > if you want a separate object, use .dup for duplicate
> > 
> > > > bobs\_cats = bob.cats.dup bobs\_cats.object\_id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> > 
> > =\> 19619092 &nbsp;&nbsp;&nbsp;&nbsp;
> > 
> > > > bob.cats.object\_id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> > 
> > =\> 18829402
> > 
> > now there are two distinct objects &nbsp;&nbsp;&nbsp;&nbsp; Just to elaborate a little further: this is happening because the object in question is an association proxy object. It gets created the first time, and then cached:
> 
> =\> #\<Tag:0xb75f6d1c @attributes={"body"=\>"Device", "id"=\>"1"}\> &nbsp;&nbsp;
> 
> > > things = tag.things &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> 
> =\> \<things not loaded yet\> # (Ugh, but that's another story 🙂&nbsp;&nbsp;
> 
> > > things.object\_id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> 
> =\> -609253418 &nbsp;&nbsp;
> 
> > > tag.things.object\_id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> 
> =\> -609253418
> 
> And when you call tag.things again, you get the same object:
> 
> > > tag.things.object\_id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> 
> =\> -609253418
> 
> It gets a little weirder here:
> 
> > > tag.things.reload &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> 
> =\> [#\<Thing:0xb75e99dc @readonly=true, @attributes={"thing\_id"=\>"4", "tag\_id"=\>"1", "id"=\>"4"}\>, #\<Thing:0xb75e99c8 @readonly=true, @attributes={"thing\_id"=\>"1", "tag\_id"=\>"1", "id"=\>"21"}\>, #\<Thing:0xb75e99a0 @readonly=true, @attributes={"thing\_id"=\>"2", "tag\_id"=\>"1", "id"=\>"22"}\>] &nbsp;&nbsp;
> 
> > > tag.things.object\_id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> 
> =\> -609268288 &nbsp;&nbsp;
> 
> > > things.object\_id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> 
> =\> -609268288
> 
> The object\_id of things has changed, though things has not been reassigned. Rather bizarre from the Ruby point of view, and not particularly to my taste; I prefer to know what's going to happen when I assign to a variable, and to be the one who decides if and when the binding will change. But it's unlikely to cause trouble in practice, as far as I can tell.
> 
> David

David

Thanks for this. Have been getting so much into the Ruby aspect of Rails recently (not least thanks to your excellent book) sort of forgot about some of the strange things that Rails does. Cheers Chris
