Rbenv、RubyGems、Bundlerがどのように連携するかを理解する
Rubyでの依存関係の管理には、通常、プロジェクトが依存するRubyとgemのバージョンを指定することが含まれます。 Rubyでの作業経験では、依存関係のデバッグは私の最大の課題の1つです。多くのものが「うまくいく」ので、失敗は一般的ではありません。ただし、問題が発生した場合、通常、デバッグと修正は不必要に困難になります。この記事では、Rubyの依存関係管理に関連する部分について説明します。これは、これらの奇妙な問題が発生したときにデバッグするのに役立ちます。
デフォルトでは、Ruby言語は、他の場所で定義されたコードをロードするための2つの主要なメソッドを提供します。load
&require
。
load 'json.rb'
require 'json.rb'
require_relative 'json.rb'
どちらのロードメソッドも、引数として絶対パスと相対パスの両方を受け入れます。ただし、2つの差別化要因があります。
-
load
への複数の呼び出しrequire
を複数回呼び出すと、ファイルが再実行されます。 ファイルを再実行しません。代わりに、false
を返します 。 -
load
の呼び出し 絶対パスと相対パスにのみ解決されます。require
への呼び出し$LOAD_PATH
をチェックします パスが絶対パスに解決されない場合。
3番目のバリアントはrequire_relative
です 、相対パスを使用して、Rubyプロセスの作業ディレクトリではなく、現在のファイルの場所に相対的なコードを要求します。
Rbenv
バージョンマネージャーは、インタープリター(この場合はRuby)のバージョンを管理して簡単に切り替え、プロジェクトのそれぞれのgemを見つける場所を指定するために使用されるツールです。バージョンマネージャーは主に言語に依存しないツールであり、Nvm、Node.jsの場合はn、Pythonの場合はpyenv、Rubyの場合はRbenv、rvm、chrubyなど、さまざまな言語にそれぞれの実装があります。それでは、rbenv
を見てみましょう。 スピンのために、私たちはしませんか?
Rubyバージョンのインストール
コマンドrbenv install
を使用します Rubyの任意のバージョンをインストールするには:
# Install ruby 2.6.1
$ rbenv install 2.6.1
Downloading openssl-1.1.1i.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242
Installing openssl-1.1.1i...
Installed openssl-1.1.1i to /home/directory/.rbenv/versions/2.6.1
Downloading ruby-2.6.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.1.tar.bz2
Installing ruby-2.6.1...
ruby-build: using readline from homebrew
Installed ruby-2.6.1 to /home/directory/.rbenv/versions/2.6.1
# Check Installation
$ rbenv versions # Shows all versions installed.
system
2.6.1
# Lookup versions available for installation
$ rbenv install -L
1.8.5-p52
1.8.5-p113
1.8.5-p114
...
2.7.0-rc1
2.7.0-rc2
2.7.0
...
truffleruby+graalvm-20.1.0
truffleruby+graalvm-20.2.0
truffleruby+graalvm-20.3.0
# The full list above amounts to about 500 versions, scrolling through the entire list is a lot.
# The command below is an easy shortcut to find your specific version with fzf.
$ rbenv install `rbenv install -L | fzf`
Rubyのバージョンを切り替える方法を特定する方法はいくつかあります。常に、rbenv
次のことを行います:
-
RBENV_VERSION
をチェックします 。 -
.ruby-version
を検索します スクリプトのディレクトリとその親に、ルートディレクトリに到達するまでファイルを保存します。 -
.ruby-version
を検索します$PWD
のファイル ルートディレクトリに到達するまで、その親ディレクトリ。 - グローバルファイル
~/.rbenv/version
を使用します 。
優先順位は上から下に移動します。 ~/.rbenv/version
は最終的なフォールバックであり、グローバルバージョンとして扱われます。以下を参照してください:
# Inside First Project Root
# Select ruby version for project
$ touch .ruby-version && echo "2.7.1" >> .ruby-version
# Verify selected version
$ ruby --version
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin20] # Result
$ rbenv version
2.7.1 (set by /path/to/current/directory/.ruby-version) # Result
# Change selected version
$ : >> .ruby-version && echo "2.6.1" >> .ruby-version
# Verify selection change
$ ruby --version
ruby 2.6.1p33 (2019-01-30 revision 66950) [x86_64-darwin20] # Result
$ rbenv version
2.6.1 (set by /path/to/current/directory/.ruby-version)
# Change selection with RBENV_VERSION while .ruby-version is present
$ export RBENV_VERSION=2.5.1
# Verify selection change
# .ruby-version is ignored.
$ ruby --version
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin20] # Result
$ rbenv version
2.5.1 (set by RBENV_VERSION environment variable) # Result
# Change to a version that is not installed & remove RBENV_VERSION
$ unset RBENV_VERSION & : >> .ruby-version && echo "2.4.1" >> .ruby-version
# Verify selection change
$ ruby --version
rbenv: version `2.4.1' is not installed (set by full/path/to/current/directory/.ruby-version) # Result
rbenv
をデバッグするには、これら2つの概念を正しく理解する必要があります。 効果的に。
シムは、PATH
に存在する軽量のbashスクリプトです。 コマンドをインターセプトし、実行のために適切なバージョンにルーティングします。大まかに言うと、すべてのコマンド(rspec
など )はrbenv exec rspec
に変換されます 。以下の詳細を参照してください。
まず、rbenv
すべてのコマンドのシムを作成します(rspec
、bundle
、など)インストールされているすべてのRubyバージョンにわたって、バージョンに関係なくCLIへの呼び出しをインターセプトします。これらのシムは~/.rbenv/shims
にあります。 。以下に示すように、すべてのシムには同じbashスクリプトが含まれています。
#!/usr/bin/env bash
set -e
[ -n "$RBENV_DEBUG" ] && set -x
program="${0##*/}"
if [ "$program" = "ruby" ]; then
for arg; do
case "$arg" in
-e* | -- ) break ;;
*/* )
if [ -f "$arg" ]; then
export RBENV_DIR="${arg%/*}"
break
fi
;;
esac
done
fi
export RBENV_ROOT="/home/directory/.rbenv"
exec "/usr/local/Cellar/rbenv/1.1.2/libexec/rbenv" exec "$program" "$@"
次に、上記のスクリプトは大まかに次のように変換されます。
- プログラム名が
ruby
の場合 引数付き-e
、-
rbenv exec ruby <args>
に変換します
-
- プログラム名が
ruby
の場合 スクリプトへのパスを使用して、-
RBENV_DIR
を設定します スクリプトのディレクトリに移動します。これにより、rbenv
が有効になります.ruby-version
を検索するには$PWD
の前のスクリプトのディレクトリ 。.ruby-version
の場合rbenv
の両方の場所で指定されます スクリプトのディレクトリを選択します。
-
- プログラム名がRubyでない場合は、
-
rbenv exec <program-name> <args>
に変換します 。
-
最後に、rbenv exec <command-name> <args>
RBENV_VERSION
をチェックして、コマンドを渡す正しいバージョンを識別します 環境変数。 RBENV_VERSION
を忘れないでください 上で定義されたアルゴリズムによって設定されます。
PATH
のシム 付加する必要があります。これにより、Ruby実行可能ファイルの最初の連絡先となり、適切にインターセプトできるようになります。あなたのPATH
を理解するために私が見つけた最良の方法 シムが適切にインターセプトされているかどうかを設定して確認するには、次のようにします。
$ which -a bundle
/path/to/home/.rbenv/shims/bundle
/usr/bin/bundle
which -a bundle
:これはあなたのPATH
を素朴に調べます 見つかった順序で、bundle
の場所を印刷します 見つけることができます。 ~/.rbenv/shims
で何かが何かの前に印刷されている場合 、それはあなたのシムが適切に設定されていないことを意味します。 rbenv which bundle
コマンドはrbenv
のコンテキストで機能するため、これは明らかになりません。 PATH
を検索していません 。
再ハッシュは、シムを作成するプロセスです。 rspec
などの実行可能ファイルを提供するRubygemを新しくインストールする場合 、rbenv rehash
を実行する必要があります その後のrspec
の呼び出しで、シムを作成します。 rbenv
によって傍受される可能性があります そして適切なRubyバージョンに渡されます。
RubyGems
次はRubyGemsです。 Rubyの公式サイトから入手できます。 RubyGemsは、ライブラリの作成、共有、インストールを容易にするために設計されたRubyパッケージングシステムです。ある意味では、これはapt-getなどに似た配布パッケージシステムですが、Rubyソフトウェアを対象としています。 RubyGemsは、gemを共有するための事実上の方法です。これらは通常、~/.rbenv/versions/{version-number}/lib/ruby/gems/{minor-version}/
にインストールされます。 、またはそのバリアント。使用するバージョンマネージャーによって異なります。 Rubyのデフォルトの必須メソッドKernel.require
Gemsインストールディレクトリからgemをロードするメカニズムは提供していません。 RubyGemsモンキーパッチKernel.require
に
- まず、
$LOAD_PATH
で宝石を検索します 。 - 見つからない場合は、
GEMS INSTALLATION DIRECTORY
でgemを検索してください 。- 見つかったら、パスを
$LOAD_PATH
に追加します 。
- 見つかったら、パスを
バージョン1.9以降、RubyにはデフォルトでRubyGemsが付属しているため、これは「ネイティブに」機能します。以前のRubyバージョンでは、RubyGemsを手動でインストールする必要がありました。これはネイティブで機能しますが、デバッグ時にこの違いを知ることも重要です。
gemは、特定の問題を解決するために使用される一連の関連コードです。次のようにgemをインストールし、gem環境に関する情報を取得します。
$ gem install gemname
$ gem env
RubyGems Environment:
- RUBYGEMS VERSION: 3.1.2
- RUBY VERSION: 2.7.1 (2020-03-31 patchlevel 83) [x86_64-darwin20]
- INSTALLATION DIRECTORY: /path/to/home/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0
- USER INSTALLATION DIRECTORY: /path/to/home/.gem/ruby/2.7.0
- RUBY EXECUTABLE: /path/to/home/.rbenv/versions/2.7.1/bin/ruby
- GIT EXECUTABLE: /usr/bin/git
- EXECUTABLE DIRECTORY: /path/to/home/.rbenv/versions/2.7.1/bin
- SPEC CACHE DIRECTORY: /path/to/home/.gem/specs
- SYSTEM CONFIGURATION DIRECTORY: /path/to/home/.rbenv/versions/2.7.1/etc
- RUBYGEMS PLATFORMS:
- ruby
- x86_64-darwin-20
- GEM PATHS:
- /path/to/home/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0
- /path/to/home/.gem/ruby/2.7.0
- GEM CONFIGURATION:
...
- REMOTE SOURCES:
- https://rubygems.org/
- SHELL PATH:
- /path/to/home/.rbenv/versions/2.7.1/bin
RubyGemsはこの問題をどのように解決しますか? Kernel
にモンキーパッチを適用します 独自のrequire
を備えたrequireシステム 方法。これをインプレースで使用すると、require honeybadger
が呼び出され、gemsフォルダーでhoneybadger.rb
を検索します。 見つかったときに宝石をアクティブにします。
たとえば、require 'honeybadger'
次のようなものを生成します:
-
spec = Gem::Specification.find_by_path('honeybadger')
-
spec.activate
gemをアクティブ化するということは、それを$LOAD_PATH
に配置することを意味します。 。 RubyGemsは、gem自体をダウンロードする前に、gemのすべての依存関係をダウンロードするのにも役立ちます。
また、Rubygemsには、gem open <gem-name>
を使用して関連するgemのディレクトリを開くことができる優れた機能が付属しています。;たとえば、
これにより、アプリが参照している宝石の特定のバージョンを簡単に見つけて追跡することができます。
このレイヤーでは、Bundlerを使用すると、プロジェクトのすべての依存関係を簡単に指定し、オプションでそれぞれのバージョンを指定できます。次に、gemを解決し、gemとその依存関係をインストールします。プレバンドラーで実際のアプリケーションを構築するには、次のような無数の課題がありました。
- 私たちのアプリケーションには多数の依存関係があり、これらの依存関係には他にもさまざまな依存関係とそれぞれのバージョンがあります。 1つのgemの間違ったバージョンをインストールすると、アプリが簡単に壊れてしまいます。この問題を修正するには、多くの涙が必要でした。
- また、2つの依存関係が同じ第3レベルの依存関係を参照できます。互換性を見つけることが問題でした。もしあれば、それは問題でした。
- 同じマシン上に複数のアプリケーションがあり、さまざまな依存関係がある場合、アプリケーションはマシンにインストールされているすべてのgemにアクセスできます。これは、最小特権の原則に反し、マシンにインストールされているすべてのgemにアプリケーションを公開します。悪意があるかどうか。
Bundlerは、3つの問題すべてを解決し、次のようにしてアプリの依存関係を管理するための適切な方法を提供します。
Bundlerは依存関係を解決し、ロックファイルを生成します:
# Gemfile
gem 'httparty'
bundle
を実行した場合 またはbundle install
、ロックファイルを生成します:
GEM
specs:
httparty (0.18.1)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2020.1104)
multi_xml (0.6.0)
PLATFORMS
ruby
DEPENDENCIES
httparty
BUNDLED WITH
2.1.4
上記から、バンドラーはhttparty
のバージョンを生成します インストールするものと、Gemfile.lock.
内の独自の依存関係 このファイルはアプリの依存関係の青写真であり、バージョン管理にチェックインする必要があります。これにより、プロジェクトの依存関係が環境(開発、ステージング、または本番)全体で一貫していることが保証されます。
Bundlerは依存関係間の互換性を解決します
httparty
の依存関係を解決します 依存関係に適したバージョンを見つけて指定します。 Bundlerは、gem間の依存関係も解決しようとします。たとえば、
# Gemfile
gem 'httparty' # That relies on gem 'mime-types', '>= 3.0.1, < 4.0.1'
gem 'rest-client' # That relies on gem 'mime-types', '>= 2.0.1, < 3.0'
上記の例は任意であり、次のようなエラーが発生します。
Bundler could not find compatible versions for gem "mime-types":
In Gemfile:
httparty was resolved to 0.18.1, which depends on
mime-types ('>= 3.0.1, < 4.0.1')
rest-client was resolved to 2.0.4, which depends on
mime-types ('>= 2.0.1, < 3.0')
これは、2つのgemに互換性がなく、自動的に解決できない依存関係があるためです。
Bundlerは、インストールされているがGemfile
で指定されていないgemへのアクセスを制限します
次のようなサンプルgemfileでは、
# Gemfile
gem 'httparty'
# irb
require 'rest-client'
# raises
LoadError (cannot load such file -- rest-client)
Gemfile
で指定された依存関係のみが保証されます 私たちのプロジェクトで要求される可能性があります。
rspec
を実行する場合 プロジェクトディレクトリで、Gemfile
で指定されたもの以外の異なるバージョンを実行する可能性があります 。これは、Gemfile
で指定されたバージョンではなく、最新バージョンが実行対象として選択されるためです。 。 bundle exec rspec
rspec
を保証します そのプロジェクトのコンテキストで実行されます(つまり、Gemfileで指定されたgem)。
多くの場合、./bin/rails
などのコマンドを実行する記事を読みます。;このコマンドは、bundle exec rails
に似ています。 。ビンスタブは、bundle exec
の使用を容易にするRuby実行可能ファイルのラッパーです。 。
binstub実行を生成するには、bundle binstubs gem-name
を使用します 。これにより、./bin
にbinstubが作成されます フォルダですが、--path
で設定できます 設定されている場合はディレクトリ。
詳細については、次のリファレンスをご覧ください:
- 宝石はどのように機能しますか?
- Rbenv
- RubyGems
- バンドラー
-
Ruby 2.6のMJITとは何ですか?どのように機能しますか?
Rubyのパフォーマンスはバージョンごとに大幅に向上しており、Ruby開発チームはRubyをさらに高速化するためにあらゆる努力をしています! これらの取り組みの1つは、3×3プロジェクトです。 目標は? Ruby3.0はRuby2.0の3倍高速になります 。 このプロジェクトの一部は、この記事のトピックである新しいMJITコンパイラです。 MJITの説明 MJITは「メソッドベースのジャストインタイムコンパイラ」の略です。 それはどういう意味ですか? RubyはコードをYARV命令にコンパイルします 、これらの命令はRuby仮想マシンによって実行されます。 JITはこれに別のレ
-
Cortana と Alexa を一緒に使用する方法
Microsoft は、1 月の Build 開発者会議で発表した後、ついに Windows 10 PC に Alexa を、Echo スピーカーに Cortana をもたらします。現在、プレビューは米国でのみ利用可能ですが、このパートナーシップには長い道のりがあるようです. 私たちは多面的な世界に住んでおり、デバイスにアシスタントを搭載することが理にかなっており、有益であることが証明されています.個々のオペレーティング システムではなく、アプリなどの 3 つのアシスタントにアクセスできることほど優れたものはありません。 現在、統合は基本的なものですが、間もなく Cortana と Ale