2013-03-22 8 views
8

Rack specifiesDlaczego Railsy generują plik config.ru, który uruchamia klasę, a nie obiekt?

Aplikacja Rack jest obiektem Ruby (nie klasa), który odpowiada na połączenie.

konsekwencji prosty config.ru wygląda następująco:

class MyApp 
    def call(env) 
    [200, {"Content-Type" => "text/plain"}, ["Hello from Rack!\n"]] 
    end 
end 

run MyApp.new 

podczas Rails generuje to:

# This file is used by Rack-based servers to start the application. 

require ::File.expand_path('../config/environment', __FILE__) 
run RailsApp::Application 

Więc zastanawiam się: dlaczego nie run RailsApp::Application.new gdy Rack określa ją jako obiekt, a nie klasa? Czy jest coś szczególnego w tym, czego mi brakuje Rails::Application?

Odpowiedz

15

To jest rzeczywiście nieco ukryte :)

RailsApp::Application jest klasa dzieckiem Rails::Application, który z kolei jest Rails::Engine który jest Rails::Railtie. Teraz Rails::Railtie ma numer inherited hook, który jest wywoływany za każdym razem, gdy klasa potomna dziedziczy z klasy Railtie (w tym przypadku Engine).

Ten wywołanie zwrotne zawiera moduł Rails::Railtie::Configurable do podklasy. W tym module znajdziesz pierwszą część magii.

Sposób method_missing który zostanie określony na klasy wywołuje metodę na instancji klasy, która bardziej lub mniej postanawia

RailsApp::Application.new.call(...) 

Ta metoda call instancja jest zdefiniowana w Rails::Application#call i robi typowy przekazanie Rack .

Prawdopodobnie jest jeszcze trochę więcej magii, co sprawia, że ​​nie jest w 100% równoważny, ale to powinno być z grubsza ...

1

Klasa jest również przedmiotem. Rack nie tworzy instancji obiektu aplikacji (dlatego określa, że ​​musisz dostarczyć obiekt), robisz to w config.ru, więc pod warunkiem, że obiekt klasy Rails będzie zgodny z wszystkimi zasadami Rack, gdy Rack wyśle ​​"call", nie powinno być problem.

Wewnętrznie, nie wiem, czy Rails robi coś specjalnego na call. Może to być nawet metoda fabryczna, która wypluwa instancję klasy aplikacji i uruchamia ją. Ale nie musi to być satysfakcjonujące Rack.