=
依存関係のみを指定できないのですか?Q: 特定のバージョンにgemを固定することの価値は理解していますが、Gemfile
内のすべての依存関係に=
バージョンを指定して、Gemfile.lock
について忘れることはできないのでしょうか?
A: 多くのgemには独自の依存関係があり、それらは=
依存関係を指定する可能性は低いでしょう。さらに、gemが自身の依存関係をすべて厳密に固定することは、おそらく賢明ではありません。Gemfile.lock
を使用すると、アプリケーションがGemfile
で必要な依存関係のバージョンを指定できるだけでなく、アプリケーションが最後に正しく動作したときに使用したサードパーティコードの正確なバージョンをすべて記憶できます。
Gemfile
でより緩い依存関係(例:nokogiri ~> 1.4.2
)を指定することで、bundle update nokogiri
を実行して、bundlerにnokogiri
とその依存関係を、~> 1.4.2
のバージョン要件を満たす最新バージョンにのみ更新させることができます。これにより、「nokogiriの現在のバージョンを使用したい」(Gemfile
内のgem 'nokogiri'
)と指定することもでき、正確なバージョン番号を調べる必要がなくなり、アプリケーションが常にまったく同じバージョンのサードパーティコードで実行されるという利点も得られます。
Q: このようにgemを管理するためにbundlerが必要な理由がわかりません。必要なgemを取得してサブモジュールに入れ、各サブモジュールをロードパスに入れるだけではいけないのでしょうか?
A: 残念ながら、その解決策では、依存関係の依存関係を含め、アプリケーション内のすべての依存関係を手動で解決する必要があります。そして、一度それを正常に行ったとしても、特定のgemを更新したい場合は、その作業をやり直す必要があります。たとえば、rails
gemを更新したい場合、Railsの依存関係(rack
、erubis
、i18n
、tzinfo
など)に依存しているすべてのgemを見つけ、新しいバージョンのRailsの要件を満たす新しいバージョンを見つける必要があります。
率直に言って、これはコンピュータが得意とする種類の問題であり、開発者であるあなたは時間を費やすべきではありません。
さらに重要なことに、手動の依存関係解決プロセスで間違いを犯した場合、異なる依存関係間の競合に関するフィードバックが得られず、微妙なランタイムエラーが発生します。たとえば、誤って間違ったバージョンのrack
をサブモジュールに入れた場合、Railsまたは別の依存関係が存在しないメソッドに依存しようとしたときに、実行時にエラーが発生する可能性があります。
結論: 一見シンプルに見えるかもしれませんが、実際には非常に複雑です。
--without
グループからgemをダウンロードしているのですか?Q: bundle install --without production
を実行しましたが、bundlerは依然として:production
グループのgemをダウンロードしています。なぜですか?
A: BundlerのGemfile.lock
には、渡すオプションに関係なく、Gemfile
内のすべての依存関係の正確なバージョンが含まれている必要があります。そうでない場合、アプリケーションを本番環境にデプロイすると、すべての依存関係が変更される可能性があり、Bundlerの利点が失われます。開発およびテストで使用したのと同じgemを本番環境でアプリケーションが使用しているかどうかを確信できなくなります。さらに、本番環境で依存関係を追加すると、デプロイ不可能なアプリケーションになる可能性があります。
たとえば、rack =1.1
に依存する本番環境専用のgem(rack-debugging
と呼びましょう)があると想像してください。bundle install --without production
を実行したときにproductionグループを評価しなかった場合、アプリケーションをデプロイしたときに、rack-debugging
がrails
(rack ~> 1.2.1
に依存するactionpack
に依存)と競合するというエラーが表示されるでしょう。
別の例:Gemfile
にgem 'rack'
があるシンプルなRackアプリケーションを想像してください。繰り返しますが、rack-debugging
を:production
グループに入れると想像してください。bundle install --without production
でインストールしたときに:production
グループを評価しなかった場合、アプリは開発環境でrack 1.2.1
を使用し、デプロイ時にrack-debugging
がテストしたRackのバージョンと競合することを知ることになります。
対照的に、環境で実際に使用したいグループに関係なく、bundle install
を呼び出すときにすべてのグループのgemを評価することで、rack-debugger
の要件を発見し、Gemfile
内のgem 'rack'
の要件とも互換性のあるrack 1.1
をインストールします。
要するに、特定の環境で使用するつもりの依存関係に関係なく、常にGemfile内のすべての依存関係を評価することで、異なる環境で異なるグループセットに切り替える際の不快な驚きを回避できます。そして、gemをダウンロードするだけで(インストールはしません)、本番環境(または開発環境)でのみ使用するgemの困難なインストールプロセスについて心配する必要はありません。
Q: mysql
などのC拡張機能のgemがあり、コンパイルとインストールには特別なフラグが必要です。これらのフラグをこれらのgemのインストールプロセスに渡すにはどうすればよいですか?
A: まず第一に、この問題はmysql
gemのドロップイン代替であるmysql2
gemには存在しません。一般的に、最新のC拡張機能は必要なヘッダーを適切に検出します。
C拡張機能にフラグを渡す必要がある場合は、bundle config
コマンドを使用できます。
$ bundle config build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config
Bundlerはこの構成を~/.bundle/config
に保存し、bundlerは同じユーザーが実行するすべてのbundle install
でこの構成を使用します。その結果、gemに必要なビルドフラグを指定すると、必要な回数だけそのgemを正常にインストールできます。
Q: インターネット接続はありませんが、以前にgemをインストールしました。bundlerにリモートのgemサーバーに接続せずにローカルのgemキャッシュを使用させるにはどうすればよいですか?
A: bundle install
で--local
フラグを使用します。--local
フラグは、bundlerにリモートのgemサーバーに接続するのではなく、ローカルのgemキャッシュを使用するように指示します。
$ bundle install --local
Q: RubyGems.orgからバンドルすると、非常に遅いです。速くするためにできることはありますか?
A: まず、gem install bundler
を実行してBundlerの最新バージョンに更新してください。gemのインストールを高速化する多くの改善を長年にわたって追加してきました。非常に遅延が大きい接続の場合は、--full-index
フラグを使用すると改善される可能性があります。これにより、多くの小さなHTTPリクエストを行うのではなく、gem情報をすべて一度にダウンロードします。
$ bundle install --full-index
Q: gemにGemfile
を入れるとどうなりますか?
A: 誰かがあなたのgemをインストールすると、あなたがrubygems.orgにアップロードする.gem
ファイルに含めたとしても、Gemfile
とGemfile.lock
ファイルは完全に無視されます。gem内のGemfile
は、開発者(あなたのような人)があなたのgemで開発作業を行うために必要な依存関係を簡単にインストールできるようにするためのものです。Gemfile
は、開発専用またはテスト専用のgemを追跡およびインストールする簡単な方法も提供します。gemでのBundlerページおよびBundlerを使用してgemを作成する方法ガイドから、gem内のGemfileについて読んでください。
Q: gemを作成するときにGemfile.lock
をコミットする必要がありますか?
A: はい、コミットする必要があります。gemのリポジトリにGemfile.lock
が存在することで、リポジトリの新しいチェックアウトが毎回まったく同じ依存関係のセットを使用することが保証されます。これにより、リポジトリが新規および既存のコントリビューターに対してよりフレンドリーになると考えています。理想的には、誰でもリポジトリをクローンし、bundle install
を実行して、テストに合格する必要があります。Gemfile.lock
をチェックインしないと、新しいコントリビューターが異なるバージョンの依存関係を取得し、修正方法がわからないテストの失敗に遭遇する可能性があります。
Q: しかし、gemはGemfile.lockをチェックインすべきではないと読んだことがあります!
A: Gemfile.lockをチェックインしない主な利点は、依存関係のいずれかが破壊的な方法で変更された場合、新しいチェックアウト(CIを含む)でテストがすぐに失敗することです。すべての新しいチェックアウト(および可能性のある新しいコントリビューター)に壊れたビルドに遭遇させる代わりに、Bundlerチームは、依存関係が新しいバージョンをリリースするたびに、Dependabotのようなツールを使用して自動的にPRを作成し、テストスイートを実行することを推奨しています。依存関係監視ボットを使用したくない場合は、bundle install
を実行する前にGemfile.lockを削除する追加の毎日のCIビルドを作成することをお勧めします。そうすることで、あなたやCIステータスを監視している他の人は、依存関係の変更による失敗について最初に知ることができます。