【发布时间】:2014-06-28 19:15:19
【问题描述】:
'bundler',流行的 ruby gem 操作工具,将 gem 安装到与普通 gem 命令相同的目录中。但是使用bundle exec 执行的应用程序只能访问使用捆绑程序安装的gem,而不是“系统范围”的gem。这在技术上是如何完成的? bundler 猴子补丁require,或一些路径操作,还是什么?
【问题讨论】:
'bundler',流行的 ruby gem 操作工具,将 gem 安装到与普通 gem 命令相同的目录中。但是使用bundle exec 执行的应用程序只能访问使用捆绑程序安装的gem,而不是“系统范围”的gem。这在技术上是如何完成的? bundler 猴子补丁require,或一些路径操作,还是什么?
【问题讨论】:
Bundler 确保 Ruby 可以找到 Gemfile 中的所有 gem(及其所有依赖项)。它通过配置加载路径来实现,因此您的 Gemfile 中的所有依赖项都是必需的。这是使用以下调用完成的:
Bundler.setup
ruby LOAD_PATH 是文件系统中 ruby 查找文件的位置列表,如果你需要的话。认为它类似于 Linux/Windows 操作系统中的 PATH 变量,但用于 ruby。
要查看此操作,请以 root 用户身份运行 load_path。我在我的 Mac 上这样做
$ sudo ruby -e 'p $LOAD_PATH'
["/Library/Ruby/Site/2.0.0", "/Library/Ruby/Site/2.0.0/x86_64-darwin13", "/Library/Ruby/Site/2.0.0/universal-darwin13", "/Library/Ruby/Site", "/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/vendor_ruby/2.0.0", "/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/vendor_ruby/2.0.0/x86_64-darwin13", "/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/vendor_ruby/2.0.0/universal-darwin13", "/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/vendor_ruby", "/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0", "/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/x86_64-darwin13", "/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/universal-darwin13"]
现在,在 Rails 应用程序中运行相同的命令:
$ ruby -e 'p $LOAD_PATH' #paths on new rails 4.1 app
["/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/uglifier-2.5.0/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/turbolinks-2.2.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/extensions/x86_64-darwin-12/2.1.0-static/sqlite3-1.3.9", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/sqlite3-1.3.9/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/sdoc-0.4.0/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/sass-rails-4.0.3/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/sass-3.2.19/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/rdoc-4.1.1/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/rails-4.0.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/sprockets-rails-2.0.1/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/sprockets-2.11.0/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/tilt-1.4.1/lib", "/Users/gaurish/.rvm/rubies/ruby-2.1.1/lib/ruby/gems/2.1.0/gems/json-1.8.1/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/jquery-rails-3.1.0/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/jbuilder-1.5.3/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/hike-1.2.3/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/coffee-rails-4.0.1/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/railties-4.0.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/thor-0.19.1/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/coffee-script-2.2.0/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/execjs-2.0.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/coffee-script-source-1.7.0/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/arel-4.0.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/activerecord-deprecated_finders-1.0.3/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/activemodel-4.0.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/actionmailer-4.0.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/mail-2.5.4/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/treetop-1.4.15/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/polyglot-0.3.4/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/mime-types-1.25.1/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/actionpack-4.0.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/rack-test-0.6.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/rack-1.5.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/erubis-2.7.0/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/builder-3.1.4/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/activesupport-4.0.2/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/tzinfo-0.3.39/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/thread_safe-0.3.3/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/multi_json-1.10.0/lib", "/Users/gaurish/.rvm/rubies/ruby-2.1.1/lib/ruby/gems/2.1.0/gems/minitest-4.7.5/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/i18n-0.6.9/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1/gems/rake-10.3.1/lib", "/Users/gaurish/.rvm/gems/ruby-2.1.1@global/gems/bundler-1.6.1/lib", "/Users/gaurish/.rvm/rubies/ruby-2.1.1/lib/ruby/site_ruby/2.1.0", "/Users/gaurish/.rvm/rubies/ruby-2.1.1/lib/ruby/site_ruby/2.1.0/x86_64-darwin12.0", "/Users/gaurish/.rvm/rubies/ruby-2.1.1/lib/ruby/site_ruby", "/Users/gaurish/.rvm/rubies/ruby-2.1.1/lib/ruby/vendor_ruby/2.1.0", "/Users/gaurish/.rvm/rubies/ruby-2.1.1/lib/ruby/vendor_ruby/2.1.0/x86_64-darwin12.0", "/Users/gaurish/.rvm/rubies/ruby-2.1.1/lib/ruby/vendor_ruby", "/Users/gaurish/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0", "/Users/gaurish/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/x86_64-darwin12.0"]
注意,加载路径已被修改为精确指向 Gemfile 中指定的 gem 版本
您可能会注意到,bundler 调整了这个加载路径,因此它指向 Gemfile 中给出的依赖项。所以每当你运行require 时,ruby 只会拾取LOAD PATH 中给出的版本,并记住这个加载路径是由bundler 在Bundler.setup 调用期间设置/修改的。因此它可以根据 Gemfile 准确地将 ruby 指向它希望的任何文件版本,正如您从上面的示例中看到的那样,当我们以 root 用户打印我们的 rails 应用程序的加载路径与 rails 应用程序外部的加载路径时
想知道这个回答你的问题吗?
【讨论】:
require 并且在当前加载路径中未找到目标,则会搜索您的其他 gem 以查找匹配项。如果找到匹配的 gems lib 目录,则将其添加到加载路径中。 Bundler 通过removing the patched require method that Rubygems adds 防止这种情况发生。
我通过以下链接在 Rubygems 上构建并发布了我的第一个 gem:
【讨论】: