Rails源码阅读(11)Rails使用bundle保持多机器环境gem版本的一致性
====rails3====
文件conf/book.rb
require 'rubygems' # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
require 'rubygems' #这个ruby1。9后已经不需要了
后面的几句就是启动bundle,把gem包加载进来。
熟悉ruby包加载原理的,估计能猜出来bundle和Gemfile都做了啥,就是把用到的包路径加载进ruby寻找的路径中,从而在使用某个rb文件的时候,可以从某个路径下面找出来。
让我们验证一下吧。
文件bundler/setup
require 'bundler/shared_helpers' if Bundler::SharedHelpers.in_bundle? require 'bundler' if STDOUT.tty? begin Bundler.setup rescue Bundler::BundlerError => e puts "\e[31m#{e.message}\e[0m" puts e.backtrace.join("\n") if ENV["DEBUG"] if Bundler::GemNotFound === e puts "\e[33mRun `bundle install` to install missing gems.\e[0m" end exit e.status_code end else Bundler.setup end # Add bundler to the load path after disabling system gems bundler_lib = File.expand_path("../..", __FILE__) $LOAD_PATH.unshift(bundler_lib) unless $LOAD_PATH.include?(bundler_lib) end
这个文件核心就这一句:Bundler.setup
文件bundler。rb
。。。 。。。 def setup(*groups) # Just return if all groups are already loaded return @setup if defined?(@setup) if groups.empty? # Load all groups, but only once @setup = load.setup else @completed_groups ||= [] # Figure out which groups haven't been loaded yet unloaded = groups - @completed_groups # Record groups that are now loaded @completed_groups = groups unloaded.any? ? load.setup(*groups) : load end end def require(*groups) setup(*groups).require(*groups) end def load @load ||= Runtime.new(root, definition) end 。。。 。。。
这个文件比较大,是用来加载Gemfile.lock中的gem的。详细的类太多了,先跳出吧。
看看加载的结果:
irb
1.9.3p194 :002 > puts $:
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/x86_64-linux
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/vendor_ruby/1.9.1
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/vendor_ruby/1.9.1/x86_64-linux
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/vendor_ruby
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/x86_64-linux
1.9.3p194 :003 > require "./config/boot.rb"
=> true
1.9.3p194 :004 > puts $:
/usr/share/ruby-rvm/gems/[email protected]/gems/uglifier-2.1.2/lib
/usr/share/ruby-rvm/gems/[email protected]/gems/thin-1.5.1/lib
... ...
/usr/share/ruby-rvm/gems/[email protected]/gems/activemodel-3.2.13/lib
/usr/share/ruby-rvm/gems/[email protected]/gems/builder-3.0.4/lib
/usr/share/ruby-rvm/gems/[email protected]/gems/activesupport-3.2.13/lib
/usr/share/ruby-rvm/gems/[email protected]/gems/multi_json-1.7.9/lib
/usr/share/ruby-rvm/gems/[email protected]/gems/i18n-0.6.1/lib
/usr/share/ruby-rvm/gems/[email protected]/gems/rake-10.1.0/lib
/usr/share/ruby-rvm/gems/ruby-1.9.3-p194@global/gems/bundler-1.1.5/lib
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/x86_64-linux
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/vendor_ruby/1.9.1
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/vendor_ruby/1.9.1/x86_64-linux
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/vendor_ruby
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1
/usr/share/ruby-rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/x86_64-linux
看结果,都加载进来了,而且版本都是跟Gemfile.lock中一致的。
加载的时候,是必须有版本的,虽然Gemfile有很多gem我们不指定版本,或者不指定精确版本。
至此,rails是怎么使用bundle的,以及bundle大概干了什么事情,就清楚了。
从这些源码也可以扩展,如果我们的项目(不是rails项目),想用bundle来维持版本的一致性,怎么使用和价值bundle,自然跟这里类似了。
Bundle官网就介绍了使用,使用上跟上面的几乎一致。
require 'rubygems' require 'bundler/setup'
+
+
+
=
+
+
+