推奨されるワークフローとその根拠に関心がない場合は、下のまとめにスキップしてください。
まず、アプリケーションのルートにあるGemfile
というファイルにこれらの依存関係を宣言します。それは以下のようになります。
source 'https://rubygems.org'
gem 'rails', '4.1.0.rc2'
gem 'rack-cache'
gem 'nokogiri', '~> 1.6.1'
このGemfile
はいくつかのことを示しています。まず、Bundlerはデフォルトでhttps://rubygems.org
で宣言されたgemを探す必要があることを示しています。一部のgemをプライベートなgemサーバーから取得する必要がある場合、これらのgemについてはデフォルトのソースを上書きできます。
次に、いくつかの依存関係を宣言します
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
(および宣言したその他のソース)に接続し、指定した要件を満たす必要なgemのリストをすべて見つけます。Gemfile
内のすべてのgemには独自の依存関係があるため(そしてそれらの一部には独自の依存関係がある)、上記のGemfile
でbundle install
を実行すると、非常に多くのgemがインストールされます。
$ 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.
必要なgemが既にインストールされている場合、Bundlerはそれらを使用します。必要なgemをシステムにインストールした後、BundlerはインストールしたすべてのgemとそのバージョンのスナップショットをGemfile.lock
に書き込みます。
Bundlerは、RubyがGemfile
内のすべてのgem(およびそのすべての依存関係)を見つけられるようにします。アプリケーションがRailsアプリケーションの場合、デフォルトのアプリケーションには、Bundlerを呼び出すために必要なコードが既に含まれています。
別の種類のアプリケーション(Sinatraアプリケーションなど)の場合、gemをrequireする前にBundlerを設定する必要があります。アプリケーションがロードする最初のファイル(Sinatraの場合は、require 'sinatra'
を呼び出すファイル)の先頭に、次のコードを記述します。
require 'bundler/setup'
これにより、Gemfile
が自動的に検出され、Gemfile
内のすべてのgemがRubyで使用できるようになります(技術的には、gemを「ロードパスに追加」します)。これは、require 'rubygems'
にいくつかの追加機能を追加することと考えることができます。
コードがRubyで使用できるようになったので、必要なgemをrequireできます。たとえば、require 'sinatra'
とできます。多くの依存関係がある場合は、「Gemfile
内のすべてのgemをrequireする」ということができます。これを行うには、require 'bundler/setup'
の直後に次のコードを記述します。
Bundler.require(:default)
この例のGemfileでは、この行は以下と完全に同等です。
require 'rails'
require 'rack-cache'
require 'nokogiri'
このような小さなGemfile
の場合、Bundler.require
をスキップして、gemを手動でrequireすることをお勧めします。はるかに大きなGemfile
の場合、Bundler.require
を使用すると、大量のrequireの繰り返しをスキップできます。
アプリケーションをしばらく開発したら、アプリケーションをGemfile
およびGemfile.lock
スナップショットとともにチェックインします。これで、リポジトリには、アプリケーションが最後に確実に動作したことがわかっているときに使用したすべてのgemの正確なバージョンの記録があります。Gemfile
には3つのgemのみがリストされていますが(バージョン厳密度の程度は異なります)、依存関係の暗黙的な要件をすべて考慮に入れると、アプリケーションは数十のgemに依存していることに注意してください。
これは重要です:Gemfile.lock
は、アプリケーションを、独自のコードと、最後に確実にすべてが動作したときに実行されたサードパーティコードの両方の単一のパッケージにします。Gemfile
で依存するサードパーティコードの正確なバージョンを指定しても、gemは通常依存関係のバージョンの範囲を宣言するため、同じ保証は提供されません。
同じマシンで次にbundle install
を実行すると、Bundlerは必要な依存関係がすべて既に存在することを確認し、インストールプロセスをスキップします。
.bundle
ディレクトリまたはその中のファイルはチェックインしないでください。これらのファイルは特定の各マシンに固有のものであり、bundle install
コマンドの実行間でインストールオプションを永続化するために使用されます。
bundle pack
を実行した場合、バンドルに必要なgem(git gemを除く)はvendor/cache
にダウンロードされます。必要なすべてのgemがそのフォルダーに存在し、ソース管理にチェックインされている場合、Bundlerはインターネット(またはRubyGemsサーバー)に接続せずに実行できます。これはオプションの手順であり、ソース管理リポジトリのサイズが増加するため、推奨されません。
共同開発者(または別のマシンのあなた)がコードをチェックアウトすると、最後に開発したマシンでアプリケーションが使用したすべてのサードパーティコードの正確なバージョン(Gemfile.lock
内)が付属します。彼らがbundle install
を実行すると、BundlerはGemfile.lock
を見つけて、依存関係解決手順をスキップします。代わりに、元のマシンで使用したのと同じgemがすべてインストールされます。
言い換えれば、インストールする必要がある依存関係のバージョンを推測する必要はありません。これまで使用してきた例では、rack-cache
はrack >= 0.4
への依存関係を宣言していますが、rack 1.5.2
で動作することを確実に知っています。Rackチームがrack 1.5.3
をリリースした場合でも、Bundlerは常に1.5.2
をインストールします。これは、動作することがわかっているgemの正確なバージョンです。これにより、すべてのマシンが常にまったく同じサードパーティコードを実行するため、アプリケーション開発者からの大きなメンテナンス負担が軽減されます。
もちろん、ある時点で、アプリケーションが依存している特定の依存関係のバージョンを更新したい場合があります。たとえば、rails
を4.1.0
の最終バージョンに更新したい場合があります。重要なことは、1つの依存関係を更新しているからといって、すべての依存関係を再解決し、すべての一番新しいバージョンを使用する必要はないということです。この例では、依存関係は3つしかありませんが、この場合でも、すべてを更新すると複雑になる可能性があります。
例を挙げると、rails 4.1.0.rc2
gemはactionpack 4.1.0.rc2
gemに依存し、これはrack ~> 1.5.2
(つまり、>= 1.5.2
および< 1.6.0
)に依存します。rack-cache
gemはrack >= 0.4
に依存します。rails 4.1.0
の最終gemもrack ~> 1.5.2
に依存しており、rails 4.1.0
のリリース以降、Rackチームがrack 1.5.3
をリリースしたと仮定します。
Railsを更新するためにすべてのgemを単純に更新すると、rails 4.1.0
とrack-cache
の両方の要件を満たすrack 1.5.3
が得られます。ただし、rack-cache
を更新するように特に要求したわけではありません。これはrack 1.5.3
と互換性がない可能性があります(理由は何であれ)。rack 1.5.2
からrack 1.5.3
への更新はおそらく何も壊しませんが、同様のシナリオで、さらに大きなジャンプが発生する可能性があります。(詳細については、下の[1]を参照してください)
この問題を回避するために、gemを更新するとき、Bundlerは、別のgemがそれに依存している場合、そのgemの依存関係を更新しません。この例では、rack-cache
は引き続きrack
に依存しているため、Bundlerはrack
gemを更新しません。これにより、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
を透過的に更新します。たとえば、Gemfile
にmysql
を追加し、システムに既にインストールしている場合、bundle install
を実行せずにアプリケーションを起動できます。Bundlerは「最後に既知の良好な」構成をGemfile.lock
スナップショットに保持します。
これは、最小限の依存関係(データベースドライバー、wirble
、ruby-debug
)を持つgemを追加または更新するときに役立ちます。依存関係が大きいgem(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
に更新します。これは、rack
を更新するようにBundlerに依頼していなくてもです。Bundlerが別のgemに依存しているgemを更新する必要がある場合、更新が完了した後に通知します。
Gemfile内のすべてのgemを可能な限り最新バージョンに更新する場合は、以下を実行します。
$ bundle update
これは、Gemfile.lock
を無視して、依存関係を最初から解決します。これを行う場合は、git reset --hard
とテストスイートをすぐに使えるように準備しておいてください。すべての依存関係を最初から解決すると、特に依存しているサードパーティパッケージの多くが最後に完全な更新を行ってから新しいバージョンをリリースしている場合、驚くべき結果になる可能性があります。
Railsアプリケーションを初めて作成すると、すでにGemfile
が付属しています。別の種類のアプリケーション(Sinatraなど)の場合は、以下を実行します。
$ bundle init
bundle init
コマンドは、編集可能なシンプルなGemfile
を作成します。
次に、アプリケーションが依存するgemを追加します。特定のgemのどのバージョンが必要かを気にする場合は、適切なバージョン制限を含めるようにしてください。
source 'https://rubygems.org'
gem 'sinatra', '~> 1.3.6'
gem 'rack-cache'
gem 'rack-bug'
まだシステムにgemがインストールされていない場合は、以下を実行します。
$ bundle install
gemのバージョン要件を更新するには、まず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 gemとその依存関係のみが更新されます。
Gemfile
内のすべてのgemを可能な限り最新のバージョンに更新するには、以下を実行します。
$ bundle update
Gemfile.lock
が変更された場合は、常にバージョン管理にチェックインしてください。これは、アプリケーションを正常に実行するために使用したすべてのサードパーティコードの正確なバージョンの履歴を保持します。コードをステージングまたは本番サーバーにデプロイするときは、まずテストを実行(またはローカル開発サーバーを起動)し、Gemfile.lock
をバージョン管理にチェックインしていることを確認してください。リモートサーバーで、以下を実行します。
$ bundle install --deployment
[1] たとえば、rails 4.1.0
がrack 2.0
に依存していた場合、そのgemはrack-cache
の要件(>= 0.4
を依存関係として宣言)を満たします。もちろん、rack-cache
がオープンエンドのバージョンに依存するのは愚かだと主張できますが、これらの状況は(広範囲に)実際に存在し、プロジェクトはどのバージョンに依存するかを決定する際に板挟みになることがよくあります。依存関係をあまりにも制約すると(rack =1.5.1
)、他の互換性のあるプロジェクトでプロジェクトを使用するのが難しくなります。制約が少なすぎると(rack >= 1.0
)、Rackの新しいリリースがコードを壊す可能性があります。rack ~> 1.5.2
のような依存関係を使用し、SemVerに準拠した方法でコードをバージョン管理することで、ほとんどの場合この問題は解決しますが、普遍的な準拠を前提としています。RubyGemsには10万を超えるパッケージがあるため、この前提は実際には成り立ちません。