sでRailsサーバーが起動するまでに何が起きているのかを紐解くことでRailsとは何なのかを理解していきたい。今回読んでいくソースコードのコミットは2d9b9fb5b5f6015e66d3ad5cb96bc1ba117fd626だ。sがユーザーによって実行される。Gemfileで管理されるrubygemをrequireする。Rails::CommandsTasks#serverを実行する。config/application.rbをrequireする。Railsを構成する各rubygemのrailtieをrequireする。各rubygemのinitializerが登録される。config.ruが実行される。登録されたinitializerが実行される。RailsアプリケーションがRackアプリケーションとして起動する。コマンドの実行まずbin/railsを見る。newを実行したときに生成されるのだが、このひな形はrailties/lib/rails/generators/rails/app/templates/bin/railsにある。'rails/commands'config/boot.rbとrails/commands.rbを見る。Gemfile.config/boot.rbはGemfileにあるgemをrequireするようだ。serverを実行することになる。rails/commands/commands_tasksを見る。endend#parse_commandは--versionや--helpをそれぞれ"version"と"help"というコマンドに変換するもの。それ以外はそのまま返す。COMMAND_WHITELISTに含まれていれば実行、そうでなければエラーを出力する。今回は"server"がcommandに入るのでsend("server")が実行され、#serverが実行されることになる。sを実行できるようにするためのものらしい。"config/application"をserver.startの前に実行している。"bundler/setup"を実行しておりGemfile.lockに記載されたバージョンのrubygemをrequireしている。rails/all.rbを見る。endendRailsを構成する各rubygemのrailtieをrequireしている。rails.rbを見る。Rails.envなどの重要なメソッドが定義されているため、登場次第また見ていくことにする。rails/all.rbとrails.rbについて見たので、config/applicationに戻る。endendRails.groupsは上述したrails.rbで定義されているのでさっそく見る。endendRails.groupsはRails.envの値に合わせてBundlerが読みこむべきgroupを返す。Rails.envは環境変数"RAILS_ENV"または"RACK_ENV"から実行環境を返す。config/application.rbに戻る。endendSampleApp::ApplicationがRails::Applicationを継承するとき、以下のような実装によってRails::Application.inheritedが呼ばれ、Rails.app_classがSampleApp::Applicationとなる。endendサーバーの起動サーバー起動前にどういった設定を読み込んでいるか見たので、サーバーの起動について詳細に見ていく。"rails/commands/server"をしている。Rails::Serverはrails/commands/server.rbで定義されているので見る。endendスーパークラスの::Rack::Serverがサーバー起動において主な役割を果たしているようだ。これ以降はRackのソースコードを追うことになるが本題から反れるので、結論だけ言うとconfig.ruが実行されることになる。config.ruを見る。Rails.applicationconfig/environment.rbを読み込んでいる。その後Rails.applicationをrackアプリケーションとして実行している。config/environment.rbを見る。)Rails.application.initialize!config/application.rbは既に読み込まれているはず。Rails.application.initialize!について見ていくため、まずはRails.applicationの定義を見る。endendapp_classは、config/application.rbでRails::Applicationのサブクラスが定義されたときにそのサブクラスが代入される。SampleApp::Application.instanceが呼ばれているが、これのメソッドはRails::Applicationに定義されていると思われる。Rails::Applicationを見る。endendSampleApp::Application.instance内でsuper.run_load_hooks!が呼ばれている。このsuperはスーパークラスで定義された.instanceを呼んでおり、スーパークラスをたどるとRails::Railtie.instanceが呼ばれていることがわかる。これはそのままnewを呼んでインスタンスを返すだけだ。super.run_load_hooks!というのはSampleApp::Application#run_load_hooks!を指す。SampleApp::Application#run_load_hooks!はRails::Applicationで上のように定義されており自分自身を返す。self)を呼んでおり、これによって:before_configurationをフックとして登録しておいた処理が実行される。結局、Rails.applicationはSampleApp::Applicationインスタンスということになる。initializerの実行config/environment.rbに戻る。)Rails.application.initialize!Rails.application.initialize!はつまりSampleApp::Application#initialize!ということ。Rails::Applicationを見る。endend#run_initializersはRails::Initializableで以下のように定義されている。endend#initializersはRails::Applicationで以下のように定義されている。endendBootstrap.initializers_forとかFinisher.initializers_forはRails::Initializableモジュールで以下のように定義されている。})endInitializable::Collectionを初期化しているようだ。endendTSortモジュールはRubyの標準モジュールで、依存関係を解決する順番に並び替える(=トポロジカルソート)実装を提供する。#tsort_each_nodeと#tsort_each_childの2つを実装する必要がある。#tsort_each_nodeはすべての要素を走査するメソッド、#tsort_each_childは子要素を走査するメソッド。Collection#tsort_each_childでは与えられたinitializerの前後のinitlaizerに対してブロックを実行する。Initializable.initializers_forに戻る。})end続いて.initializers_chainを見る。.ancestorsはスーパークラスやincludeしているモジュールを直接の親から順に並べて配列で返す。.ancestors.reverse_eachなので、最も遠いクラスまたはモジュールから順にinitializersを取得して一つのCollectionに連結させている。initializers_chainの要素はおそらくInitializerインスタンスだと思われるので、Initializer#bindを見る。endendInitializer#initializeの第2引数は、Initializer#runでinstance_execのレシーバとして利用される。今回の場合、これはRails::Applicationインスタンスとなる。Rails::Application#initializersに戻る。endend#railties_initializersがまだ残っているので見る。endendconfig.railties_orderはデフォルトでは[:all]を返すようになっているが、ここを変更することで実行するRailtieのinitializerの順番を変更することもできるようだ。order)の部分なので、あとで詳しく#railtiesについて見る。ある順番でソートされた各Railtieのinitializersを結合して返している。#railtiesはRails::Engineから継承されたメソッドなので見る。Railties.newendRails::Engine::Railtiesを見る。::Rails::Engine.subclasses.map(&:instance)end::Rails::RailtieまたはRails::Engineのサブクラスをすべて返している(!)railties_initializersに戻る。initializersendordered_railtiesは::Rails::Railtieまたは::Rails::Engineのサブクラスすべてだということがわかった。よって、それらのinitializersをすべて連結したものを返していることになる。Rails::Application#initializersについて見たので、#run_initializersに戻る。trueendinitializersはInitializable::Collectionインスタンスなので、#tsort_eachによって依存関係を解決する順番で#eachを行う。Initializer#runを見る。endend@contextは#bindによってセットされる。blockはInitializerが初期化される際に渡されたブロックだ。このblockは#bindによってセットされた@contextをレシーバとして実行される。今回の場合、@contextはRails::Applicationインスタンスをレシーバとしてblockが実行されることになる。続いて、実行されるInitializerがどのように初期化されて登録されているのか見ていく。これはRails::Initializable::ClassMethods.initializerによって行われる。&blk)endopts[:after]はInitializerインスタンス間の依存関係の解決に利用される。initializerで特に指定しなければ既存のinitializersの最後の要素がinitializer#afterになる。Railsアプリケーションの起動initializersの実行について一通り眺めたのでこれでconfig/environment.rbを読んだことになる。config.ruに戻る。Rails.applicationでアプリケーションを起動できる。Rails.applicationがSampleApp::Applicationインスタンスであることは上述の通り。DeckHomePosts。