不论是script/console 还是 script/server 都会调用前置的文件:config/boot
现在分析一下这个文件的源代码,看看究竟做了哪些工作。
config/boot.rb阅读:
# Don't change this file!
# Configure your app in config/environment.rb and config/environments/*.rb
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
module Rails
... ...
end
# All that for this:
Rails.boot!
看这个模块定义之外的代码就首尾两行,比较直观。
Rails模块内容:
#启动,做了两件事
class << self
def boot!
unless booted?
preinitialize
pick_boot.run
end
end
# 可以在preinitialize这里写一个patch,做些rails启动之前的操作:
def preinitializer_path
"#{RAILS_ROOT}/config/preinitializer.rb"
end
# pick_boot会找是用系统安装的rails还是固化到vender目录的rails
#1 verder的rails加载,3个步骤
class VendorBoot < Boot
def load_initializer
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
Rails::Initializer.run(:install_gem_spec_stubs)
Rails::GemDependency.add_frozen_gem_path
end
end
#2 系统安装的rails加载
class GemBoot < Boot
def load_initializer
self.class.load_rubygems #=>require 'rubygems'操作和检查版本
load_rails_gem #=>gem 'rails', version
require 'initializer'
end
# rails 是要用系统安装的,还是vender目录的,启动的时候仅仅有没有这个目录来决定
def vendor_rails?
File.exist?("#{RAILS_ROOT}/vendor/rails")
end
# rails启动之前,如果想做些操作,放在哪里呢
def preinitializer_path
"#{RAILS_ROOT}/config/preinitializer.rb"
end
# rails 启动的时候,知道gem版本么
def gem_version
if defined? RAILS_GEM_VERSION
RAILS_GEM_VERSION
elsif ENV.include?('RAILS_GEM_VERSION')
ENV['RAILS_GEM_VERSION']
else
parse_gem_version(read_environment_rb)
end
end
private
def read_environment_rb
File.read("#{RAILS_ROOT}/config/environment.rb")
end
看见了么,只能在environment.rb里申明,如果是自己配置的话,不能在例如development.rb里申明
# EVN在很多地方用到,他在哪里定义的呢(我并没有发现在config里面定义的地方)
Ok吧,在这里
irb;Object.const_get('ENV') 或者用这个命令ruby -e 'puts Object.const_get("ENV").inspect'
# 一个设计模式,AcstractClass,父类没有必要非要显式申明一个接口给子类
java等编译型语言需要这么做,因为编译的时候会检查
非编译型语言可以不这么做
但申明的话,会更好看些,利于团队合作
class Boot
def run
load_initializer
Rails::Initializer.run(:set_load_path)
end
end
class VendorBoot < Boot
def load_initializer
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
Rails::Initializer.run(:install_gem_spec_stubs)
Rails::GemDependency.add_frozen_gem_path
end
end
最终Rails.boot!做了什么
class Boot
def run
load_initializer #选取了自带的rails还是vender的rails
Rails::Initializer.run(:set_load_path) #这个是关键语句
end
end
#run的代码:
Rails::Initializer.run(:set_load_path) #做了什么
def self.run(command = :process, configuration = Configuration.new) #这里已经new了一个conf
yield configuration if block_given? #可以修改conf的配置
initializer = new configuration #new 一个 initializer
initializer.send(command) #执行command #-->>这里就是要执行:set_laod_path
initializer
end
#
set_laod_path的执行作用:
# Rails::Initializer.run(:set_load_path)
#
# This is useful if you only want the load path initialized, without
# incurring the overhead of completely loading the entire environment.
# Set the <tt>$LOAD_PATH</tt> based on the value of
# Configuration#load_paths. Duplicates are removed.
def set_load_path
load_paths = configuration.load_paths + configuration.framework_paths
load_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) } #移除if it is not dir
$LOAD_PATH.uniq!
end
#到底有多少framework:
def framework_paths
paths = %w(railties railties/lib activesupport/lib) #3个
#1个,其实actionpack会加载:action_controller和:action_view
paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view)
[:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework| #4个
paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include?(framework)
end
paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
end
==>>总结:
require File.expand_path('../../config/boot', __FILE__)
这个文件执行Rails.boot!,作用:
#1 根据有没有vender的rails,确定了使用rails的路径
#2 初始化了rails的环境路径(load_paths)(configuration.load_paths + configuration.framework_paths)
+
+
+
||
+
+
+