Slide 1

Slide 1 text

銀座Rails#26@ リンクアンドモチベーション 銀座Rails#26@ リンクアンドモチベーション これからの Ruby と今の Ruby について これからの Ruby と今の Ruby について

Slide 2

Slide 2 text

Ruby 3.0 でこれを実⾏すると何が起きる? Ruby 3.0 でこれを実⾏すると何が起きる? private def value(value) = value => @value private def value(value) = value => @value → 知りたい⼈は最後まで読んでね! → 知りたい⼈は最後まで読んでね!

Slide 3

Slide 3 text

⾃⼰紹介 ⾃⼰紹介 名前:osyo Twitter : github : ブログ : 趣味で Ruby にパッチを投げたり bugs.ruby で気になったチケットを ブログにまとめたりしてる Ruby 2.5 〜 2.7 までオレオレ機能を追加した Ruby 3.0 では機能追加できなかった… Ruby で⼀番好きな機能は Refinements オンラインなのであちこちの地域.rb に参加してる @pink_bangbi osyo-manga Secret Garden(Instrumental) Fukuoka.rb Hamada.rb kawasaki.rb nikotama.rb Sendai.rb Shibuya.rb Shinjuku.rb Tama.rb Toyama.rb Gotanda.rb Entaku.rb Grow.rb Hamamatsu.rb kanazawa.rb Kobe.rb Machida.rb mitaka.rb Ruby Tuesday toruby ⻄⽇暮⾥.rb

Slide 4

Slide 4 text

これからの Ruby と今の Ruby について これからの Ruby と今の Ruby について

Slide 5

Slide 5 text

これからの Ruby これからの Ruby → Ruby 3.0 → Ruby 3.0

Slide 6

Slide 6 text

