# ActiveRecord AssociationProxy magic?

**URL:** <https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153>\
**Category:** Rails\
**Created:** [November 3, 2007, 9:27pm UTC](https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153 "2007-11-03T21:27:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![ericgoodwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/c68b51/32.png) [@ericgoodwin](https://www.ruby-forum.com/u/ericgoodwin)\
**Post date:** [November 3, 2007, 9:27pm UTC](https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153/1 "2007-11-03T21:27:09Z")

</div>

In the following ActiveRecord code, it defines a method to access  
associations like user.addresses (has\_many)

```
    def collection_reader_method(reflection,

```

association\_proxy\_class)  
define\_method(reflection.name) do |\*params|  
force\_reload = params.first unless params.empty?  
association = instance\_variable\_get("@#{reflection.name}")

```
        unless association.respond_to?(:loaded?)
          association = association_proxy_class.new(self,

```

reflection)  
instance\_variable\_set("@#{reflection.name}", association)  
end

```
        association.reload if force_reload

        association
      end
    end

```

What is so weird is that association\_proxy\_class.new(self, reflection)  
returns an object of type Array for a has\_many, yet, if you look in  
HasManyAssociation, at the initialize method, it is :

```
  def initialize(owner, reflection)
    super
    construct_sql
  end

```

which returns a Sql String. How the heck does it instantiate an array?  
And then how does that array have all the active record methods on it,  
like being able to do book.pages.find(:first). After all, the return  
object is of type Array, not some class that extends Array and includes  
those methods.

What am I missing here?

---

<div class="post-metadata">

