Я изучаю метапрограммирование в Ruby и просто пытаюсь определить отсутствующие методы с помощью методов method_missing и define_method. Я получаю какое-то неожиданное поведение, и мне интересно, может ли кто-нибудь объяснить это. Вот мой класс:
class X
def method_missing(m, *args, &block)
puts "method #{m} not found. Defining it."
self.class.send :define_method, m do
puts "hi from method #{m}"
end
puts "defined method #{m}"
end
end
Теперь этот код:
x = X.new
x.some_method
puts
x.some_method
puts
puts x
Производит вывод:
method some_method not found. Defining it.
defined method some_method
hi from method some_method
method to_ary not found. Defining it.
defined method to_ary
#<X:0x007fcbc38e5030>
То, что я не получаю, является последней частью: почему Ruby вызывает to_ary в вызове puts? Почему Ruby попытается преобразовать мой объект в массив только для его печати?
У меня Googled вокруг и нашел эти связанные ссылки:
- http://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary/
- http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/
Здесь также рассказывается о методах_имя и to_ary gotchas, но не о том, почему puts будет обращаться к to_ary.
Я также должен отметить, что поведение не меняется, когда я определяю значение to_s, например.
def to_s
"I'm an instance of X"
end
Результат "puts x":
method to_ary not found. Defining it.
defined method to_ary
I'm an instance of X