Rails是如何使用Bundler

Bundler作为Ruby应用的依赖管理工具,它的核心功能是安装,隔离你项目中的Gem,并且通过依赖图解决不同Gem中的依赖关系。但初次之外Bundler还做了其他重要的事。在Gemfile中指定的gem的代码是如何被添加进Rails的应用的呢?
通过查看 bin/rails

#!/usr/bin/env ruby
begin
  load File.expand_path("../spring", __FILE__)
rescue LoadError
end
APP_PATH = File.expand_path('../../config/application',  __FILE__)
require_relative '../config/boot'
require 'rails/commands'

你会看到,它通过 加载 ../config/boot来加载 Rails,那让我们再看看 config/boot文件。

ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' # Set up gems listed in the Gemfile.

Bundler在这个文件中被使用,(同时在这里你可以通过设置不同的环境变量来使用不同的Gemfile文件)。
bundler/setup做了这几件事

  • 它从$LOAD_PATH中移除了所有gem的路径
  • 然后,它将所有Gemfile.lock中的gem的路径添加回$LOAD_PATH

这样你就只能require,那些Gemfile中指定的gem了。

那么,所有你需要的Gem,都已经添加到你的加载路径当中了,但是当你只使用 RubyGems的话,你仍然需要require你需要的文件,当你使用Rails和bundler时为什么不需要require gem包呢。

来快速的看一下 config/application.rb这个文件,当rails启动时:

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

又是Bundler!,Bundler.require require 所有你在Gemfile中的分组中的Gem。

Rails.groups会返回哪些分组呢?

# Returns all rails groups for loading based on:
 #
 # * The Rails environment;
 # * The environment variable RAILS_GROUPS;
 # * The optional envs given as argument and the hash with group dependencies;
 #
 #   groups assets: [:development, :test]
 #
 #   # Returns
 #   # => [:default, :development, :assets] for Rails.env == "development"
 #   # => [:default, :production]           for Rails.env == "production"
 def groups(*groups)
   hash = groups.extract_options!
   env = Rails.env
   groups.unshift(:default, env)
   groups.concat ENV["RAILS_GROUPS"].to_s.split(",")
   groups.concat hash.map { |k, v| k if v.map(&:to_s).include?(env) }
   groups.compact!
   groups.uniq!
   groups
 end

从上面可以看出,当你的Rails应用运行在开发模式下Rails.groups就会是 [:default, :development],同理生成模式下是[:default, :production]

所以,Bundler会在Gemfile中找到这些指定的分支,然后使用require加载每一个Gem,如果Gemfile中有faker,它就会require "faker",这就是为什么你不是需要手动加载Gem,它们就可以在Rails中使用的原因。

你可能感兴趣的:(Rails是如何使用Bundler)