**Author:** ![ericgoodwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/c68b51/32.png) [@ericgoodwin](https://www.ruby-forum.com/u/ericgoodwin)\
**Post date:** [November 3, 2007, 10:14pm UTC](https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153/2 "2007-11-03T22:14:27Z")

</div>

On 3 Nov 2007, at 20:27, Aryk G. wrote:

> which returns a Sql String. How the heck does it instantiate an array?  
> And then how does that array have all the active record methods on it,  
> like being able to do book.pages.find(:first). After all, the return  
> object is of type Array, not some class that extends Array and  
> includes  
> those methods.

say you have User, User has\_many :addresses.  
User.addresses is not an array. It looks like an array, it quacks like  
an array but it’s actually an association proxy pretending to be an  
array. It manages an actual array with the elements of the collection  
and (via method\_missing) lets that array handle most calls.

Fred

---

<div class="post-metadata">

**Author:** ![ericgoodwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/c68b51/32.png) [@ericgoodwin](https://www.ruby-forum.com/u/ericgoodwin)\
**Post date:** [November 3, 2007, 10:25pm UTC](https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153/3 "2007-11-03T22:25:13Z")

</div>

Frederick C. wrote:

> On 3 Nov 2007, at 20:27, Aryk G. wrote:
> 
> > which returns a Sql String. How the heck does it instantiate an array?  
> > And then how does that array have all the active record methods on it,  
> > like being able to do book.pages.find(:first). After all, the return  
> > object is of type Array, not some class that extends Array and  
> > includes  
> > those methods.
> 
> say you have User, User has\_many :addresses.  
> User.addresses is not an array. It looks like an array, it quacks like  
> an array but it’s actually an association proxy pretending to be an  
> array. It manages an actual array with the elements of the collection  
> and (via method\_missing) lets that array handle most calls.
> 
> Fred  
> So why is it that when I do, User.addresses.class, I dont get  
> HasManyAssociation, and Array instead? Where in AR does it actually make  
> it so that calling .class will yield Array instead of the proxy class  
> that it actually is. The HasManyAssociation class, for example, is not  
> even superclassed by an array.

---

<div class="post-metadata">

**Author:** ![ericgoodwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/c68b51/32.png) [@ericgoodwin](https://www.ruby-forum.com/u/ericgoodwin)\
**Post date:** [November 3, 2007, 10:40pm UTC](https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153/4 "2007-11-03T22:40:12Z")

</div>

On 3 Nov 2007, at 21:25, Aryk G. wrote:

> HasManyAssociation, and Array instead? Where in AR does it actually  
> make  
> it so that calling .class will yield Array instead of the proxy class  
> that it actually is. The HasManyAssociation class, for example, is not  
> even superclassed by an array.

because the class method is also proxyed through to the target array,  
which returns Array because it is one.

Fred

---

<div class="post-metadata">

**Author:** ![ericgoodwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/c68b51/32.png) [@ericgoodwin](https://www.ruby-forum.com/u/ericgoodwin)\
**Post date:** [November 4, 2007, 11:52am UTC](https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153/5 "2007-11-04T11:52:32Z")

</div>

On 4 Nov 2007, at 02:02, Aryk G. wrote:

> when you say the class method, you mean like has\_many, belongs\_to,  
> etc?  
> Can you point to me in the code where this is done. Where lines of  
> code  
> are responsible for the “proxy through to the target array” part.

No I mean the method “class”, which you call to get the class of an  
object. The code you are interested in is in association\_proxy.rb

---

<div class="post-metadata">

**Author:** ![ericgoodwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/c68b51/32.png) [@ericgoodwin](https://www.ruby-forum.com/u/ericgoodwin)\
**Post date:** [November 5, 2007, 5:45pm UTC](https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153/6 "2007-11-05T17:45:11Z")

</div>

Ok, Im looking in association\_proxy.rb and I can’t find where they  
overwrite the “class” method to return Array.

Should I be looking in a different file?

Aryk

Frederick C. wrote:

> On 4 Nov 2007, at 02:02, Aryk G. wrote:
> 
> > when you say the class method, you mean like has\_many, belongs\_to,  
> > etc?  
> > Can you point to me in the code where this is done. Where lines of  
> > code  
> > are responsible for the “proxy through to the target array” part.
> 
> No I mean the method “class”, which you call to get the class of an  
> object. The code you are interested in is in association\_proxy.rb

---

<div class="post-metadata">

**Author:** ![ericgoodwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/c68b51/32.png) [@ericgoodwin](https://www.ruby-forum.com/u/ericgoodwin)\
**Post date:** [November 4, 2007, 3:02am UTC](https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153/7 "2007-11-04T03:02:31Z")

</div>

when you say the class method, you mean like has\_many, belongs\_to, etc?  
Can you point to me in the code where this is done. Where lines of code  
are responsible for the “proxy through to the target array” part.

Thanks for the help,  
Aryk

Frederick C. wrote:

> On 3 Nov 2007, at 21:25, Aryk G. wrote:
> 
> > HasManyAssociation, and Array instead? Where in AR does it actually  
> > make  
> > it so that calling .class will yield Array instead of the proxy class  
> > that it actually is. The HasManyAssociation class, for example, is not  
> > even superclassed by an array.
> 
> because the class method is also proxyed through to the target array,  
> which returns Array because it is one.
> 
> Fred

---

<div class="post-metadata">

**Author:** ![ericgoodwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/c68b51/32.png) [@ericgoodwin](https://www.ruby-forum.com/u/ericgoodwin)\
**Post date:** [November 5, 2007, 6:22pm UTC](https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153/8 "2007-11-05T18:22:09Z")

</div>

Frederick C. wrote:

> On 5 Nov 2007, at 16:45, Aryk G. wrote:
> 
> > Ok, Im looking in association\_proxy.rb and I can’t find where they  
> > overwrite the “class” method to return Array.
> > 
> > Should I be looking in a different file?
> 
> Nope. The point is that it’s not overwriting anything: it’s (at the  
> top) undefining just about every method (including class) and then, in  
> method\_missing it forwards on the method to the target
> 
> Fred

yup, now i got it! Thanks for the help, this has been bugging me for  
quite a while. Although, this seems very hacky to me, whats your take?

---

<div class="post-metadata">

**Author:** ![ericgoodwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/c68b51/32.png) [@ericgoodwin](https://www.ruby-forum.com/u/ericgoodwin)\
**Post date:** [November 5, 2007, 6:08pm UTC](https://www.ruby-forum.com/t/activerecord-associationproxy-magic/119153/9 "2007-11-05T18:08:42Z")

</div>

On 5 Nov 2007, at 16:45, Aryk G. wrote:

> Ok, Im looking in association\_proxy.rb and I can’t find where they  
> overwrite the “class” method to return Array.
> 
> Should I be looking in a different file?

Nope. The point is that it’s not overwriting anything: it’s (at the  
top) undefining just about every method (including class) and then, in  
method\_missing it forwards on the method to the target

Fred
