読者です 読者をやめる 読者になる 読者になる

ゆうなんとかさんの雑記帳的な。

Twitterで踊ったり音ゲーしたりしてるあの名前がよくわからない人が書いてるらしいよ。

メソッドが定義されていないけれどNoMethodErrorが起きない…?

ActiveRecordってdefで明示的にメソッドを定義していないのにメンバーにアクセスすることができますよね。それなのに例外が起きない。これどうなってるんでしょうか?いままで普通に使ってましたが…
ちょっと調べるとこんなメソッドがあるようです。

method_missing(method_id, *args, &block) private
Allows access to the object attributes, which are held in the @attributes hash, as were they first-class methods. So a Person class with a name attribute can use Person#name and Person#name= and never directly use the attributes hash — except for multiple assigns with ActiveRecord#attributes=. A Milestone class can also ask Milestone#completed? to test that the completed attribute is not nil or 0.

It’s also possible to instantiate related objects, so a Client class belonging to the clients table with a master_id foreign key can instantiate master through Client#master.

method_missing (ActiveRecord::Base) - APIdock

適当に訳すとこんな感じです。

method_missing(method_id, *args, &block) private
@属性のハッシュで保持されているオブジェクトの属性に、第一級メソッドとしてアクセスできるようにします。つまり、nameという属性を持ったPersonクラスは、Person#nameとPerson#name=というメソッドがつかえ、さらにActiveRecord#attributes=で複数の値を割り当てる場合をのぞいて属性ハッシュを決して直接使用しません。Milestoneクラスの場合はMilestone#completed?でcompleted属性がnilまたは0でないか確かめることができます。

また、関連オブジェクトのインスタンスを生成することもできます。このため、master_idを外部キーに持ち、clientsテーブルに属するClientクラスは、Client#masterを通してmasterのインスタンスを作成することができます。

メソッドが見つからないときはここに飛ばされて、属性を持っていないか確認する→あればアクセサーを提供する、なければ例外を飛ばす、と言った挙動になるのでしょうか?(まあそうなると今度はその「属性」をどうやって拾ってくるんだという問題になりますが)
今日はこの辺の話があったのでちょっと調べてみました。あとはclass_evalについてなど、割とメタい話が多かった気がします。これが動く理由、気になるんですけど今は追いかける気力がないので今年の終わりがけにでもやってみようと思います。