【问题标题】:How bundler isolates gems in Ruby?bundler 如何在 Ruby 中隔离 gem?
【发布时间】:2014-06-28 19:15:19
【问题描述】:

'bundler',流行的 ruby​​ gem 操作工具,将 gem 安装到与普通 gem 命令相同的目录中。但是使用bundle exec 执行的应用程序只能访问使用捆绑程序安装的gem,而不是“系统范围”的gem。这在技术上是如何完成的? bundler 猴子补丁require,或一些路径操作,还是什么?

【问题讨论】:

    标签: ruby bundler


    【解决方案1】:

    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 应用程序外部的加载路径时

    想知道这个回答你的问题吗?

    【讨论】:

    • 这只是部分答案。如果 Rubygems 已加载(在当前 Ruby 版本中默认情况下),那么如果您调用 require 并且在当前加载路径中未找到目标,则会搜索您的其他 gem 以查找匹配项。如果找到匹配的 gems lib 目录,则将其添加到加载路径中。 Bundler 通过removing the patched require method that Rubygems adds 防止这种情况发生。
    【解决方案2】:

    我通过以下链接在 Rubygems 上构建并发布了我的第一个 gem:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      相关资源
      最近更新 更多