前回の動画ではローカル環境にて Gem の開発を行う準備を整えました。
今回の動画からは実際に rubygems の plugin の実装をおこなっていきます!
rubygems の plugin を追加する手順
rubygems の plugin を実装する手順については以下の公式ドキュメントにまとまっています。
要点だけをまとめていくと、plugin として読み込ませるためには rubygems_plugin
という名前のファイルを作成する必要があること、require_path
でロードされるルートディレクトリにそれを配置する必要があるという点です。
このルールに基づいたプラグインを持つ Gem がインストールされた環境においては、rubygems が実行されるたびにこのプラグインをロードして実行してくれます。
実際に rdoc
に rubygems_plugin.rb
を作成して試してみましょう。ファイルは以下の構成のように作成します。
❯ tree -L 1 ./rdoc/lib
./rdoc/lib
├── rdoc
├── rdoc.rb
└── rubygems_plugin.rb
確認のために rubygems_plugin.rb
の中身は以下のようにしてみましょう。
# frozen_string_literal: true
pp "called!!!!"
適当な rubygems のコマンドを実行してみると called!!!!
が表示されました。この通りプラグインがロードされて実行されていることがわかります。
❯ ruby -I rdoc/lib -I rubygems/lib rubygems/exe/gem list
"called!!!!"
*** LOCAL GEMS ***
abbrev (default: 0.1.0)
base64 (default: 0.1.1)
// ...
rubygems の中の rdoc に依存しているコードを移植する
いよいよ今回の本題である、rubygems の中にある rdoc に依存しているコードの移植をしていきます。
問題のコードは rubygems/lib/rubygems/rdoc.rb
にある以下のコードです。
# frozen_string_literal: true
require_relative "../rubygems"
begin
require "rdoc/rubygems_hook"
module Gem
RDoc = ::RDoc::RubygemsHook
end
Gem.done_installing(&Gem::RDoc.method(:generation_hook))
rescue LoadError
end
このコードは rdoc/rubygems_hook
という rdoc にあるコードをロードして実行する必要がありました。この部分が密結合になってしまっているわけです。ですのでこの処理を rdoc 側に移してしまいましょう。
# frozen_string_literal: true
require "rdoc/rubygems_hook"
Gem.done_installing(&::RDoc::RubygemsHook.method(:generation_hook))
ただ移行するだけではなく少しリファクタリングも加えています。
begin-rescue
節は rdoc がインストールされていない環境では require
に失敗するためエラーハンドリングをおこなっていたものです。今回は rdoc 側に実装するのでこのようなケースを想定する必要はありません。
module Gem
を拡張する形で実装している部分も移行後はもはや不要です。こちらも修正を加えました。
実際に適当な Gem をインストールしてみましょう。
❯ ruby -I rdoc/lib -I rubygems/lib rubygems/exe/gem install settingslogic
Fetching settingslogic-2.0.9.gem
Successfully installed settingslogic-2.0.9
Parsing documentation for settingslogic-2.0.9
Installing ri documentation for settingslogic-2.0.9
Done installing documentation for settingslogic after 0 seconds
1 gem installed
Parsing documentation for settingslogic-2.0.9
という行が表示されていると思いますが、これは実際に rdoc/rubygems_hook
が呼び出されて実行されたことを表しています。
これで問題のあるコードを移植することに成功しました!
しかし、これをそのままリリースするわけにはいきません。
なぜなら rubygems からは rdoc のドキュメントを生成する処理は削除してしまったので、rubygems のバージョンを上げて rdoc のバージョンが古いまま、という環境の人はドキュメントの生成がされない不具合が発生してしまうからです。
次回の動画ではこのような問題に対して、後方互換性を担保するためにはどうするか?というテーマで進めていく予定ですので、楽しみにして頂ければと思います!
コメント