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

前端 未结 4 459
野趣味
野趣味 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.

    0 讨论(0)
  • 2020-12-31 14:08

    You must use Bundle.setup and you can use Bundle.require.

    The main point of bundler is to make sure that exactly the Gems defined in the Gemfile are made visible to the application, i.e. all the gems mentioned there in exactly the mentioned versions, but not one more. To do that, the load path is adapted. This is done by Bundle.setup.

    To actually use the gems, they have to be required and thus loaded into the application. This can either be done by hand using a number of require statements or automatically for all the gems listed in the Gemfile (or only some groups) using Bundle.require. This however is only possible after adapting the loadpath as mentioned above.

    0 讨论(0)
  • 2020-12-31 14:10

    Bundle.setup is not necessory for recently bundler version. in fact, when you run Bundler.require, it always try to setup correct $LOAD_PATH for you.

    the only need is:

    require 'bundler' Bundler.require

    0 讨论(0)
  • 2020-12-31 14:21

    Bundler.setup modifies the LOAD_PATH, so you can do things like require 'some_gem' and they will work. It allows you to require gems 'by hand'. Before Bundler, using Rubygems, you would achieve much of the same effect doing require 'rubygems'.

    Bundler.require(:default) on the other hand actually requires all the gems in the Gemfile (assuming you're not using groups; otherwise it requires those in the specified groups if you provide arguments). It is a shorthand for a bunch of require 'some_gem' statements.

    See http://gembundler.com/rationale.html. Note that they say you have to do require 'bundler/setup' before doing Bundler.require, but in practice this usually is not necessary. I almost never use Bundler.setup (or require 'bundler/setup), because I require all gems via Bundler.require).

    0 讨论(0)
提交回复
热议问题