what's the difference between bundle.setup and bundle.require

前端 未结 4 461
野趣味
野趣味 2020-12-31 13:24

From the gemfile man page, I learned there are two ways to import the gems you specified in the Gemfile. The bundle.setup will \"s

4条回答
  •  粉色の甜心
    2020-12-31 13:59

    I will answer this in the context of Rails. I was reviewing the Rails initialization process and came across both "bundler/setup" and Bundler.require. Remember the goal of Bundler: install the gems you need and ensures those are the only gems being required inside your Rails application. And this is how it works with Rails:

    In initialization, the Rails environment loads the contents of bin/rails first. It requires two important files:

    require_relative '../config/boot'
    require 'rails/commands'
    

    The config/boot is the most critical one here. It first stores the Gemfile in an environment variable and then runs bundler/setup.

    ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
    require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
    

    One thing I notice is apparently you can choose a different Gemfile to use by setting the environment variable BUNDLE_GEMFILE. But more importantly, because of 'bundler/setup', the $LOAD_PATH is changed. Typically RubyGems has a default $LOAD_PATH, where it will search for files when you use "require". Well, bundler/setup removes all paths to gems from the $LOAD_PATH (which reverses any load path work that RubyGems did). Then, it adds the load paths of just the gems in your Gemfile.lock back to the $LOAD_PATH. Now, the only gems you can require files from are the ones in your Gemfile.

    What's also interesting is even though RubyGems has a default $LOAD_PATH, which is searched when using "require", you still have to use "require". The gems are not already required. But when you use Bundler with Rails, you do not need to require any of the Gems in the Gemfile. How is this accomplished? This is handled by Bundler.require! Back in the bin/rails file, there is this line:

    APP_PATH = File.expand_path('../../config/application',  __FILE__)
    

    APP_PATH is just set up here. Not loaded. But when you run something like rails server, APP_PATH will be used and consequently config/application.rb file will be loaded and thus the following:

    require 'rails/all'
    Bundler.require(*Rails.groups)
    

    config/application.rb runs after Rails boots and in the above content, Bundler.require requires all the gems in all the groups you pass to it. ("groups" refers to the groups you specify in your Gemfile.) Rails.groups is going to be [:default, :development] when you’re running Rails in development mode, [:default, :production] in production mode, and so on. The :default group includes all gems not listed under any group. So, Bundler will look in your Gemfile for gems belonging to each of those groups, and call require on each of the gems it finds.

提交回复
热议问题