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?
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
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
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
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
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
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?
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