前回(ActiveRecord::Base#find(_by_id)? のお話)の続きのような。

あと、ちゃんとソース読んでないのでなんですが、「find_by_XXX」系メソッドは内部でmethod_missingを呼んでるとかいう話なので、当然ただのfindよりオーバヘッドがかかります(特にRuby 1.9系)。なんでもfind_by_idに置き換えるべきではないでしょう。

って書いたんだけど、たまたま当該箇所のソースを張ってらっしゃる方を見かけた。

……method_missing自体のオーバヘッドに加えて、class_eval までしてるし……(w Railsの黒魔術の恐ろしさの一環を垣間見ました。

で、ところどころ、なんかraiseのように使われているsuperが気になった。method_missingの中で呼んでるのはどういうこと?

以下、適当に試す。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def method_missing(meth_id, *args)
  if match = /^power(\d+)$/.match(meth_id.to_s)
    $1.to_i ** 2
  else
    super
  end
end
#=> nil
 
power2
#=> 4
 
power10
#=> 100
 
hoge
#=> NameError: undefined local variable or method `hoge' for main:Object
#        from (irb):12:in `method_missing'
#        from (irb):20
#        from :0

メソッドが無いときのデフォルトの挙動、NameError が出る。

アレか。method_missingはもともと、NameErrorraiseするだけのメソッドとして定義されていて、それをオーバーライドしてるイメージ? なの?

そうでした。

ソースでも、多分そんな感じ。rb_eNameErrorが確かに呼ばれてるみたい。

「マニュアルちゃんと読め。ソース読め。」という結論になりそうな。

Ruby技術者認定試験 公式ガイド (ITpro BOOKs)

著者/訳者:伊藤忠テクノソリューションズ

出版社:日経BP社( 2009-03-25 )

単行本(ソフトカバー) ( 256 ページ )


↑、「いつか受ける」と思って早半年……。