ローカル環境で Gem の開発を行うためには?【Red Data Tools開発者に聞け!】

Red Data Tools

前回の動画では密結合によって生じる問題を解説し、その問題を解決するためには Plugins を利用することで依存関係を解消を図れると分かりました。

今回の動画では開発に入るためにローカル環境に入れたソースで Gem を動かしてみるところまでを紹介しています。本件の修正だけに限らず、さまざまな開発において汎用的に使えるお話になると思いますのでぜひ参考にして頂ければと思います。

前編↓

Red Data Tools開発者に聞け!第22回 「RubyGemsとRDocの密結合を解消する」Part3

後編↓

Red Data Tools開発者に聞け!第23回 「RubyGemsとRDocの密結合を解消する」Part4

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/libreline が見つかります。従ってここにあるライブラリがロードされてくるというわけです。

ローカルで 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 から rdocrubygems をロードしたとしても、ローカルにクローンしたこれらのソースが使用されることはありません。なぜなら ruby の $LOAD_PATH にはこのディレクトリへの検索パスは含まれていないからです。

検索パスに追加するためには、コマンドラインオプション -I を利用することができます。また、-I で追加された検索パスは最上位にくるため、既に rdocrubygemsgem コマンドでインストールしていたとしてもこっちが優先されます。

今回では rdoc のライブラリは /rdoc/lib/rdocrubygems/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 から呼び出すことができました。次回の動画では実際にソースを修正して動かすところに入っていく予定です!

コメント

タイトルとURLをコピーしました