注意 注意 このスライドでは基本的に Ruby 3.0.0-preview1 時点での挙動を元に して書いている 特別な記述がない限りは preview1 でコードを実⾏できる(はず ただし、⼀部、最新版で動作確認しているので注意 Ruby 3.0 がリリースされた時に挙動が変わっている可能性がある Ruby 3.0 を使⽤する場合はその時点でのリリースノート等の情報 を参照してね

Slide 7

Slide 7 text

Ruby 3.0 の概要 Ruby 3.0 の概要 Ruby 3.0 は 2020/12/25 にリリース予定 オリンピックは延期しても Ruby のリリースは延期しないよ それに先駆け先⽇ がリリースされた Ruby 3.0 はいろいろと⽬⽟機能がてんこ盛りなのでみんな試してみ よう!! 実際に試して変な挙動があればどんどん に報告してね ⼀⽅で Ruby 3.0 ではいくつか⾮互換な変更が⼊っている キーワード引数の挙動などなど… バージョンを上げる際には注意する必要がある Ruby 3.0.0 preview1 bugs.ruby

Slide 8

Slide 8 text

Ruby 3.0 で追加される機能について解説 Ruby 3.0 で追加される機能について解説

Slide 9

Slide 9 text

RBS RBS Ruby 3.0 で RBS という型情報の概念が追加される RBS は .rbs というファイルに型情報を定義する Ruby のコード上には型情報は記述しない .rbs の書き⽅はドキュメントをみてね RBS の利⽤⽅法は⼤きく分けて 2 種類ある 1. CLI から型情報を取得する 2. Ruby のコード上から型情報を取得する また Ruby 3.0 時点では標準の機能で RBS を利⽤した型チェックなど は⾏わない予定 RBS は gem としても配布されているので gem install rbs すれば Ruby 2.7 でも使えるよ!!

Slide 10

Slide 10 text

CLI から RBS を利⽤する rbs コマンドから型情報を取得する # 任意のクラス/ モジュールの継承リストを取得する $ rbs ancestors ::String ::String ::Comparable ::Object ::Kernel ::BasicObject # 任意のメソッドの型シグネチャを取得する $ rbs method ::String gsub ::String#gsub defined_in: ::String implementation: ::String accessibility: public types: (::Regexp | ::string pattern, ::string replacement) -> ::String | (::Regexp | ::string pattern, ::Hash[::String, ::String] hash) -> ::String | (::Regexp | ::string pattern) { (::String match) -> ::_ToS } -> ::String | (::Regexp | ::string pattern) -> ::Enumerator[::String, self]

Slide 11

Slide 11 text

rbs コマンドで .rbs の雛形を⽣成する 元にする .rb ファイル # fizzbuzz.rb class FizzBuzz def initialize(value) @value = value end def fizz?; @value % 3 == 0 end def buzz?; @value % 5 == 0 end def fizzbuzz?; fizz? && buzz? end def to_s fizzbuzz? ? "FizzBuzz" : fizz? ? "Fizz" : buzz? ? "Buzz" : @value.to_s end end class Integer def to_fizzbuzz FizzBuzz.new(self) end end

Slide 12

Slide 12 text

"rbs prototype rb ファイル名" で雛形を⽣成できる このファイルを元に .rbs ファイルに型情報を記述する $ rbs prototype rb fizzbuzz.rb class FizzBuzz def initialize: (untyped value) -> untyped def fizz?: () -> untyped def buzz?: () -> untyped def fizzbuzz?: () -> untyped def to_s: () -> untyped end class Integer def to_fizzbuzz: () -> untyped end

Slide 13

Slide 13 text

こんな感じで実際の型情報を .rbs ファイルに保存する # fizzbuzz.rbs class FizzBuzz def initialize: (Integer) -> void def fizz?: () -> bool def buzz?: () -> bool def fizzbuzz?: () -> bool def to_s: () -> String end class Integer def to_fizzbuzz: () -> FizzBuzz end

Slide 14

Slide 14 text

Ruby から .rbs ファイルを読み込んで型情報を取得できる require "rbs" loader = RBS::EnvironmentLoader.new() # .rbs を読み込むパスを追加 loader.add(path: Pathname("./")) environment = RBS::Environment.from_loader(loader).resolve_type_names builder = RBS::DefinitionBuilder.new(env: environment) # FizzBuzz クラスの型情報を取得 fizzbuzz = RBS::TypeName.new(name: :FizzBuzz, namespace: RBS::Namespace.root) instance = builder.build_instance(fizzbuzz) # 全インスタンスメソッドを出⼒ puts instance.methods.map { |name, sig| method.method_types.map { |sig| "FizzBuzz##{name}#{sig}" } } # output: # ... # FizzBuzz#fizz?() -> bool # FizzBuzz#buzz?() -> bool # FizzBuzz#fizzbuzz?() -> bool # ...

Slide 15

Slide 15 text

標準ライブラリの型情報を取得したりもできる require "rbs" loader = RBS::EnvironmentLoader.new() environment = RBS::Environment.from_loader(loader).resolve_type_names builder = RBS::DefinitionBuilder.new(env: environment) # String の型情報を取得する string = RBS::TypeName.new(name: :String, namespace: RBS::Namespace.root) # String#index の型シグネチャを取得する instance = builder.build_instance(string) puts instance.methods[:index].method_types.join("\n") # output: # (::Regexp | ::string substr_or_regexp, ?::int offset) -> ::Integer? # (?::string str, ?capacity: ::int, ?encoding: ::encoding) -> ::String # String.new の型シグネチャを取得する singleton = builder.build_singleton(string) puts singleton.methods[:new].method_types.join("\n") # output: # (?::string str, ?capacity: ::int, ?encoding: ::encoding) -> ::String

Slide 16

Slide 16 text

参照リンク 参照リンク GitHub - ruby/rbs: Type Signature for Ruby rbs/CONTRIBUTING.md at master · ruby/rbs · GitHub rbs cli - pockestrap Ruby の型関連の情報まとめ - Qiita

Slide 17

Slide 17 text

TypeProf TypeProf TypeProf は Ruby のソースコードから型推論して型情報がある .rbs を ⽣成するツール 最近 TypeProfiler から TypeProf に名前が変わった TypeProf は Ruby 3.0 に同梱される予定 開発版だとすでに これは .rb をパースする際に実際にメソッドに渡されたリテラルから 型を推論するような仕組みになっている なので .rb の書き⽅によって⽣成される .rbs は異なる また TypeProf は Ruby 3.0.0-preview1 には同梱されていないので注意 TypeProf は gem としても配布されているので gem install typeprof で 今すぐ試すことができる!! bundled gem になっている

Slide 18

Slide 18 text

typeprof コマンドで .rbs 形式の情報を出⼒する Ruby 3.0.0-preview1 では事前に gem install typeprof しておく必要があ る ここに書かれているのは 2020/10/21 時点のもの # 元ファイル # twice.rb def twice(a) a + a end # typeprof コマンドで .rbs 形式の出⼒がされる # typeprof は実際にメソッドに渡される引数リテラルを元にして型推論を⾏う # 現状だと twice メソッドの呼び出しがないので型推論できない… $ typeprof twice.rb # Classes class Object def twice : (untyped) -> untyped end

Slide 19

Slide 19 text

TypeProf はメソッド呼び出しのリテラルから型推論する # twice.rb def twice(a) a + a end # メソッドを呼び出す twice(42) twice("homu") $ typeprof twice.rb # 型情報が追加されている # twice に Integer や String が渡されている情報を元にして型推論する # Classes class Object def twice : (Integer | String) -> (Integer | String) end

Slide 20

Slide 20 text

変数やメソッドを経由しても推論される、すごい def twice(a) a + a end value = 42 value2= twice(value) # Integer を渡す twice(value2.to_s) # String を渡す $ typeprof twice.rb # Classes class Object def twice : (Integer | String) -> (Integer | String) end

Slide 21

Slide 21 text

複雑なコードを渡すと… ? class FizzBuzz def initialize(value) @value = value end def fizz?; @value % 3 == 0 end def buzz?; @value % 5 == 0 end def fizzbuzz?; fizz? && buzz? end def to_s fizzbuzz? ? "FizzBuzz" : fizz? ? "Fizz" : buzz? ? "Buzz" : @value.to_s end end class Integer def to_fizzbuzz FizzBuzz.new(self) end end puts 1.upto(20).map { |index| index.to_fizzbuzz }

Slide 22

Slide 22 text

こういう結果になる かなり便利そうなので期待したい $ typeprof fizzbuzz.rb # Classes class Integer < Numeric def to_fizzbuzz : -> FizzBuzz end class FizzBuzz @value : Integer def initialize : (Integer) -> Integer def fizz? : -> bool def buzz? : -> bool def fizzbuzz? : -> bool def to_s : -> String end

Slide 23

Slide 23 text

参照リンク 参照リンク ⽇本語の資料なので読みやすい! ここを読めばだいたい OK RubyKaigi Takeout 2020 の登壇動画 RubyKaigi Takeout 2020 の登壇資料 GitHub - ruby/typeprof: An experimental type-level Ruby interpreter for testing and understanding Ruby code typeprof/doc.ja.md at master · ruby/typeprof · GitHub [JA] Type Profiler: a Progress Report of a Ruby 3 Type Analyzer / Yusuke Endoh @mametter - YouTube Type Profiler: Ambitious Type Inference for Ruby 3

Slide 24

Slide 24 text

Ractor Ractor Ractor は Ruby で並列処理を⾏うためのライブラリ 以前は Guild という名前で開発されていたが Ractor という名前に 変わった Ruby + Actor の略 Ruby 3.0 では実験的に導⼊される予定 Ractor に関しては⽇々改良されているので preview1 と⽐較して Ruby 3.0 がリリースされる頃にはいろいろと使い⽅や制限が変わっている 可能性があるので注意する 最近も #recv から #receive に名前が変わった サポートする共有可能オブジェクトが追加されたりとか

Slide 25

Slide 25 text

以下のコードを実⾏すると hello と world が混ざって出⼒される # Ractor.new のブロックが並⾏処理として実⾏される # ブロック内は外の変数を参照できないので # .new の引数がブロックの引数として受け取る事ができる ractor = Ractor.new(10) do |loop_count| # トップレベルとは別に Ractor 内でも設定する必要がある $stdout.sync = true loop_count.times do puts :hello sleep 0.3 end end # 出⼒バッファリングを無効にする $stdout.sync = true 10.times do puts :world sleep 0.3 end

Slide 26

Slide 26 text

Ractor のメッセージの送り⽅:push 型 # Ractor へメッセージを送る # push 型 ractor = Ractor.new { $stdout.sync = true puts "=== Ractor start ===" # メッセージを受け取るまで待つ # 将来的に recv は receive に名前が変わるので注意 value = Ractor.recv puts value # => 42 puts "=== Ractor end ===" sleep 3 # ブロックの戻り値が take の戻り値になる value + value } sleep 3 ractor.send(42) # 待ち処理 puts ractor.take # => 84 puts "=== Finish ==="

Slide 27

Slide 27 text

Ractor のメッセージの送り⽅:pull 型 # Ractor からメッセージを受け取る # pull 型 ractor = Ractor.new { $stdout.sync = true puts "=== Ractor start ===" # take が呼ばれるまで待つ puts Ractor.yield 42 puts "=== Ractor end ===" } sleep 3 # 待ち処理 # Ractor.yield の引数を返す puts ractor.take # => 42 sleep 2 puts "=== Finish ==="

Slide 28

Slide 28 text

Ractor でスリープソートを書いてみるとこんな感じ 要素の値だけ sleep して要素の値が少ない順で処理するソート $stdout.sync = true puts " かいし!!!" data = (1..20).to_a.shuffle p data ractors = data.map { |i| Ractor.new(i) { |it| # バッファリングを無効化 $stdout.sync = true sleep it / 5.0 puts it } } # 待ち処理 ractors.map(&:take) puts " おわり!!"

Slide 29

Slide 29 text

参照リンク 参照リンク ⽇本語の資料だがちょっと古いので注意 ruby/ractor.md at master · ruby/ruby · GitHub ruby/ractor.ja.md at ractor · ko1/ruby · GitHub Ractor 超⼊⾨ - Qiita 並列処理⼊⾨ + Ruby での新しい並列実⾏単位Ractor - Qiita

Slide 30

Slide 30 text

Module#include の挙動が変わった Module#include の挙動が変わった Ruby 3.0 で Module#include / prepend の挙動がちょっと変わります 今まではすでに include 済みのモジュールに対して include してもす でに include されているオブジェクトには反映されませんでした Ruby 3.0 ではあとから include した場合でもすでに include 済みのオ ブジェクトに反映されるようになりました 何をいってるのかわからないと思うのでサンプルコードを⾒てみよ う

Slide 31

Slide 31 text

以下のようすでに X.include M してる M に対して M.include M2 をする と X.ancestors に M2 が反映されるようになる module M; end class X include M end # この時点では M のみ反映されている p X.ancestors # => [X, M, Object, Kernel, BasicObject] module M2; end # M に対してあとから include したときの挙動が変わった M.include M2 # Ruby 2.7 : M2 は反映されない # Ruby 3.0 : M2 が反映される p X.ancestors # Ruby 2.7 => [X, M, Object, Kernel, BasicObject] # Ruby 3.0 => [X, M, M2, Object, Kernel, BasicObject]

Slide 32

Slide 32 text

Ruby 3.0 からは Kernel.include M をすると既存のクラスに反映される module M def twice self + self end end p String.ancestors Kernel.include M # => [String, Comparable, Object, Kernel, BasicObject] # 既存のクラスに M が反映されるようになる p String.ancestors # Ruby 2.7 => [String, Comparable, Object, Kernel, BasicObject] # Ruby 3.0 => [String, Comparable, Object, Kernel, M, BasicObject] # M のインスタンスメソッドが呼び出せるようになる p "hoge".twice # Ruby 2.7 => error: undefined method `twice' for "hoge":String (NoMethodError) # Ruby 3.0 => "hogehoge"

Slide 33

Slide 33 text

またこれは以下のように複数のモジュールを mixin している場合に 問題になる可能性がある module M1 def to_s; "M1 -> " + super end end module M2 def to_s; "M2 -> " + super end end class X include M1 include M2 def to_s; "X -> " + super end end # このあたりは今までどおり期待する挙動 p X.ancestors # => [X, M2, M1, Object, Kernel, BasicObject] p X.new.to_s # => "X -> M2 -> M1 -> #"

Slide 34

Slide 34 text

以下のようにすると .ancestors に同じモジュールが複数含まれるよ うになる これにより今までの挙動と少し変わる可能性がある 今までは問題なかったが Ruby 3.0 に上げるとモジュールが重複して しまう可能性があるので注意する # M1 に M2 を mixin する M1.include M2 # Ruby 2.7 だとモジュールは重複しないが Ruby 3.0 だと重複するようになる p X.ancestors # Ruby 2.7 => [X, M2, M1, Object, Kernel, BasicObject] # Ruby 3.0 => [X, M2, M1, M2, Object, Kernel, BasicObject] # 当然 super 経由で呼び出されるメソッドも異なるようになる p X.new.to_s # Ruby 2.7 => "X -> M2 -> M1 -> #" # Ruby 3.0 => "X -> M2 -> M1 -> M2 -> #"

Slide 35

Slide 35 text

参照リンク 参照リンク 元のバグチケット 継承リストに同じモジュールが複数含まれるのはバグじゃない? というバグチケット 実際はバグではなくて意図した挙動なのでこのチケットは Reject されている Ruby 3.0 で変わる Module#include の挙動 - Secret Garden(Instrumental) [Bug #9573] descendants of a module don't gain its future ancestors, but descendants of a class, do [Bug #17038] On master, ancestry edits can lead to duplicates in Module#ancestors

Slide 36

Slide 36 text

右代⼊ 右代⼊ 通常は左辺に変数に対して右辺の値を代⼊する result = 42 右代⼊は左辺の値を右辺の変数に代⼊する構⽂ 42 => result これを利⽤するとメソッドチェーンなど⻑いコードを書いている際 に左から右にコードを書く流れで変数を定義する事ができる irb などで変数定義する場合にいちいち左にカーソルを移動させ たりしていたがそういう煩わしさがなくなる ただし、いくつか注意点がある Ruby 3.0 では実験的な機能という位置づけ

Slide 37

Slide 37 text

通常は左辺の変数に右辺の値を代⼊していた Ruby 3.0 から追加される => 演算⼦を使うと『左辺の値を右辺の変数 に』代⼊する事ができる ただし、以下のような代⼊はできないので注意 # 左辺に右辺の値を代⼊ result = 42 # 左辺を右辺に代⼊ 42 => result # 多重代⼊などもできる [1, 2] => a, b # error # see: https://bugs.ruby-lang.org/issues/17190 1, 2 => a, b

Slide 38

Slide 38 text

メソッドの戻り値を代⼊する場合に注意する必要がある => の優先順位の問題で以下のコードはうまく動作しない この書き⽅は twice({ 42 => result }) と解釈される 右代⼊は処理の優先順位を考えて使う必要がある def twice(a) a + a end # twice(42) の結果を変数 reuslt に代⼊したい twice 42 => result # これは => が Hash リテラルとして解釈される為 # twice 42 => result という書き⽅は Ruby 2.7 でも有効な書き⽅になる twice({ 42 => result }) # 明⽰的に括弧を付けて代⼊する twice(42) => result p result # => 42

Slide 39

Slide 39 text

参照リンク 参照リンク 改めて整理する Ruby 3.0 に実験的に⼊る予定のエンドレスメソッド 定義構⽂と右代⼊演算⼦について - Secret Garden(Instrumental)

Slide 40

Slide 40 text

エンドレスメソッド定義 エンドレスメソッド定義 1 ⾏でメソッドが定義できる構⽂ def value() = 42 みたいに定義できる エンドレスとは『end がない』という意味 Ruby 3.0 では定義できるメソッドの仕⽅に制限があるので注意する 元々はエイプリルフールネタで投稿されたチケットがなぜか実装さ れてしまい、その流れで⼊った Ruby 3.0 では実験的な機能という位置づけ

Slide 41

Slide 41 text

def メソッド名() = 式という形でメソッドを定義することができる class FizzBuzz def initialize(value) = @value = value def fizz?() = @value % 3 == 0 def buzz?() = @value % 5 == 0 def fizzbuzz?() = fizz? && buzz? def to_s() = fizzbuzz? ? "FizzBuzz" : fizz? ? "Fizz" : buzz? ? "Buzz" : @value.to_s end class Integer def to_fizzbuzz() = FizzBuzz.new(self) end puts 1.upto(20).map { |index| index.to_fizzbuzz }

Slide 42

Slide 42 text

通常のメソッド定義とは違いいくつか制限がある 必ず () を書く必要があり = が付いているメソッドは定義できない # OK def set_value(value) = @value = value def value() = @value def invalid?() = @value.nil? # NG # () を付ける必要がある # syntax error, unexpected '=', expecting ';' or '\n' def value = 42 # 名前に = がついてるメソッドは定義できない # error: setter method cannot be defined in an endless method definition def value=(value) = @value = value

Slide 43

Slide 43 text

参照リンク 参照リンク 改めて整理する Ruby 3.0 に実験的に⼊る予定のエンドレスメソッド 定義構⽂と右代⼊演算⼦について - Secret Garden(Instrumental)

Slide 44

Slide 44 text

右代⼊とエンドレスメソッド定義を 右代⼊とエンドレスメソッド定義を 組み合わせると 組み合わせると 何が起きる… ? 何が起きる… ?

Slide 45

Slide 45 text

例えばセッターメソッドとしてこういうメソッドを定義する これをエンドレスメソッド定義するとこうなる 更に右代⼊を利⽤するとこうなる private def set_value(value) @value = value end private def set_value(value) = @value = value private def set_value(value) = value => @value

Slide 46

Slide 46 text

どうなるのか 1 つ1 つ⾒ていく どうなるのか 1 つ1 つ⾒ていく

Slide 47

Slide 47 text

まず は となる これは右代⼊よりもメソッド定義のほうが優先順 位が⾼いから def value(value) = value => @value # def 式の戻り値が @value に代⼊される (def value(value) = value) => @value @value # => :value

Slide 48

Slide 48 text

更に は という意味になる private def value(value) = value => @value private(def value(value) = value => @value)

Slide 49

Slide 49 text

つまり は と同じ意味になる 右代⼊が => を使っているのがだいたい悪い private def value(value) = value => @value # (def value(value) = value) がキーで値が @value の Hash を private に渡そ うとする # error: `private': {:value=>nil} is not a symbol nor a string (TypeError) private( { (def value(value) = value) => @value } )

Slide 50

Slide 50 text

Ruby むずかしくない??? Ruby むずかしくない???

Slide 51

Slide 51 text

その他:細かい変更点や追加点 その他:細かい変更点や追加点 キーワード引数周りで⾮互換な変更が⼊る 今まで出てた警告がエラーになる Hash#except, ENV.except が追加された ほしかったやつ Symbol#name が追加された ⾃⾝を frozen string で返すメソッド _1 という名前の変数やメソッドは定義できなくなる (...) 引数で第⼀引数を仮引数で定義できるようになった 詳しくは をみてくれよな! def method_missing(meth, ...) send(:"do_#{meth}", ...) end Ruby 3.0.0-preview1 の NEWS

Slide 52

Slide 52 text

今の Ruby 今の Ruby → Ruby 2.7.2 → Ruby 2.7.2

Slide 53

Slide 53 text

Ruby 2.7.2 でどういう世界になるのか Ruby 2.7.2 でどういう世界になるのか

Slide 54

Slide 54 text

Ruby 2.7.2 の世界 Ruby 2.7.2 の世界 先⽇ された このリリースでは webrick の脆弱性対応が含まれている また『⾮推奨な警告がデフォルトでは出⼒さなくなる』という対応 も含まれている 今回話すのはこの『⾮推奨な警告がデフォルトでは出⼒さなくな る』ことに対して Ruby 2.7.2 がリリース

Slide 55

Slide 55 text

⾮推奨な警告が出⼒されなくなるとどうなる? ⾮推奨な警告が出⼒されなくなるとどうなる? 1. アプリケーションで⾮推奨な機能を使っていた これは今まで問題なかったコードが⾮推奨になってしまうケース も含まれる 2. ⾮推奨であることに気づかないままそのコードを使い続けた デフォルトでは警告が出なくなるので気づきづらい 3. ある⽇、⾮推奨な機能が Ruby から削除された 4. そして Ruby のバージョンを上げると突然アプリケーションが壊れる これはこわい!! これはこわい!!

Slide 56

Slide 56 text

明⽰的に⾮推奨な警告を出⼒する⽅法 明⽰的に⾮推奨な警告を出⼒する⽅法 明⽰的に⾮推奨な警告を出⼒する⼿段として 2 つある 1 つは Ruby のコマンドラインオプションに -W:deprecated を渡す ruby -W:deprecated sample.rb もう1 つは Ruby のコード上で Warning[:deprecated] = true を呼び出す この2 つは Ruby 2.7 から使える機能になる なので Ruby 2.6 とかで使おうとするとエラーになる Ruby 2.6 の環境と混同する場合はワークアラウンド対応が必要…

Slide 57

Slide 57 text

これからどう向き合っていくのか これからどう向き合っていくのか

Slide 58

Slide 58 text

いつ警告を出す? いつ警告を出す? どのタイミング、どの出⼒で警告を出すべき? CI で出す? ローカルで出す? テストを実⾏したときに出す? rails s で出す? などなどいろいろと考えられる

Slide 59

Slide 59 text

警告を出すべき出さないべき? 警告を出すべき出さないべき? そもそも警告を出すべき?出さないべき? 警告を出さない場合は⾮推奨な機能が削除された場合にいきなりア プリケーションが壊れてしまう 警告⾃体はいずれかのタイミングでキャッチアップするべき? 普段は気にせずに開発して Ruby のバージョンを上げる際に対応する ⼿もある? でも漏れがあったら怖いし…

Slide 60

Slide 60 text

どうやって制御する? どうやって制御する? コマンドオププションで制御する?Warning[:deprecate] で制御す る? 環境変数 RUBYOPT に -W:deprecated を追加すればいい? でも Ruby 2.6 でこのオプションを参照すると死ぬ… Ruby 2.7 のプロジェクトでのみ RUBYOPT に追加したい Warning[:deprecate] = true する場合どのタイミンで呼び出す? Rails のプロジェクトだと ./bin/rails に直接記述してしまうとか? gem を開発する場合 Warning[:deprecate] を書き換えて運⽤するのは 難しそう…

Slide 61

Slide 61 text

考えることが多くて結構難しい 考えることが多くて結構難しい

Slide 62

Slide 62 text

個⼈的な結論 個⼈的な結論 いろいろとあって Ruby 2.7.2 ではデフォルトで出なくするという選 択肢を選んだ しかし、今まではデフォルトで警告が出ること前提で運⽤してきた なのでいずれにしろ警告⾃体を出すようにする事⾃体は問題ないは ず その上でどういう⼿段を⽤いて警告を出すようにするのか考えてい く必要がある 他にもいい運⽤の仕⽅を思いついたらどんどんフィードバックして ほしい 個⼈的にはアプリケーションコードの警告は出⼒して、gem の警告 は出⼒しないようにするなど細かい制御をしていきたい warning-gem とか試してみたい いい運⽤⽅法があったら教えて!! いい運⽤⽅法があったら教えて!!

Slide 63

Slide 63 text

まとめ まとめ

Slide 64

Slide 64 text

まとめ まとめ Ruby 3.0.0 preview1 が出たからみんな試してみてね バグとかあったらフィードバックがほしい rbs や typeprof は gem install でシュッと試せるよ! Ruby 2.7.2 から⾮推奨な警告がデフォルトで出なくなるよ どう運⽤していくのか考えるとむずかしい 警告⾃体は問答無⽤で出してしまってしまうのがよいと思う どう運⽤していくのがいいのかフィードバックがほしい Ruby 3.0 はまだ開発中なので実際にリリースされる時に挙動が変わ っている可能性があるので注意しましょう オンライン勉強会は場所を選ばず参加できるので参加し得 今の時期しかできないよ!!

Slide 65

Slide 65 text

ご清聴 ご清聴 ありがとうございました ありがとうございました