こんにちは、@tk0miya です。RubyKaigi 2023、楽しかったですね。
今回は RubyKaigi 2023 で最も感銘を受けた gem である、katakata_irb を導入してみたので、レポートしてみたいと思います。
これまでも irb には入力補完機能がありましたが、サジェストされるメソッドが不完全であったり、メソッドチェーンの呼び出しで補完が動かないといった問題がありました。
katakata_irb gem は Ruby の型定義情報を使って irb の補完機能を強化するための gem です。
RubyKaigi 2023 の Power up your REPL life with types – RubyKaigi 2023 というセッションで紹介されました。
katakata_irb gem はその名の通り irb を強化するための gem ですが、irb は多くのところで使われているので、思わぬところにも効果があります。
たとえば、rails console
は内部的に irb を利用しているので、katakata_irb gem を導入すると rails console
の入力補完機能も強化されます。また、デバッグに binding.irb
をつかっている人も同様にデバッグコンソールの強化に繋がります。
普段 irb を使う機会はないや…と思っている人も試してみる価値はあります。
比較のために、これまでの irb の補完の様子を見てみましょう。
たとえば 123 という数値を入れてメソッドを呼び出そうとすると以下のようにサジェストが行われます。
このケースではうまく行っているように見えるのですが、他のオブジェクトではサジェストがされなかったり、誤ったりすることがあります。
また、今度はメソッドチェーンでどうなるか見てみましょう。
123.to_s に対してさらにメソッド呼び出しを試みます。String 型に対するメソッド呼び出しとなるのですが、irb はうまくサジェストしてくれません。
それでは、katakata_irb を入れるとどうなるのかを見てみましょう。
先程と同様に 123 に対するサジェストは以下のようになります。
サジェスト候補の右側を見ると、Integer と表示されていますが、これは katakata_irb がオブジェクトの型を認識してサジェスト候補を出しているという表示です。
また、メソッドチェーン呼び出しでは以下のように入力補完をしてくれます。
123.to_s が String 型を返すというのを認識しているので、オブジェクトの方は String 型と識別されていますし、サジェストされるメソッドも String のメソッドです。
もう少し複雑な例として、ブロックを試してみました。
ここも意図通りオブジェクトの型が識別されて、適切なサジェストが行われています。
katakata_irb gem の動作を理解したところで、あらためてインストール手順を確認しましょう。
.irbrc
にロードする設定を書くkatakata_irb gem のインストールはシンプルですね。いつもどおり Gemfile に記述するか、gem install してください。
group :development do
gem 'katakata_irb', require: false
end
次に、 .irbrc
ファイルに設定を加えます。.irbrc
は irb の設定ファイルです。
自分のホームディレクトリもしくはプロジェクトルートに配置するとよいでしょう。
以下の内容を .irbrc
に書きます。
require 'katakata_irb' rescue nil
特別な手順はありません。irb
コマンドや rails console
コマンド経由で irb を起動してください。
いろいろ入力してみて、いい感じにサジェストされるか実験してみてください。
さて、ここまでは katakata_irb が提供してくれるデフォルトの型定義情報に基づいてサジェストしていました。
実際の Ruby プロジェクトでは、3rd party gem を使ったり、自身でクラスを定義して使いますよね。
こうしたクラス群については、型情報を持たないため katakata_irb は入力補完を受けることができません。
より広範囲な入力補完を受けるために、さらに設定を追加します。
3rd party gem については、gem_rbs_collection というリポジトリにさまざまな gem の型定義情報が集約されています。
このリポジトリは Ruby コミュニティの有志により情報が収集されているものです。
型情報が収録されている gem の数はまだあまり多くはありませんが、ActiveRecord や ActiveSupport といったよく使われている gem については型定義情報が提供されているので、まずはこれらの型定義をインストールしましょう。
まずは設定ファイルを生成します。
bundle exec rbs collection init
上記のコマンドを実行すると rbs_collection.yml
というファイルが生成されます。
次に、以下のコマンドを実行して gem_rbs_collection リポジトリから型定義を取得します。
bundle exec rbs collection install
上記のコマンドを実行すると、rbs_collection.lock.yml
というファイルと .rbs_collection/
というディレクトリが生成されます。
rbs_collection.yml
と rbs_collection.lock.yml
にはリポジトリからダウンロードする型定義情報の設定と、実際にダウンロードした型定義情報の一覧が記載されています。
Gemfile/Gemfile.lock と同様の関係にあるファイルです。コミットして管理すると良いでしょう。
.rbs_collection/
ディレクトリには実際にダウンロードした型情報が保存されています。
こちらは、コミットする必要はないものですので、 .gitignore
に追加してコミット対象から外すとよさそうです。
実際にプロジェクトで利用する場合は
rbs_collection.yml
と rbs_collection.lock.yml
を生成するrbs collection install
を実行するという流れで、各メンバーの開発環境に型定義ファイルをダウンロードします。
型定義ファイルをダウンロードしたら、あとは irb を起動するだけで、入力補完に型定義が利用されます。
たとえば、ActiveSupport の型定義をダウンロードされると、以下のように入力補完が行われます。
あとは開発対象のアプリケーションの型定義情報を用意できると、より便利そうですよね。
Rails アプリケーションの場合には便利 gem が存在します。
rbs_rails
gem は DB スキーマやモデル定義(associationなど)などから型定義を自動抽出してくれます。
まずは Gemfile に rbs_rails
を追加し、 bundle install
を実行します。
group :development do
gem 'rbs_rails'
end
bundle install
次に rbs_rails
用の Rake タスクを生成します。生成用の Rake タスクが用意されています。
bundle exec rails g rbs_rails:install
最後に rbs_rails:all
タスクを実行します。
bundle exec rails rbs_rails:all
一連のコマンドを実行すると、Rails アプリケーションから抽出された型定義が sig/rbs_rails
ディレクトリ以下に出力されます。
これまでと同様に irb を起動します。
たとえば、以下は ActiveRecord モデル Staff
に対する入力補完が行われている様子です。
Staff
モデルが認識されており、AR 系のメソッドが提供されている様子が見えます。
また、こちらは association に基づいて関連モデルのサジェストをしている様子です。
この例では Staff
は Corporation
に belongs_to しているので、たどることができています。
DB スキーマの変更やモデルの定義が変更されるにつれ、抽出した型定義は古くなっていきます。
自動抽出した型定義ファイルは rbs_rails:all
で更新できるため、定期的に (書き換える都度に) 型定義ファイルを再生成することで、入力補完の精度を維持できます。
GitHub Actions などで自動化すると便利そうですが、それはまた別の記事で紹介したいと思います。
ここまでは gem_rbs_collection や rbs_rails gem で型定義情報をお手軽に得られる方法を説明しました。
入力補完の精度をより上げるには、自分で作ったクラスやメソッドの型情報を定義していく必要があります。
これらについては、我々も知見が不足しているので、調査の上あらためて紹介したいと思います。
この記事では katakata_irb を使った irb の入力補完機能の強化方法を紹介しました。
katakata_irb はかんたんに導入できて、とても効果のある gem です。RubyKaigi でトークを聞いて「帰ったらすぐに入れてみよう」と思える素晴らしい gem だと思います。
今回は katakata_irb gem を中心に紹介しましたが、今回セットアップした型定義情報は他のツールでも利用できます。
型定義情報をうまく利用すると開発効率を上げ、ミスやエラーをへらすことに繋がるので、導入する価値がありそうです。
今回紹介した範囲については、いくつかの設定で済むため、導入障壁もかなり低いと感じています。利便性も非常に高いので、普段の開発に徐々に型を入れていくというのを検討してみてはいかがでしょうか。