Я недавно написал кое-что, что могло бы быть полезным, хотя есть некоторые оговорки (см. Ниже).
Вот класс, к которому вы хотите добавить свой крючок:
class Original
def regular_old_method msg
puts msg
end
private
def always_called method_called
puts "'#{method_called.to_s.capitalize}' method's been called!"
end
end
А вот код для добавления этого хука:
class << Original
def new(*args)
inner = self.allocate
outer_name = self.name + 'Wrapper'
outer_class = Class.new do
def initialize inner_object
@inner = inner_object
end
def method_missing method_called, *args
@inner.send method_called, *args
@inner.send :always_called, method_called
end
end
outer_class_constant = Object.const_set(outer_name, outer_class)
inner.send :initialize, *args
outer_class_constant.new inner
end
end
Если вы называете это так ...
o = Original.new
o.regular_old_method "nothing unusual about this bit"
Вы получите следующий вывод:
ничего необычного в этом бите
Вызван метод 'Regular_old_method'!
Этот подход был бы плохой идеей, если бы ваш код проверял имена классов, потому что даже если вы запросили объект класса 'Original', вы получили объект класса 'OriginalWrapper'.
Кроме того, я полагаю, что могут быть и другие недостатки, связанные с «новым» методом, но мои знания о метапрограммировании в Ruby пока еще не настолько велики.