はじめに
Software Designで今連載されている「Ruby×静的型付け戦略」をずっと読んでいて、いろんなメリットや実際に導入したプロジェクトでの事例を読んできました。紹介されていたメリットの中で特に気になっているのが、コード補完とAIエージェントの質が良くなる可能性で、リソースの少ない弊社にはありがたそうなことです。
ただ、がっつり入れようとするとキツそうだよなと思いながら、いろいろ探していたんですが…あまりにもちょうどよいメドピアさんの「Railsプロジェクトへの「頑張らない型導入」のすすめ」にたどり着きました。「型を書かず、自動生成のみでsteep checkしない」という割り切りとそれでも今自分が欲しいと思っている補完が得られることを知り、うちも導入してみようと考えました。
…ということで、この記事は導入とその時に躓いた点を書きます。効果等々は来年にはわかっていると思いますので、少々お待ち下さい。
導入と遭遇したトラブル
rbs
インストール
rbsのインストール手順のまま、Gemfileに開発とテスト環境に対してgem 'rbs', require: falseを追加しました。
$ bundle install
Fetching gem metadata from https://rubygems.org/........
Resolving dependencies...
Bundle complete! 101 Gemfile dependencies, 321 gems now installed.
Bundled gems are installed into `./vendor/bundle`
2 installed gems you directly depend on are looking for funding.
Run `bundle fund` for details
$
セットアップ
rbs collectionの使い方にしたがって、rbs collection init、rbs collection installをしました。
$ bundle exec rbs collection init
created: rbs_collection.yaml
$ bundle exec rbs collection install
Installing actioncable:7.1 (actioncable@a5024cf78a9)
Installing actionmailer:7.0 (actionmailer@a5024cf78a9)
(省略)
Installing webmock:3.19 (webmock@a5024cf78a9)
Using webrick:1.9.2 (/Users/ken1flan/src/academist/vendor/bundle/ruby/3.2.0/gems/webrick-1.9.2/sig)
It's done! 112 gems' RBSs now installed.
$
Git管理する対象
実行後に増えた.gem_rbs_collectionを見てみると…Gemの型情報がきていました。
$ tree .gem_rbs_collection
.gem_rbs_collection
├── actioncable
│ └── 7.1
│ └── actioncable.rbs
├── actionmailer
│ └── 7.0
│ ├── actionmailer.rbs
│ ├── mail-message.rbs
│ └── manifest.yaml
(省略)
.gem_rbs_collectionは自プロジェクトのものではないので、管理しないことにします。
rbs_collection.yaml、rbs_collection.lock.yamlは管理しなくても…とも思いましたが、人によって結果が異なると、それはそれで面倒なので登録することにしました。
rbs_rails
インストールと初期化
インストール手順に従って、Gemfileに開発とテスト環境に対してgem 'rbs_rails', require: falseを追加しました。
$ bundle install
Bundle complete! 102 Gemfile dependencies, 322 gems now installed.
Bundled gems are installed into `./vendor/bundle`
2 installed gems you directly depend on are looking for funding.
Run `bundle fund` for details
使い方のまま、bin/rails g rbs_rails:installしました。
$ bin/rails g rbs_rails:install
create lib/tasks/rbs.rake
$
型ファイル生成 / 修正&リトライ
使い方のまま、bin/rails rbs_rails:allを……。
1回目
えーッ!失敗 ![]()
bin/rails rbs_rails:all
warning: parser/current is loading parser/ruby32, which recognizes 3.2.9-compliant syntax, but you are running 3.2.2.
Please see https://github.com/whitequark/parser#compatibility-with-ruby-mri.
bin/rails aborted!
NameError: Missing model class ProjectUser for the RewardItem#project_user association. You can specify a different model class with the :class_name option. (NameError)
raise NameError.new(message, name)
^^^^^
/Users/ken1flan/src/academist/vendor/bundle/ruby/3.2.0/gems/activerecord-7.1.6/lib/active_record/reflection.rb:473:in `rescue in compute_class'
/Users/ken1flan/src/academist/vendor/bundle/ruby/3.2.0/gems/activerecord-7.1.6/lib/active_record/reflection.rb:467:in `compute_class'
/Users/ken1flan/src/academist/vendor/bundle/ruby/3.2.0/gems/activerecord-7.1.6/lib/active_record/reflection.rb:412:in `klass'
/Users/ken1flan/src/academist/vendor/bundle/ruby/3.2.0/gems/rbs_rails-0.12.1/lib/rbs_rails/active_record.rb:162:in `block in belongs_to'
(省略)
RewardItemに記述されていた関連project_userの名前から類推できるテーブルがありませんでした…。
使ってもなかったから発覚したなかったということで、消して再実行し……。
2回目
えーッ!また失敗 ![]()
$ bin/rails rbs_rails:all
warning: parser/current is loading parser/ruby32, which recognizes 3.2.9-compliant syntax, but you are running 3.2.2.
Please see https://github.com/whitequark/parser#compatibility-with-ruby-mri.
bin/rails aborted!
NameError: Missing model class TransferChargesAndSpotCharge for the GmoTransferCharge#transfer_charges_and_spot_charges association. You can specify a different model class with the :class_name option. (NameError)
raise NameError.new(message, name)
^^^^^
/Users/ken1flan/src/academist/vendor/bundle/ruby/3.2.0/gems/activerecord-7.1.6/lib/active_record/reflection.rb:473:in `rescue in compute_class'
/Users/ken1flan/src/academist/vendor/bundle/ruby/3.2.0/gems/activerecord-7.1.6/lib/active_record/reflection.rb:467:in `compute_class'
/Users/ken1flan/src/academist/vendor/bundle/ruby/3.2.0/gems/activerecord-7.1.6/lib/active_record/reflection.rb:412:in `klass'
/Users/ken1flan/src/academist/vendor/bundle/ruby/3.2.0/gems/rbs_rails-0.12.1/lib/rbs_rails/active_record.rb:127:in `block in has_many'
(省略)
GmoTransferChargeに記述されていた関連transfer_charges_and_spot_chargesから類推できるテーブルがやはりありませんでした…。今回はそれらしきテーブルがあったので修正して、再実行し……。
3回目
ました!成功です ![]()
$ bin/rails rbs_rails:all
warning: parser/current is loading parser/ruby32, which recognizes 3.2.9-compliant syntax, but you are running 3.2.2.
Please see https://github.com/whitequark/parser#compatibility-with-ruby-mri.
$
Git管理する対象
bin/rails rbs_rails:allを実行すると、sigディレクトリ以下に型ファイルができるのですが、管理しないことにしたので、.gitignoreにsigを追加しました。
プロジェクトでの利用
開発者各人の手元で rbs collection installとbin/rails rbs_rails:allをしてもらうことにします。
また、今回の型ファイル生成時に不具合を見つけられたことから、週次でbin/rails rbs_rails:allを実行することにしました。
おわりに
まさか、導入するだけで不具合が見つかるとは思っていませんでした。
とにかくこれから使ってみて…いい具合にエディタの補完などが動いてくれることを祈ってます。そして来年のアドベントカレンダーで、導入してみての感想が書けるといいな、と思っています。
参照
以下、とくに感謝です!