Bundlerを使用したバージョンの管理

rakeアップデートは最近、バージョン0.8.7からバージョン0.9.0にリリースされました。これにより、コミュニティで多くのノイズが発生し、再びバージョン管理の問題が明らかになりました。 Bundler 1.0のリリース中に既に述べた主なポイントを繰り返し、状況を明確にしたいと思います。 最初に、単純な作業ルールについて説明し、次に詳細をもう少し詳しく説明します。

シンプルなバージョン管理


  1. bundle実行したら、Gemfile.lockをリポジトリに追加します。
  2. Gemfileを変更した後は、必ず最初にbundle installください。これにより、Gemfile.lockが「保守的に」更新されます。 Gemfileで変更したgemのみが変更されます。 それ以外はすべてそのまま残ります。
  3. 「保守的な」更新が不可能な場合、Bundlerは、 bundle update [somegem]を行うように提案します。 このコマンドは、指定されたgemとそれに必要なすべての依存関係のみを更新します。 残りの宝石はそのまま残ります。
  4. すべての依存関係を最初から再解決する必要がある場合は、 bundle updateを行う必要があります。
  5. 実行可能ファイルを実行するときは、 常に bundle exec [command]してこれを実行します。 ドキュメントからの引用: 場合によっては、このファイルがシステムにインストールされ、バンドルと競合する可能性のある依存関係をロードしないgemの一部である場合、 bundle execなしでファイルを起動することができます。 ただし、この方法は非常に信頼性が低く、多くの問題の原因です。 すべてが機能しているように見えても、明日または別のサーバーで機能するという事実ではありません。 次のセクション「実行可能ファイル」はこれについてです。
  6. 古いGemfile.lockをgit checkout Gemfile.lockまたは他のSCMの同様のgit checkout Gemfile.lockいつでも返すことができることに注意してください。


実行可能ファイル


gemをインストールすると、Rubygemsはgemに付属するすべての実行可能ファイルのラッパーを作成します。 ラッパーが起動すると、Rubygemsが起動し、標準のアクティベーションメカニズムを使用してgem自体が接続されます。 Rubygemsは、Gemfile.lockで別のバージョンが指定されている場合でも、システムインストールされている gemの最新バージョンを起動します。 さらに、Gemfile.lockで他のバージョンが指定されている場合でも、すべての gem 依存関係最新の(互換性のある)バージョンがアクティブ化されます。

これは、単純なコマンドとして実行可能ファイルを実行すると、Bundlerとそのすべての依存関係を単にバイパスすることを意味します。 開発者はすべてのgemの適切なバージョンを持っている可能性が高いため、これは問題ではない場合があります。 Gemfile.lockのほとんどはバージョン0.8.7にロックされていたため、Rakeは「正しい」バージョンを備えたそのようなgemの優れた例でした。

その結果、実行可能ファイルの直接起動はBundlerと互換性があり、それを使用して依存関係を解決するという誤解がありました。 Gemfile.lockからコンパイルされたgemsetは、本質的に環境のすべての実行可能ファイルが必要な依存関係バージョンで機能することを意味するため、問題が発生した場合、RVMのgemsetを使用することをお勧めします。

残念ながら、この松葉杖のため、人々はドキュメントからのアドバイスを無視し続けて、常にbundle exec使用します。

コンソールでrake fooと入力することでBundlerサンドボックスコードを実行すると信じる理由はありません。実際には、それはどのような方法にも関与せず、どこからも開始されないからです。 Bundlerは、ダウンロードの最初にアクティブにし、Gemfile.lockに規定されているgemの必要なバージョンをスリップすることでブートローダーを置き換えることができます。 実行可能ファイルを直接起動することで、Bundlerが依存関係接続プロセスに介入する前にルビーコードを実行します。 その結果、あなたが頼りにしているコードはまったく接続されていません。 これが発生すると、すべてが非常に予測不能になります。

bundle install --binstubs


bundle execでこれらすべてのダンスを何らかの形で容易にするために、Bundler 1.0は特別なフラグ--binstubs提供します。これは、アプリケーションで使用されるすべてのgemの実行可能ファイルを入れるbinディレクトリを作成します。 したがって、たとえばbin/cucumber実行することは、 bundle exec cucumberコマンドと同等です。

binディレクトリは、実行可能ファイル用の「ポータブル」ラッパーを作成するため、リポジトリに安全に追加できます。

railsチーム


上記の規則の唯一の例外はrailsコマンドです。 バージョン3.0以降、このコマンドは最初に現在のディレクトリからscript/railsを実行しようとします。 そして、 script/rails 、最初にバンドラーを開始します
 #This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. APP_PATH = File.expand_path('../../config/application', __FILE__) require File.expand_path('../../config/boot', __FILE__) require 'rails/commands' 


boot.rbファイルの内容は、かなり重要です。
 require 'rubygems' # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) 


要するに、 rails実行可能ファイルは、Bundlerサンドボックススタートアップロジックが最初からトリガーされ、 Kernel#execを使用して、gemがまだロードされている場合に現在のプロセスをオーバーロードすることを保証するために、可能な限りすべてを実行します。
この振る舞いはほとんどのアプリケーションgemにとって不可能であり、このハックを使用する価値があるかどうか、またbundle execを混乱させずにrailsを実行できるという事実bundle execさらに複雑かどうかという疑問が残ります。

Source: https://habr.com/ru/post/J120259/


All Articles