Slide 1

Slide 1 text

相生ゆらの #Kaigieffect Yla Aioi (@Little_Rubyist)

Slide 2

Slide 2 text

今回話す人 相生ゆら/Yla Aioi @Little_Rubyist @Little-Rubyist RBSとRuboCopに興味があります 2023/02~

Slide 3

Slide 3 text

- lramaにPR出した - 会社のプロジェクトにRBS導入を始めた - RBS導入時のポイント アジェンダ

Slide 4

Slide 4 text

今回のRubyKaigiは 大パーサー時代でしたね lramaの話

Slide 5

Slide 5 text

lramaの話

Slide 6

Slide 6 text

lramaの話

Slide 7

Slide 7 text

というわけで

Slide 8

Slide 8 text

lramaの話

Slide 9

Slide 9 text

やったこと lramaの話

Slide 10

Slide 10 text

rbs, steepを入れる lramaの話

Slide 11

Slide 11 text

挙動確認のために 適当なファイルに型をつける lramaの話

Slide 12

Slide 12 text

Github Actionに Steep checkを追加する lramaの話

Slide 13

Slide 13 text

PRを出して終わり :tada: lramaの話

Slide 14

Slide 14 text

ちなみに初contributeでした lramaの話

Slide 15

Slide 15 text

あなたがlramaに RBSを追加したいときに やるべきこと lramaの話

Slide 16

Slide 16 text

型付けするファイルを決める lramaの話

Slide 17

Slide 17 text

(現状は) steepfileに狙いをつけたファイルを checkさせる lramaの話

Slide 18

Slide 18 text

ファイルの中身を読む lramaの話

Slide 19

Slide 19 text

RBSを書く lramaの話

Slide 20

Slide 20 text

ruby/lramaに PR出して祈る :pray: lramaの話

Slide 21

Slide 21 text

lramaは金子さんがRBS 入れようとしてくれていますが 他gemはあんまりっぽい gem_rbs_collection

Slide 22

Slide 22 text

そういう時はgem_rbs_collectionに 新しいgemを追加したり 既存gemの型を足していきましょう gem_rbs_collection

Slide 23

Slide 23 text

え,gemは使ってるけど プロジェクトでは 一部のmethodしか使ってない? gem_rbs_collection

Slide 24

Slide 24 text

そんな状況で1ファイルの 型付けは厳しい? gem_rbs_collection

Slide 25

Slide 25 text

わかる〜〜〜!!!!! gem_rbs_collection

Slide 26

Slide 26 text

1method 1PR でも大丈夫です :+1: gem_rbs_collection

Slide 27

Slide 27 text

もし不安な時は手元で patch的に型を付けてから PRを出しましょう gem_rbs_collection

Slide 28

Slide 28 text

私の例を話しましょう 会社のプロジェクトにRBS入れた話

Slide 29

Slide 29 text

手順

Slide 30

Slide 30 text

steep, rbs_rails を入れる

Slide 31

Slide 31 text

rbs_rails:generate_rbs_for_models を走らせる

Slide 32

Slide 32 text

動かないので困る

Slide 33

Slide 33 text

composite-primary-key を使っていた

Slide 34

Slide 34 text

rbs_railsのprimary_key部を 変える

Slide 35

Slide 35 text

class Generator < RbsRails::ActiveRecord::Generator private def pk_type pk = klass.primary_key return 'top' unless pk if pk.instance_of?(::CompositePrimaryKeys::CompositeKeys) sql_types = [] pk.each do |x| col = klass.columns.find { |column| column.name == x } sql_types << sql_type_to_class(col.type) end return sql_types.join(' | ') end col = klass.columns.find { |column| column.name == pk } sql_type_to_class(col.type) end end

Slide 36

Slide 36 text

通った :tada:

Slide 37

Slide 37 text

> bundle exec steep check > Detected 714 problems from 91 files

Slide 38

Slide 38 text

Rails wayに沿ってないので 余計にエラーが出る

Slide 39

Slide 39 text

これが3/2

Slide 40

Slide 40 text

大体は定義したら解決したけど どれだけ悩んでも分からない子も 結構いた

Slide 41

Slide 41 text

included do…endの中で 定義しているので include先のclassが持ってる methodが分からない

Slide 42

Slide 42 text

module SomeModule extend ActiveSupport::Concern included do # @type self: ClassMethods & singleton(ApplicationRecord) ... end 型注釈してあげる

Slide 43

Slide 43 text

明らかにお前はModuleだろ… と思うのに define_methodを知らないと言う

Slide 44

Slide 44 text

module Models::UndefinedDateTimeAttribute extend ActiveSupport::Concern module ClassMethods : Module def attr_undefined_datetime: (untyped column) -> void end end 実はこれどういう時に使うか 分かってない. moduleそのものの情報を足してあげる

Slide 45

Slide 45 text

read_attributeやscopeに blockが必須と言われる

Slide 46

Slide 46 text

必須ではないので blockを持たない型を足してあげる

Slide 47

Slide 47 text

module ActiveRecord module AttributeMethods module Read extend ActiveSupport::Concern def read_attribute: (untyped attr_name) -> untyped | ... end end module Scoping module Named extend ActiveSupport::Concern module ClassMethods def scope: (untyped name, untyped body) -> untyped | ... end end end end

Slide 48

Slide 48 text

みたいなのを延々とやりました

Slide 49

Slide 49 text

この辺は全部RubyKaigi中に @pockeと@soutaroに 助けてもらいました thanks!

Slide 50

Slide 50 text

一昨日

Slide 51

Slide 51 text

それなりに出来たので katakata_irb導入 thanks @tompng

Slide 52

Slide 52 text

しかしちょっと問題があって

Slide 53

Slide 53 text

今回簡単なところから RBSを入れたので models/しか対応していない

Slide 54

Slide 54 text

ので あんまりkatakata_irbでは 自前RBSの恩恵を 受けられていなさそう

Slide 55

Slide 55 text

まあnilableとかのエラーは 見つけたのでいいか!

Slide 56

Slide 56 text

型書くの楽しいです

Slide 57

Slide 57 text

便利command

Slide 58

Slide 58 text

bundle exec rbs -I sig method Hoge foo?

Slide 59

Slide 59 text

bundle exec rbs -I sig method Hoge foo? RBSファイルの定義場所

Slide 60

Slide 60 text

bundle exec rbs -I sig method Hoge foo? RBSファイルの定義場所 method コマンド 最強

Slide 61

Slide 61 text

bundle exec rbs -I sig method Hoge foo? RBSファイルの定義場所 method コマンド 最強 探したいmethod

Slide 62

Slide 62 text

❯ bundle exec rbs -I sig method --singleton Hoge find ::hoge.find defined_in: ::_ActiveRecord_Relation_ClassMethods implementation: ::OfficialComicGroup accessibility: public types: (::Integer id) -> ::Hoge | (::Array[::Integer]) -> ::Array[::Hoge] | (*::Integer) -> ::Array[::Hoge] 便利だね〜〜〜

Slide 63

Slide 63 text

これで見つからなかったら 型注釈を足すとか 型定義を足すとか includeとかしてあげるとか

Slide 64

Slide 64 text

何かどう足掻いても直せない時 -> ruby-jp #types に投げるとよいです

Slide 65

Slide 65 text

あまったら喋るやつ

Slide 66

Slide 66 text

今まだ直せてない謎エラー達

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

ガード文書いてるのに association系でchild.age? 的なmethodやると nilableなエラーが出る (一般的なコードにする時間なかった)

Slide 69

Slide 69 text

解決法がわかる人がいたら 教えて下さい〜