2012-02-25 15 views
5

Analizuję kod źródłowy szyny, ponieważ chciałbym zrozumieć wewnętrzne działanie has_many i podobnych konstrukcji.W jaki sposób zaimplementowano ruby ​​na szynach has_many (i podobne)?

Do tej pory udało mi się znaleźć, gdzie realizowany jest metoda (link to github): jest w module ActiveRecord :: Associations

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

Ten eventualy końce (link to github) w klasie ActiveRecord :: stowarzyszenia :: Builder :: CollectionAssociation jak

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

jest gdzie mój koniec umiejętności Ruby i nie mogłem śledzić go dalej i dowiedzieć się, gdzie jest „nowy” realizowany i co robi.

Czy ktoś może wskazać mi właściwy kierunek i może komentować, co się dzieje pod maską?

+4

+1 do przeglądania kodu źródłowego narzędzia używasz w celu uzyskania głębsze zrozumienie ich wewnętrznych elementów. Droga do celu. –

+1

@ s.m .: Zgadzam się. Jeśli czytanie kodu źródłowego nie "pokazuje wysiłku badawczego" (jak mówi podpowiedź do przycisku upvote), nie wiem, co robi! +1! –

+1

Dziękuję wszystkim za odpowiedź. Przyjąłem odpowiedź Jörga, ponieważ jest ona najbardziej szczegółowa. Ja też + +1 Baldrik i s.m. za to, że pierwszy odpowiedział. –

Odpowiedz

4

Zasadniczo new jest zdefiniowany następująco:

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 jest zdefiniowany następująco:

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 
1

new dzwoni do konstruktora bieżącej klasy. Konstruktorem jest metoda initialize zdefiniowana tuż po metodzie self.build w klasie CollectionAssociation. To czysta Ruby (ruby guide)

1

Aby rozwinąć na odpowiedź @ Baldrick, co jest słuszne, new jest zdefiniowana w Class zarówno jako metody klasy i metody instancji, a zatem jest dostępna dla wszystkich klas.

To, co robi, wywołuje zarówno allocate, jak i initialize (zakładając, że została zdefiniowana metoda initialize).

+0

Nie uważam, że "nowy" jest zdefiniowany jako metoda klasy. Klasa 'Class' jest instancją samą w sobie (yay, circularity!), Dlatego też działa' Class.new'. –

+0

@ JörgWMittag Nie jestem ekspertem od wewnętrznych elementów Ruby, ale dokumentacja pokazuje, że nowa jest zarówno klasą, jak i instancją klasy, jeśli dobrze pamiętam. –

+0

Właściwie to jest dokumentacja dla 'klasy # initialize'. RDoc po prostu * pokazuje * to jako dokumentację dla 'Class :: new'. Robi to dla * wszystkich * klas, ponieważ w ten sposób normalnie * używasz * metody 'initialize'. W rzeczywistości tak nie nazywasz, masz 'new', nazwij to dla siebie. Jeśli spojrzysz na kod źródłowy, zobaczysz, że blok dokumentacji znajduje się na szczycie funkcji 'rb_class_initialize', która odpowiada metodzie' Class # initialize'. –

Powiązane problemy