猫の魔法

主にruby系の技術メモを記載

railsの起動プロセスを追う その2

はじめに

だいぶ間が空いてしまいましたが、 railsの起動までを見ていこう第2段ということで、今回はserver_command.rbperformから見ていこうと思います。 以下の「railsの起動プロセスを追う」の部分に各回へのリンクがあります。

rails調査系まとめ - 猫の魔法

Serverの起動

rails/server_command.rb at v5.2.1 · rails/rails · GitHub

perform の主目的はサーバの起動です。つまりこの解析が終わるとrailsの起動は完了することになります。

      def perform
        set_application_directory!
        prepare_restart
        Rails::Server.new(server_options).tap do |server|
          # Require application after server sets environment to propagate
          # the --environment option.
          require APP_PATH
          Dir.chdir(Rails.application.root)
          server.start
        end
      end

set_application_directory!prepare_restart は大したことはしていないので飛ばして、Rails::Server.new から見ていきます。

rails/server_command.rb at v5.2.1 · rails/rails · GitHub

    def initialize(options = nil)
      @default_options = options || {}
      super(@default_options)
      set_environment
    end

このメソッド自体はほとんど何もしていないので、super 先を見ていきます。

rack/server.rb at 2.0.5 · rack/rack · GitHub

    def initialize(options = nil)
      @ignore_options = []

      if options
        @use_default_options = false
        @options = options
        @app = options[:app] if options[:app]
      else
        argv = defined?(SPEC_ARGV) ? SPEC_ARGV : ARGV
        @use_default_options = true
        @options = parse_options(argv)
      end
    end

これはインスタンスを返しているだけのようです。

ということで、server_command.rb の方に戻ります。 次に注目すべきはtap の中の以下の部分です。

          require APP_PATH
          Dir.chdir(Rails.application.root)
          server.start

APP_PATH はどこに定義さているのでしょうか?

実を言うと、追ってきたソースの中に一度出てきています。 記憶のいい方は覚えているかもしれないですが(自分は記憶が悪い方なので、一生懸命探しましたが。。。)、 一番最初のbin/rails 内にて定義されています。

#!/usr/bin/env ruby
begin
  load File.expand_path('../spring', __FILE__)
rescue LoadError => e
  raise unless e.message.include?('spring')
end
APP_PATH = File.expand_path('../config/application', __dir__)
require_relative '../config/boot'
require 'rails/commands'

ということで、APP_PATHは File.expand_path('../config/application', __dir__) になります。 ./config/application.rbrails new したときに作成されるファイルで、中身は以下のような物になります。

require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module TestRails
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
  end
end

require 'rails/all' で取り込んでいる rails/all.rbrailsを構成している各モジュールの初期化モジュールをrequireしています。

rails/all.rb at v5.2.1 · rails/rails · GitHub

require "rails"

%w(
  active_record/railtie
  active_storage/engine
  action_controller/railtie
  action_view/railtie
  action_mailer/railtie
  active_job/railtie
  action_cable/engine
  rails/test_unit/railtie
  sprockets/railtie
).each do |railtie|
  begin
    require railtie
  rescue LoadError
  end
end

あんまり一気にやろうとすると分からなくなってくるので今日はここまで。