Sendagaya.rb #135
Sendagaya.rb #135に行って来た。今日も前半は『メタプログラミングRuby 第2版』を読んで、後半はRails 5のチェンジログからActive Record 5.0.0.beta1のチェンジログを眺めていた。
メタプログラミングRuby Refinements
今日は「2.4.2 メソッドの実行」から「2.4.3 Refinements」まで。
メソッドの実行では他の言語から来るとprivateとかに戸惑うよねとか、protectedって何に使うんだろうねという話をした。
お次はいよいよRefinements。
class MyClass
def my_method
"original my_method"
end
def anothor_method
my_method
end
end
module MyClassRefinements
refine MyClass do
def my_method
"refined my_method"
end
end
end
using MyClassRefinements
MyClass.new.my_method # => "refined my_method"
MyClass.new.another_method # => "original my_method"
この最後の行は驚かないだろうか。僕は驚いた。
この挙動を本では
Refinementsが有効になっているコードは、(略)インクルードやプリペンドしたモジュールのコードよりも優先される。
と説明している。しかしこれだけで、メソッド探索の順番を覚えられるだろうか。@tkawaさんの説明が素晴らしかった。
- クラスやインクルードやプリペンドを考慮するより先に、まずRefinementsを探す
- 次に通常のメソッド探索手順に従って、プリペンドされた物、インクルードした物、特異クラス、クラス……とメソッドを探す
ということだ。上の例で言うと、まずmy_methodを呼ぶ場合
- Refinementsを探す
MyClassRefinementsが見付かるmy_methodが定義されているMyClassRefinements#my_methodを呼ぶ
で、結果は"refined my_method"になる。一方another_methodは
- Refinementsを探す
MyClassRefinementsが見付かるanother_methodは定義されていない- Refinementsの探索は終わり、今後二度と探索されない
- プリペンドされたモジュールやインクルードされたモジュールを探すが、ない
- クラスを見る
MyClassであるanother_methodが定義されているanother_methodを実行するmy_methodが呼ばれている- Refinementsの探索は終わっているので、クラスの
my_methodが見付かる MyClass#my_methodを実行する
ということで、結果が"original my_method"になる、というわけだ。
子の説明を聞いて僕は「あ。」と声が漏れるくらい腹に落ちた。
Active Record 5.0.0.beta1チェンジログ
その後もちょいちょいRefinementsと遊んでからはActive Record 5.0.0.beta1のチェンジログをざっと流しながら気になった所で止めて、あーだこーだ言っていた。結構RDBMSの個別機能に対応していたり、細かなユースケースを拾ったりしていて、「Active Recordは基本は既に成熟しているんだろうなあ」という感想を持った。
次回は『メタプログラミングRuby』読むほか、fukajunさんがElectronについての発表をしたいということなのでそれは聞けるはずだ。あとはその場で決まるんだろう。その場で決まるので、聞きたいことを持って行けば、聞けると思う。
次回分もすぐさまイベントが作られて、申し込める。
https://sendagayarb.doorkeeper.jp/events/38655