Ruby on rails 項目啟動流程


眾所周知,我們可以通過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 } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在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 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

這個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 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

代碼執行到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 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

最終app 這個方法會加載項目config 目錄下的environment.rb這個文件如:

# Load the Rails application. require File.expand_path('../application', __FILE__) require 'whenever' module ProductConfig DYNAMIC_FIELDS = Hash.new end module 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!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

我們可以看到rack 為我們選定了默認的server.一般來說是WEBrick .然后WEBrick啟動,打印如下信息

INFO  WEBrick 1.3.1 INFO ruby 1.9.3 INFO WEBrick::HTTPServer#start: pid=28371 port=3000 
  • 1
  • 2
  • 3

如果安裝了其他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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

至此項目的啟動已完成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM