Ruby on rails 项目启动流程

来源:互联网 发布:程序员 手机壁纸 编辑:程序博客网 时间:2024/05/06 14:00

众所周知,我们可以通过rails s 这个命令来启动一个rails 项目,但是这条命令都干了哪些事呢?抽时间研究了下,同时感谢tomwang1013的博客。当我们输入rails s 这个命令的时候,项目会加载项目bin/rails.rb 这个文件
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'

通过代码我们可以看到这个文件中定义了一个APP_PATH 即我们的项目文件:config/application.rb,并require了config/boot,boot文件主要是做了bundle的初始化。
然后,我们可以看到这个时候rails/commands(railties-3.2.3/lib/rails/commands.rb)文件被load进来,由于我们传入的command参数为s,也就是server,然后我们看看commands的这个文件的源码对应的部分:

when 'server'                                                                                           # Change to the application's path if there is no config.ru file in current dir.                      # This allows us to run script/rails server from other directories, but still get                     # the main config.ru and properly set the tmp directory.                                              Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))    require 'rails/commands/server'                                                                       Rails::Server.new.tap { |server|                                                                        # We need to require application after the server sets environment,                                   # otherwise the --environment option given to the server won't propagate.                             require APP_PATH                                                                                      Dir.chdir(Rails.application.root)                                                                     server.start                                                                                        }    

在server 这个方法中我们通过server.start这行代码可以看出最终调用了start这个方法,然后查看下start 这个方法。同时这里面也打印了我们熟悉的控制台信息

def start                                                                            url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}"    puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"                   puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}"    puts "=> Call with -d to detach" unless options[:daemonize]    trap(:INT) { exit }    puts "=> Ctrl-C to shutdown server" unless options[:daemonize]    #Create required tmp directories if not found                                      %w(cache pids sessions sockets).each do |dir_to_make|                                FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make))                           end                                                                                puts 'server start ---'    super  ensure    # The '-h' option calls exit before @options is set.                               # If we call 'options' with it unset, we get double help banners.                  puts 'Exiting' unless @options && options[:daemonize]                            end   

这个start 这个方法最终会执行super 这个,super 会调用Rack::Server#start方法:代码

def start &blk    if options[:warn]      $-w = true                                                       end                                                                if includes = options[:include]      $LOAD_PATH.unshift(*includes)                                    end    if library = options[:require]                                       require library    end    if options[:debug]      $DEBUG = true                                                      require 'pp'      p options[:server]                                                 pp wrapped_app      pp app    end    # Touch the wrapped app, so that the config.ru is loaded before    # daemonization (i.e. before chdir, etc).                          wrapped_app    daemonize_app if options[:daemonize]                               write_pid if options[:pid]    trap(:INT) do      if server.respond_to?(:shutdown)                                     server.shutdown      else                                                                 exit      end                                                              end    server.run wrapped_app, options, &blk  end  

代码执行到server.run wrapped_app 这行代码。wrapped_app方法最终又会调用Rack::Server#app

def app    @app ||= begin                                                                    if !::File.exist? options[:config]                                                abort "configuration #{options[:config]} not found"                           end      app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)      self.options.merge! options      app    end  end     

最终app 这个方法会加载项目config 目录下的environment.rb这个文件如:

# Load the Rails application.require File.expand_path('../application', __FILE__)require 'whenever'module ProductConfig  DYNAMIC_FIELDS = Hash.newendmodule RestConfig  PRODUCT_SERVER = ENV["PHOTO_HOST"] || 'http://localhost:3001/'  #CUSTOMER_SERVER = ENV["CUSTOMER_HOST"] || 'http://localhost:3001/'  CUSTOMER_SERVER = ENV["CUSTOMER_HOST"] || 'http://localhost:3001/'  OA_SERVER = 'http://localhost:3001/'  #ELEPHANT_HOST = ENV["ELEPHANT_HOST"] || 'http://www.jiuyunda.net:90/'  ELEPHANT_HOST = ENV["ELEPHANT_HOST"] || 'http://localhost:3001/'  JXC_HOST = ENV["JXC_HOST"] || 'http://localhost:3001/'  SETTLE_HOST = ENV["SETTLE_HOST"] || 'http://localhost:3001/'end# Initialize the Rails application.Rails.application.initialize!

Rails.application.initialize!这行代码我们可以看出
项目的初始化完成。这个时候我们代码就回到Rack::Server#start方法的最后一行 server.run wrapped_app, options, &blk 由于我们没有设定任何参数。通过代码

def server                                                                           @_server ||= Rack::Handler.get(options[:server]) || Rack::Handler.default(options)  end      def self.default(options = {})            # Guess.                                if ENV.include?("PHP_FCGI_CHILDREN")      # We already speak FastCGI              options.delete :File                    options.delete :Port                    Rack::Handler::FastCGI                elsif ENV.include?("REQUEST_METHOD")      Rack::Handler::CGI                    else                                      begin                                     Rack::Handler::Thin                   rescue LoadError                          Rack::Handler::WEBrick                end                                   end                                   end            

我们可以看到rack 为我们选定了默认的server.一般来说是WEBrick .然后WEBrick启动,打印如下信息

INFO  WEBrick 1.3.1  INFO  ruby 1.9.3 INFO  WEBrick::HTTPServer#start: pid=28371 port=3000 

如果安装了其他application server的话打印的信息可能会不同如

Booting Puma=> Rails 4.2.4 application starting in development on http://localhost:3000=> Run `rails server -h` for more startup options=> Ctrl-C to shutdown server"assets end:false"Puma starting in single mode...* Version 3.4.0 (ruby 2.3.0-p0), codename: Owl Bowl Brawl* Min threads: 0, max threads: 16* Environment: development* Listening on tcp://localhost:3000

至此项目的启动已完成。

0 0
原创粉丝点击