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