How is ruby on rails has_many (and similar) implemented?
Asked Answered
W

3

8

I am analysing the rails source code, because I wold like to understand the inner workings of the has_many and similar constructs.

So far, I was able to find where the method is implemented (link to github): it is in the module ActiveRecord::Associations

def has_many(name, options = {}, &extension)
  Builder::HasMany.build(self, name, options, &extension)
end

This one eventualy ends (link to github) in the class ActiveRecord::Associations::Builder::CollectionAssociation as

def self.build(model, name, options, &extension)
  new(model, name, options, &extension).build
end

There is where my ruby skills end and I could not track it further and find where is "new" implemented and what it does.

Can someone point me to the right direction and maybe comment along, what is going on under the hood?

Washcloth answered 25/2, 2012 at 22:53 Comment(3)
+1 for perusing the source code of the tools you're using in order to gain a deeper understanding of their internals. Way to go.Karaite
@s.m.: I agree. If reading the source code doesn't "show research effort" (as the tooltip for the upvote button says), I don't know what does! +1!Petuntse
Thanks everyone for answering. I accepted Jörg's answer, because it is most detailed. I also +1 Baldrik and s.m. for being the first who answered.Washcloth
S
4

Basically, new is defined like this:

class Class
  def new(*args, &block)
    obj = allocate

    obj.initialize(*args, &block)
    # *actually* obj.send(:initialize, *args, &block) since initialize is private

    obj
  end
end

allocate is defined like this:

class Class
  def allocate
    # magic stuff for creating an empty object which cannot be expressed in Ruby:

    new_obj = Deep::Within::VM.__somehow_magically_allocate_memory__!

    new_obj.__class__ = self

    new_obj
  end
end
Sporophyll answered 26/2, 2012 at 2:44 Comment(0)
D
1

new calls the constructor of the current class. The constructor is the method initialize that is defined just after self.build method in the class CollectionAssociation . It's pure Ruby (ruby guide)

Debose answered 25/2, 2012 at 22:59 Comment(0)
K
1

To expand on @Baldrick's answer, which is correct, new is defined in Class as both a class method and an instance method, and is hence available to all classes.

What new does is invoking both allocate and initialize (assuming an initialize method has been defined).

Karaite answered 25/2, 2012 at 23:11 Comment(3)
I don't think new is defined as a class method. The Class class is an instance of itself (yay, circularity!), that's why Class.new works.Petuntse
@JörgWMittag I'm not an expert of Ruby's internals whatsoever, but the documentation shows that new is both a class and instance method of Class, if I recall correctly.Karaite
Actually, that's the documentation for Class#initialize. RDoc just shows it as the documentation for Class::new. It does this for all classes, because that's how you normally use the initialize method. You don't actually call it, you have new call it for you. If you look at the source code, you can see that the documentation block sits atop the rb_class_initialize function which corresponds to the Class#initialize method.Petuntse

© 2022 - 2024 — McMap. All rights reserved.