前回の動画では密結合によって生じる問題を解説し、その問題を解決するためには Plugins を利用することで依存関係を解消を図れると分かりました。
今回の動画では開発に入るためにローカル環境に入れたソースで Gem を動かしてみるところまでを紹介しています。本件の修正だけに限らず、さまざまな開発において汎用的に使えるお話になると思いますのでぜひ参考にして頂ければと思います。
前編↓
後編↓
Ruby の Gem はどこからロードされるか?
gem install
した場合のインストール先は gem の環境変数を確認することでわかります。
❯ gem environment | grep "USER INSTALLATION DIRECTORY"
- USER INSTALLATION DIRECTORY: /Users/teradamasaru/.gem/ruby/3.1.0
実際にこのディレクトリ配下の /gems
の中を見てみると、自分がこれまでインストールした Gem が入っていることが確認できますね。
❯ ls -l /Users/teradamasaru/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems
total 0
drwxr-xr-x 7 teradamasaru staff 224 8 30 12:28 reline-0.3.8
drwxr-xr-x 13 teradamasaru staff 416 8 30 12:28 irb-1.7.4
// ...
ここにインストールした Gem は既に ruby がライブラリをロードする際の検索パスに含まれています。検索パスの一覧は $LOAD_PATH
に入っています。
❯ irb
irb(main):001:0> $LOAD_PATH
=>
["/Users/teradamasaru/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/reline-0.3.8/lib",
"/Users/teradamasaru/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.7.4/lib",
# ...
ライブラリをロードしようとすると、この検索パスの上から走査します。例えば require reline
したとすると、$LOAD_PATH
の中にある
で (略).../reline-0.3.8/lib
reline
が見つかります。従ってここにあるライブラリがロードされてくるというわけです。
ローカルで Gem の開発をする
以上を踏まえた上で実際にローカルで Gem を開発する手順に入っていきましょう。github からソースをクローンしてきます。クローンした結果以下のようなディレクトリ構成になりました。
❯ tree -L 2
.
├── rdoc
│ ├── CONTRIBUTING.rdoc
│ ├── CVE-2013-0256.rdoc
│ ├── ExampleMarkdown.md
│ ├── ExampleRDoc.rdoc
│ ├── Gemfile
│ ├── History.rdoc
│ ├── LEGAL.rdoc
│ ├── LICENSE.rdoc
│ ├── README.rdoc
│ ├── RI.rdoc
│ ├── Rakefile
│ ├── TODO.rdoc
│ ├── doc
│ ├── exe
│ ├── lib
│ ├── man
│ ├── rakelib
│ ├── rdoc.gemspec
│ └── test
└── rubygems
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── MAINTAINERS.txt
├── MIT.txt
├── Manifest.txt
├── POLICIES.md
├── README.md
├── Rakefile
├── UPGRADING.md
├── bin
├── bundler
├── exe
├── hide_lib_for_update
├── lib
├── rubygems-update.gemspec
├── setup.rb
├── test
└── tool
ただこの状態で ruby から rdoc
や rubygems
をロードしたとしても、ローカルにクローンしたこれらのソースが使用されることはありません。なぜなら ruby の $LOAD_PATH
にはこのディレクトリへの検索パスは含まれていないからです。
検索パスに追加するためには、コマンドラインオプション -I
を利用することができます。また、-I
で追加された検索パスは最上位にくるため、既に rdoc
や rubygems
を gem
コマンドでインストールしていたとしてもこっちが優先されます。
今回では rdoc
のライブラリは /rdoc/lib/rdoc
、rubygems
は /rubygems/lib/rubygems
にあります。これらが含まれるディレクトリを検索パスに加えて ruby
を実行してみましょう。試しにバージョンを表示するコマンドを実行してみます。
❯ ruby -I rubygems/lib rubygems/exe/gem --version
3.5.0.dev
❯ ruby -I rdoc/lib rdoc/exe/rdoc --version
<internal:/Users/teradamasaru/.rbenv/versions/3.1.0/lib/ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:148:in `require': cannot load such file -- /Users/teradamasaru/dev/red_data_tools/remove_dependency/rdoc/lib/rdoc/markdown (LoadError)
// ...
rubygems
の方はバージョンが表示されましたが、rdoc
の方はエラーが出てしまいました。
エラー内容を確認してみるとどうやら markdown
が見つからないようです。試しに rdoc/lib/rdoc
の中を確認してみると markdown.kpeg
というファイルは見つかるものの markdown.rb
が存在していません。
❯ ls rdoc/lib/rdoc | grep markdown
markdown
markdown.kpeg
このように Gem の中にはクローンしただけの状態では即使える状態になっていないものもあります。幸い rdoc
には rake
タスクとして gem を使用できる状態までビルドする generate
が用意されています。これを実行してみましょう。
❯ rake generate
Generating lib/rdoc/markdown.rb...
/Users/teradamasaru/.rbenv/versions/3.1.0/bin/ruby /Users/teradamasaru/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/kpeg-1.3.3/bin/kpeg -fsv -o lib/rdoc/markdown.rb lib/rdoc/markdown.kpeg
Wrote RDoc::Markdown to lib/rdoc/markdown.rb
Generating lib/rdoc/markdown/literals.rb...
/Users/teradamasaru/.rbenv/versions/3.1.0/bin/ruby /Users/teradamasaru/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/kpeg-1.3.3/bin/kpeg -fsv -o lib/rdoc/markdown/literals.rb lib/rdoc/markdown/literals.kpeg
Wrote RDoc::Markdown::Literals to lib/rdoc/markdown/literals.rb
❯ ruby -I rdoc/lib rdoc/exe/rdoc --version
6.5.0
rdoc
もローカルにダウンロードしたファイルを呼び出すことができました。本当にローカルのソースからロードしたかを確かめるため、それぞれバージョンを定義しているファイルを確認してみましょう。
module RDoc
##
# RDoc version you are using
VERSION = '6.5.0'
end
module Gem
VERSION = "3.5.0.dev"
end
それぞれ先ほどコンソールに出力したバージョンと一致していることがわかります。
以上でローカルにクローンしてきた Gem のソースを ruby から呼び出すことができました。次回の動画では実際にソースを修正して動かすところに入っていく予定です!
コメント