Slide 1

Slide 1 text

銀座Rails#25@ リンクアンドモチベーション 銀座Rails#25@ リンクアンドモチベーション Proc#using 感想戦 Proc#using 感想戦

Slide 2

Slide 2 text

⾃⼰紹介 ⾃⼰紹介 名前:osyo Twitter : github : ブログ : 趣味で Ruby にパッチを投げたり bugs.ruby で気になったチケットを ブログにまとめたりしてる Ruby で⼀番好きな機能は Refinements @pink_bangbi osyo-manga Secret Garden(Instrumental)

Slide 3

Slide 3 text

今⽇のお題 今⽇のお題 の の Proc#using について語る Proc#using について語る Magic is organizing chaos Magic is organizing chaos

Slide 4

Slide 4 text

そもそも Refinements 使ってる? そもそも Refinements 使ってる?

Slide 5

Slide 5 text

Refinements とは Refinements とは 特定のコンテキストでのみクラス拡張を適⽤する構⽂ 通常のモンキーパッチとは違い名前衝突の危険性を最⼩限に抑え、 安全にクラス拡張する事ができる module Twice # String に新しいメソッドを定義する # これだけでは定義されない refine String do def twice self + self end end end # using を呼び出したコンテキストでのみメソッドが適⽤される using Twice p "homu".twice # => "homuhomu"

Slide 6

Slide 6 text

Proc#using って? Proc#using って?

Slide 7

Slide 7 text

Proc#using とは Proc#using とは Proc#using は任意のブロックに対して using を⾏う機能になる これを利⽤することで任意のブロック内でのみメソッド拡張を適⽤ する事ができる # これを using したコンテキストのみ Proc#using が利⽤できる using Proc::Refinements block = proc { p "homu".twice } # ブロックに対して using を⾏うと # そのブロック内で Twice が適⽤される block.using Twice block.call # => "homuhomu"

Slide 8

Slide 8 text

Proc#using を利⽤するとメソッドに渡したブロック内で暗黙的にク ラス拡張を適⽤する事ができる # ブロックに対して任意の Refinements を適⽤できる def benri(&block) block.using Twice block.call end using Proc::Refinements # ブロック内で独⾃のメソッド拡張が呼べる benri { p "homu".twice p "mami".twice.twice } # ブロックの外では使えない # error: : undefined method `twice' for "mado":String (NoMethodError) p "mado".twice

Slide 9

Slide 9 text

Proc#using の気になるところ!!! Proc#using の気になるところ!!!

Slide 10

Slide 10 text

Proc#using 感想 Proc#using 感想 Refinements は using とワンセットで使う機能になる ユーザは明⽰的に『どの拡張を⾏うのか』を指定して使う ⼀⽅で Proc#using の場合は using するモジュールが定義側で隠蔽さ れてしまう ブロックを書くユーザ側ではどのモジュールが拡張されるのか不 透明になる それはユーザの意図しないメソッドが呼び出される可能性があるの で危険なのではないだろうか 個⼈的にはユーザ側でどのモジュールが適⽤されるのかを明⽰化し たい # ブロック内で何が using されているのかがわからない… benri { p "homu".twice }

Slide 11

Slide 11 text

じゃあ Proc#using いらない? じゃあ Proc#using いらない?

Slide 12

Slide 12 text

どちゃくそほしい!!!! どちゃくそほしい!!!!

Slide 13

Slide 13 text

そもそも そもそも ブロック内のコンテキストが変わってしまうのは instance_eval を使 ったときでも同じ ブロック内で self が変わってしまうことはよくある なので Proc#using で呼び出されるメソッドが意図しない云々は今更 感がある どうしても気になるなら Proc#using を使って便利メソッドを定義す ればいい # Proc#using を使ったヘルパメソッドを定義してやる def using_local(mod, &block) block.using mod block.call end using Proc::Refinements # モジュールを渡して using を明⽰化する using_local(Twice) { p "homu".twice }

Slide 14

Slide 14 text

仮に using_local みたいなメソッドがあったとしてもメソッド内で隠 蔽されてしまえば結局 Proc#using と同じ問題に突き当たる Proc#using だけを⾒ると使い⽅に関して気になる点はあるが利便性 を考えるとめっちゃほしい!!! def benri(&block) # ブロック内で using_local を経由してブロックが呼びされたら # 結局使う側からはどのモジュールが using されるのかは不透明になる using_local(Twice, &block) end # 結局どのモジュールが適⽤されているのかがわからない benri { p "homu".twice p "mami".twice.twice }

Slide 15

Slide 15 text

今後こうなってほしい!! 今後こうなってほしい!!

Slide 16

Slide 16 text

1. Proc#using が⼊る 1. Proc#using が⼊る

Slide 17

Slide 17 text

2. みんなカジュアルに 2. みんなカジュアルに Refinements を使い始める Refinements を使い始める

Slide 18

Slide 18 text

3. Refinements のエッジケース 3. Refinements のエッジケース のバグが炙り出される のバグが炙り出される

Slide 19

Slide 19 text

4. がんばってバグが修正される 4. がんばってバグが修正される

Slide 20

Slide 20 text

5. どんどん Refinements がよく 5. どんどん Refinements がよく なる なる

Slide 21

Slide 21 text

6. 幸せな世界が待っている 6. 幸せな世界が待っている

Slide 22

Slide 22 text

まとめ まとめ

Slide 23

Slide 23 text

まとめ まとめ Proc#using ⾃体に関しては書き⽅や使い⽅に関してちょっと気にな る部分がある が、それ以上に Proc#using 便利なのでほしい!!! Proc#using に関しては結構省いた部分があるので詳しくは元のセッ ションを⾒てください Refinements どちゃくそ便利なのでみんなどんどん Refinements を使 ってくれー!! あとバグがあったらどんどん報告してくれー!!!

Slide 24

Slide 24 text

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