2024年 11月 14日
Kaigi on Rails 2024、面白かったですね。
僕は現地で多くのトークを聞き、色んな人と会話することができて、いろいろ刺激になりました。
トークの中では最後の基調講演がとても印象に残っています。
色んな人の言葉、書籍などを紐解きながら、導きの星に向かっていくというのはとてもエモく、なにかの劇場版っぽさを感じました。
パターン・ランゲージでおなじみのアレグザンダー先生まで登場して、すべての道は Rails に通じるのか!? と僕は涙腺崩壊寸前でした。
さて、面白かったトークの話はすでにいろんな方が記事を書かれていると思うので、ここでは別の話をしましょう。最近の僕は型にお熱なので、Kaigi on Rails でも多くの人と型の話をしたり、型のハックをしたりしていました。
その中でも、Kaigi on Rails の会期中に conference-app の型をアップデートした話を今回は紹介します。
前回の Kaigi on Rails のあとに conference-app に型を付けた のですが、今回なかのひとから型のメンテナンスが追いついていないという話を聞いて、テコ入れをお手伝いしました。
テコ入れをしたのは以下の部分です。
まず最初に、rbs_rails が path_helpers の型を生成できなくなってしまったという問題に対処しました。
path_helpers というのは home_path や new_users_url といった、routes に基づいて生成されるパス/URL 生成ヘルパーメソッドのことです。rbs_rails は routes 定義に基づいて自動的に型を生成してくれるのですが、conference-app ではなぜか path_helpers の型がいっさい生成されていない問題が発生していました。
しばらく調べてみた結果、この問題は Rails 8.0 と rbs_rails の組み合わせで発生する問題でした。
Rails 8.0 では起動の高速化のために routes の評価を遅延するようになったため、rbs_rails は routes がうまく読み込めずに、空の型定義を生成してしまっていました。
原因がわかれば対処は難しくありません。rbs_rails を実行する前に routes をロードさせます。 Rails.application.reload_routes_unless_loaded
メソッドを呼ぶと routes をロードできるようなので、次のような Rake タスクを作り、routes をロードさせてから rbs_rails:all
タスクを呼ぶようにします。
task load_routes: :environment do
# Since Rails 8.0, route drawing has been deferred to the first request.
# This forcedly do route drawing to generate path_helpers via rbs_rails.
Rails.application.reload_routes_unless_loaded
end
なお、このパッチは rbs_rails へ提出済み です。最近 rbs_rails はメンテが滞っているようですが、そのうちマージされるでしょう。
この記事を書いているさなかに Rails 8.0 がリリースされています ので、もし rbs_rails のアップデート前に Rails 8.0 を試す場合はこの workaround をお試しください。
alba gem をはじめとするいくつかの gem で型が不足していました。
会期中は型エラーを解消するのをゴールとしていたので、adhoc に steep:ignore
で回避したり、ローカルに型を追加するなどして回避しました。
その後、作成した型定義は gem_rbs_collection に反映済みです (alba gem を除く)。gem の型定義は集合知として型を集めていくしかないので、時間はかかりますが地道にやるしかないですね。
ここまで準備を整えると、ようやく型エラーとのご対面です。
…と言いたいところでしたが、実際のところ、型エラーらしい型エラーはほとんど存在せず、いくつか調整をする程度でした。
最後に、RBS ファイルに書いていた型を RBS::Inline を使ってコードのとなりに書けるようにしました。
僕個人の興味が大きかったこともありますが、型が維持できない問題のひとつに コードと型定義ファイルが離れている とことが影響しているという考えのもと、RBS::Inline を入れると体験が変わるのではないかと導入してみました。導入を提案してみたところ、二つ返事でオッケーしていただけたので、さくさく修正していきました。
Kaigi on Rails の二日目、片耳でトークを聞きつつ RBS ファイルから型コメントに置き換える対応をこつこつやってました。最後はバッテリー切れでコンプリートできなかったものの、翌日には書き換えの PR 作成まで完了していました。
おおよそ Kaigi on Rails の会期中に型のメンテが完了したと言ってもよいでしょう。カンファレンス駆動開発、たのしいですね。
ひとつ興味深かったのは standardrb との兼ね合いです。
conference-app では Lint ツールとして standardrb を使っていますが、現時点の standardrb の最新版は少し古い rubocop をベースとしていています。そのため、RBS::Inline の一部の記法がエラーになるという問題がありました。
そのため、conference-app では #:
記法を使わず、 # @rbs
記法で型コメントを書くようにすることで回避しました。standardrb には 修正を提案しておいた ので、そのうち対応されるといいですね。
Kaigi on Rails 2024 の conference-app の型まわりが壊れていた問題を解決しました。また、合わせて RBS::Inline を導入してみました。
現時点では、Ruby の(RBS の)型システムは成熟しきったとは言えず、型チェックを維持するのはかんたんではありません。Rails の HEAD を使っている conference-app ならではの問題も見つかるなど、手がかかる部分もあります。
一方、こういうリアルのアプリケーションで型を使うことで、型システムが改善されていきます。
今回のメンテナンスでは、gem_rbs_collection や rbs_rails、standardrb などいくつかのリポジトリにフィードバックをかけました。こうした積み重ねにより、いつか手のかからない世の中が来るはずです。
現時点では、gem やフレームワークといった、アプリケーション開発者にとっては下位レイヤーの型の維持に気を配る必要があるのですが、アプリケーション開発者が、自分の書いたアプリケーションに集中できる よう、エコシステムの改善を頑張っていこうと決意を新たにするのでした。
さて、来年の Kaigi on Rails ではどうなっているか楽しみですね。
※ 今回はプロポーザルを投げそびれてしまったので、来年は登壇側にも回りたいですね。がんばります。