如果你只想瞭解我們建議的工作流程,而不在乎其原理,請隨時跳到以下摘要。
首先,你在應用程式根目錄的檔案中宣告這些相依性,檔案名稱為 Gemfile
。它看起來像這樣
source 'https://rubygems.org'
gem 'rails', '4.1.0.rc2'
gem 'rack-cache'
gem 'nokogiri', '~> 1.6.1'
這個 Gemfile
說明了一些事情。首先,它表示 bundler 應該在 https://rubygems.org
中尋找在 Gemfile
中宣告的寶石。如果你的某些寶石需要從私人寶石伺服器擷取,可以為這些寶石覆寫這個預設來源。
接下來,你宣告幾個相依性
rails
的版本 4.1.0.rc2
上rack-cache
的任何版本上nokogiri
的版本上,大於或等於 1.6.1
但小於 1.7.0
在宣告你的第一組相依性後,你告訴 bundler 去取得它們
$ bundle install # 'bundle' is a shortcut for 'bundle install'
Bundler 會連線到 rubygems.org
(以及你宣告的任何其他來源),並找出符合你指定需求的所有必要寶石清單。由於 Gemfile
中的所有寶石都有自己的相依性(其中一些有自己的相依性),在上述 Gemfile
上執行 bundle install
會安裝相當多的寶石。
$ bundle install
Fetching gem metadata from https://rubygems.org/.........
Fetching additional metadata from https://rubygems.org/..
Resolving dependencies...
Using rake 10.3.1
Using json 1.8.1
Installing minitest 5.3.3
Installing i18n 0.6.9
Installing thread_safe 0.3.3
Installing builder 3.2.2
Installing rack 1.5.2
Installing erubis 2.7.0
Installing mime-types 1.25.1
Using bundler 1.6.2
Installing polyglot 0.3.4
Installing arel 5.0.1.20140414130214
Installing hike 1.2.3
Installing mini_portile 0.5.3
Installing multi_json 1.9.3
Installing thor 0.19.1
Installing tilt 1.4.1
Installing tzinfo 1.1.0
Installing rack-test 0.6.2
Installing rack-cache 1.2
Installing treetop 1.4.15
Installing sprockets 2.12.1
Installing activesupport 4.1.0.rc2
Installing mail 2.5.4
Installing actionview 4.1.0.rc2
Installing activemodel 4.1.0.rc2
Installing actionpack 4.1.0.rc2
Installing activerecord 4.1.0.rc2
Installing actionmailer 4.1.0.rc2
Installing sprockets-rails 2.0.1
Installing railties 4.1.0.rc2
Installing rails 4.1.0.rc2
Installing nokogiri 1.6.1
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
如果任何必要的寶石已經安裝,Bundler 會使用它們。在安裝任何必要的寶石到你的系統後,bundler 會將所有安裝的寶石和版本快照寫入 Gemfile.lock
。
Bundler 確保 Ruby 能夠找到 Gemfile
中的所有寶石(以及它們的所有相依性)。如果你的應用程式是 Rails 應用程式,你的預設應用程式已經有呼叫 bundler 所需的程式碼。
對於其他類型的應用程式(例如 Sinatra 應用程式),你需要在嘗試需要任何寶石之前設定 bundler。在你的應用程式載入的第一個檔案頂端(對於 Sinatra,呼叫 require 'sinatra'
的檔案),放入以下程式碼
require 'bundler/setup'
這將自動偵測您的 Gemfile
並讓 Gemfile
中的所有寶石都能在 Ruby 中使用(技術上來說,它會將寶石「放入載入路徑」中)。您可以將它視為為 require 'rubygems'
新增一些額外功能。
現在您的程式碼已可在 Ruby 中使用,您可以需要您需要的寶石。例如,您可以 require 'sinatra'
。如果您有很多依賴項,您可能想說「需要我 Gemfile
中的所有寶石」。若要執行此操作,請將下列程式碼置於 require 'bundler/setup'
之後
Bundler.require(:default)
對於我們的範例 Gemfile,此行與以下內容完全相同
require 'rails'
require 'rack-cache'
require 'nokogiri'
對於這麼小的 Gemfile
,我們建議您略過 Bundler.require
並手動需要寶石。對於大得多的 Gemfile
,使用 Bundler.require
可讓您略過重複一大堆需求。
開發應用程式一段時間後,請將應用程式與 Gemfile
和 Gemfile.lock
檢查點一起檢查。現在,您的儲存庫記錄了您上次確定應用程式運作時所使用的所有寶石的確切版本。請記住,儘管您的 Gemfile
只列出三個寶石(版本嚴謹度不同),但您的應用程式依賴於數十個寶石,一旦您考慮到您依賴的寶石的所有隱含需求。
這很重要:Gemfile.lock
使您的應用程式成為您自己的程式碼和它上次確定一切正常時執行的第三方程式碼的單一套件。在您的 Gemfile
中指定您依賴的第三方程式碼的確切版本無法提供相同的保證,因為寶石通常會為其依賴項宣告一系列版本。
下次您在同一台機器上執行 bundle install
時,bundler 會看到它已經擁有您需要的所有依賴項,並略過安裝程序。
請勿檢查 .bundle
目錄或其內的任何檔案。這些檔案特定於每台特定機器,並用於在 bundle install
命令執行之間保留安裝選項。
如果您已執行 bundle pack
,您的套件所需的寶石(但不是 git 寶石)將下載到 vendor/cache
。如果所有您需要的寶石都存在於該資料夾中並已檢查到您的原始碼控制中,bundler 可以不連線到網際網路(或 RubyGems 伺服器)執行。這是一個選用步驟,不建議執行,因為您的原始碼控制儲存庫會增加大小。
當你的共同開發人員(或你在另一台機器上)檢出你的程式碼時,它將會包含你在最後開發的機器上應用程式所使用的所有第三方程式碼的確切版本(在 Gemfile.lock
中)。當他們執行 bundle install
時,bundler 將會找到 Gemfile.lock
並略過相依性解析步驟。它將安裝你在原始機器上使用的所有相同寶石。
換句話說,你不必猜測你應該安裝哪些版本的相依性。在我們一直在使用的範例中,即使 rack-cache
宣告對 rack >= 0.4
的相依性,我們確定它適用於 rack 1.5.2
。即使 Rack 團隊發布 rack 1.5.3
,bundler 仍會始終安裝 1.5.2
,也就是我們知道適用的寶石的確切版本。這減輕了應用程式開發人員大量的維護負擔,因為所有機器始終執行完全相同的第三方程式碼。
當然,在某個時間點,你可能想要更新應用程式依賴的特定相依性版本。例如,你可能想要將 rails
更新為 4.1.0
最終版本。重要的是,僅僅因為你更新一個相依性,並不表示你想要重新解析所有相依性並使用所有內容的最新版本。在我們的範例中,你只有三個相依性,但即使在這種情況下,更新所有內容都可能造成複雜性。
為了說明,rails 4.1.0.rc2
寶石依賴於 actionpack 4.1.0.rc2
寶石,而 actionpack 4.1.0.rc2
寶石依賴於 rack ~> 1.5.2
(表示 >= 1.5.2
和 < 1.6.0
)。rack-cache
寶石依賴於 rack >= 0.4
。我們假設 rails 4.1.0
最終寶石也依賴於 rack ~> 1.5.2
,而且自 rails 4.1.0
發布以來,Rack 團隊已發布 rack 1.5.3
。
如果我們天真地更新所有寶石以更新 Rails,我們將取得 rack 1.5.3
,它滿足 rails 4.1.0
和 rack-cache
的需求。然而,我們並未特別要求更新 rack-cache
,它可能與 rack 1.5.3
不相容(出於任何原因)。雖然從 rack 1.5.2
更新到 rack 1.5.3
可能不會造成任何問題,但可能會發生涉及更大跳躍的類似情況。(請參閱下方 [1] 以取得更深入的討論)
為了避免這個問題,當你更新寶石時,bundler 如果你另一個寶石仍依賴於該寶石,bundler 將不會更新該寶石的相依性。在此範例中,由於 rack-cache
仍依賴於 rack
,因此 bundler 將不會更新 rack
寶石。這可確保更新 rails
不會無意間中斷 rack-cache
。由於 rails 4.1.0
的相依性 actionpack 4.1.0
仍與 rack 1.5.2
相容,因此 bundler 讓它保持不變,而 rack-cache
即使面對與 rack 1.5.3
不相容的情況,仍繼續運作。
由於你最初宣告對 rails 4.1.0.rc2
的相依性,如果你想要更新為 rails 4.1.0
,只需將你的 Gemfile
更新為 gem 'rails', '4.1.0'
並執行
$ bundle install
如上所述,bundle install
命令總是執行保守更新,拒絕更新您在 Gemfile
中未明確變更的 gem(或其依賴項)。這表示如果您未在 Gemfile
中修改 rack-cache
,bundler 會將其及其依賴項(rack
)視為單一不可修改的單元。如果 rails 4.1.0
與 rack-cache
不相容,bundler 會報告您的快照依賴項(Gemfile.lock
)與更新後的 Gemfile
之間的衝突。
如果您更新 Gemfile
,而您的系統已具備所有需要的依賴項,bundler 會在您啟動應用程式時透明更新 Gemfile.lock
。例如,如果您將 mysql
新增到 Gemfile
,且已在您的系統中安裝,您可以在不執行 bundle install
的情況下啟動應用程式,而 bundler 會將「最後已知的良好」設定檔持續儲存到 Gemfile.lock
快照。
這在新增或更新具有最小依賴項的 gem(資料庫驅動程式、wirble
、ruby-debug
)時會很方便。如果您更新具有大量依賴項(rails
)或許多 gem 依賴的 gem(rack
),它可能會失敗。如果透明更新失敗,您的應用程式將無法啟動,而 bundler 會列印錯誤訊息,指示您執行 bundle install
。
有時,您想要更新依賴項而不修改 Gemfile。例如,您可能想要更新到 rack-cache
的最新版本。由於您未在 Gemfile
中宣告 rack-cache
的特定版本,您可能想要定期取得 rack-cache
的最新版本。為此,您需要使用 bundle update
命令
$ bundle update rack-cache
此命令會將 rack-cache
及其依賴項更新到 Gemfile
允許的最新版本(在本例中為可用的最新版本)。它不會修改任何其他依賴項。
不過,它會在必要時更新其他 gem 的依賴項。例如,如果 rack-cache
的最新版本指定依賴 rack >= 1.5.2
,bundler 會將 rack
更新到 1.5.2
,即使您未要求 bundler 更新 rack
。如果 bundler 需要更新其他 gem 所依賴的 gem,它會在更新完成後讓您知道。
如果您想要將 Gemfile 中的每個 gem 更新到最新可能的版本,請執行
$ bundle update
這會從頭開始解決依賴項,忽略 Gemfile.lock
。如果你這樣做,請將 git reset --hard
和你的測試套件放在後口袋。從頭開始解決所有依賴項可能會產生令人驚訝的結果,特別是如果你依賴的許多第三方套件在你上次執行完整更新後已發布新版本。
當你第一次建立一個 Rails 應用程式時,它已經附帶一個 Gemfile
。對於其他類型的應用程式(例如 Sinatra),請執行
$ bundle init
bundle init
指令會建立一個你可以編輯的簡單 Gemfile
。
接下來,新增任何你的應用程式依賴的寶石。如果你關心特定寶石的版本,請務必包含適當的版本限制
source 'https://rubygems.org'
gem 'sinatra', '~> 1.3.6'
gem 'rack-cache'
gem 'rack-bug'
如果你尚未在你的系統中安裝寶石,請執行
$ bundle install
若要更新寶石的版本需求,請先修改 Gemfile
source 'https://rubygems.org'
gem 'sinatra', '~> 1.4.5'
gem 'rack-cache'
gem 'rack-bug'
然後執行
$ bundle install
如果 bundle install
報告你的 Gemfile
和 Gemfile.lock
之間有衝突,請執行
$ bundle update sinatra
這將只更新 Sinatra 寶石,以及它的任何依賴項。
若要將 Gemfile
中的所有寶石更新到最新可能的版本,請執行
$ bundle update
Gemfile.lock
發生變更時,請務必將它檢查到版本控制中。它會保留你用於成功執行應用程式的所有第三方程式碼的確切版本記錄。在將你的程式碼部署到暫存或生產伺服器時,請先執行你的測試(或啟動你的本地開發伺服器),確認你已將 Gemfile.lock
檢查到版本控制中。在遠端伺服器上,執行
$ bundle install --deployment
[1] 例如,如果 rails 4.1.0
依賴於 rack 2.0
,該寶石仍會滿足 rack-cache
的需求,後者宣告 >= 0.4
為依賴項。當然,你可以爭辯說 rack-cache
依賴於開放式版本是愚蠢的,但這些情況在現實世界中(廣泛地)存在,而且專案在決定依賴哪個版本時,常常發現自己進退兩難。過度限制依賴項(rack =1.5.1
)會讓你在其他相容專案中難以使用你的專案。限制得太少(rack >= 1.0
),而 Rack 的新版本可能會損壞你的程式碼。使用像 rack ~> 1.5.2
這樣的依賴項,並以符合 SemVer 的方式建立版本控制程式碼,大多可以解決這個問題,但它假設普遍的相容性。由於 RubyGems 有超過 100,000 個套件,因此這個假設在實務上根本不成立。