ruby / rbs で型検証追加する
Closed this issue · 62 comments
TypeScriptを実装しているとやはり型チェックはあったほうが何かと便利。
Ruby 3.0 で導入予定な静的型検証である rbs を使ってみる。
流れ
rbs ファイル作りまくる(rails も)
steep で検証しまくる
以上
steep は vscode のプラギンもある模様
一旦保留
(gem がないとか色々と辛い
gem "rbs"
で使えるようになってる!ほんと神!
未来の自分のために、これかなり優先度あげて確認してみる
gem "rbs"
導入した
rbsファイル作ってく
日本語でおk
rbs の内容自動生成コマンド
rbs prototype rb app/models/album.rb
rails どうすんねんと思っていたらすでに神gemが
https://github.com/pocke/rbs_rails
rake copy_signature_files
rake generate_rbs_for_model
するだけでsigディレクトリにファイルがたっくさん追加される
rake generate_rbs_for_model
実行時に
Mysql2::Error: Table '***********_db.action_text_rich_texts' doesn't exist
というエラーがでる。
action_text スキップしないとダメか
自動生成ほんと神
明日 rbs validate やる
https://github.com/himanushi/music-server/compare/18/rbs?expand=1
検証方法がようわからない
mode: :extension がなくなっていた
rbs ファイルの定義が壊れていないかを検証する
rbs -I sig/ validate
これフルでモジュール書かないとエラーにならないか?
やっと全てのファイルを修正できた
rbs の情報少なすぎてツライ
rake generate_rbs_for_model
した時に rails メソッド以外のメソッドも出力しないとか
loader = RBS::EnvironmentLoader.new()
loader.add(path: Pathname("sig"))
environment = RBS::Environment.from_loader(loader).resolve_type_names
album = RBS::TypeName.new(name: :Album, namespace: RBS::Namespace.root)
decl = environment.class_decls[album]
builder = RBS::DefinitionBuilder.new(env: environment)
instance = builder.build_instance(album)
instance.methods[:artists].method_types.join("\n")
このへん使えば行けそう
だめだ
どうすれば
まぁ基礎はできたので検証やってくか
https://github.com/soutaro/steep
steep神だった
あとはどうやって運用していくのかか
むずいのでライブラリの簡単な奴からrbsしっかり作ってく
ruby 標準ライブラリの型がところどころないので untyped にしておく
今後求めるもの
- Rails model に RDoc で書いたものがそのまま rbs で出力される
- VScode で steep の型補完をする(すでにプロジェクトはある)
全てのクラスが終わるまで rbs の issue をクローズさせないッ!!
型検証だいぶいいね
全体の見直しになってとても素晴らしい
型設定するの楽しくなってきた
わかってくると楽しい
model 全てやったのだが、sig の extend 専用をどうやって実装するのかわからん。
具体的には extend ActiveSupport::Concern
の module って include 専用なので基本的に NoMethodError になるんよ。
やっと書き方わかった
module ClassMethods : _ActiveRecord_Relation[untyped]
こうだよ!
やっと進んだ
ハマってた
なんで NoMethodError なるんじゃああああああ
ってなってたら singleton method だった
rbs -I sig method Album where
↑これじゃなく↓これね
rbs -I sig method --singleton Album where
rbs やる人のハマりポイント全てハマるマン
インターフェースの立ち位置についての考え
https://twitter.com/soutaro/status/1285225653059506176?s=20
Github issue を Twitter みたいに使うマン
カンマ区切りできるんかーい
_module-self-types_ ::= _class-name_ _type-arguments_ `,` _module-self-types_ (Class instance)
| _interface-name_ _type-arguments_ `,` _module-self-types_ (Interface)
一生懸命 interface 作ってたわ
lib rbs 化やってく
型安全最高!
vscode のプラグインとして steep vscode 導入した。最近追加されたっぽい
これはほんとに最高だわ
sig追加捗る
まだ不安定なので目印的な感じかな
でもこれ高速起動してたらかなり使える
知らないうちに rbs のリポジトリ fork してた
型書くの最高じゃんと思ってた。
けど今日の RubyKaigi の Matz の話聞いてて、確かに型検証をリアルタイムで行われ続ければ型を書く必要ないなぁと。
遠い未来かもしれないがPCの性能とか型検証が優れれば逆に型を書くこと自体がボトルネックになるのか。
とても面白いカンファレンスだった。
改めて rbs のリファレンス読んだけど独自の型宣言できたのか。。。。
Hash とか繰り返し使うとき便利じゃん。
https://github.com/ruby/rbs/blob/master/docs/syntax.md#type-alias-declaration
これ gem 側が sig 提供進まないとかなり追加辛い感じがする
**はとても良いけど全員が追加するかというとそうじゃないので難しい
gem 側の sig は基本的にデフォルトで untyped で宣言されておいてくれるといいのかなー。
def foo: (*untyped, **untyped) ?{ (*untyped) -> untyped } -> untyped
みたいな。
type profiler の出番か
最強のガバ型(警告が大量に出るのでオススメしない)
(*untyped, **untyped) ?{ (*untyped, **untyped) -> untyped } -> untyped
ガバ型
(*untyped) ?{ (untyped) -> untyped } -> untyped
gem の型はまぁしっかり実装した方がいいけどそれはこちらの作業ではないので基本的にはガバ型で実装してく。
めんどかったら最強ガバ型で実装。
アプリ側の型はしっかり書いてgemは今後実装者が追加するはずなのでそんな感じの方針で書いてく。
型キツくなってきた
compact で nil が除外されないのがもっとも辛い
随時やってく感じなのでクローズ