Несколько очевидный: всегда переопределяйте respond_to?
, если Вы переопределяете method_missing
. Если method_missing(:sym)
работы, respond_to?(:sym)
должны всегда возвращать true. Существуют многие библиотеки, которые полагаются на это.
Позже:
пример:
# Wrap a Foo; don't expose the internal guts.
# Pass any method that starts with 'a' on to the
# Foo.
class FooWrapper
def initialize(foo)
@foo = foo
end
def some_method_that_doesnt_start_with_a
'bar'
end
def a_method_that_does_start_with_a
'baz'
end
def respond_to?(sym, include_private = false)
pass_sym_to_foo?(sym) || super(sym, include_private)
end
def method_missing(sym, *args, &block)
return foo.call(sym, *args, &block) if pass_sym_to_foo?(sym)
super(sym, *args, &block)
end
private
def pass_sym_to_foo?(sym)
sym.to_s =~ /^a/ && @foo.respond_to?(sym)
end
end
class Foo
def argh
'argh'
end
def blech
'blech'
end
end
w = FooWrapper.new(Foo.new)
w.respond_to?(:some_method_that_doesnt_start_with_a)
# => true
w.some_method_that_doesnt_start_with_a
# => 'bar'
w.respond_to?(:a_method_that_does_start_with_a)
# => true
w.a_method_that_does_start_with_a
# => 'baz'
w.respond_to?(:argh)
# => true
w.argh
# => 'argh'
w.respond_to?(:blech)
# => false
w.blech
# NoMethodError
w.respond_to?(:glem!)
# => false
w.glem!
# NoMethodError
w.respond_to?(:apples?)
w.apples?
# NoMethodError
Если можно ожидать имена методов, лучше динамично объявить их, чем полагаться на method_missing, потому что method_missing подвергается потере производительности. Например, предположите, что Вы хотели расширить дескриптор базы данных, чтобы быть в состоянии получить доступ к представлениям базы данных с этим синтаксисом:
selected_view_rows = @dbh.viewname( :column => value, ... )
Вместо того, чтобы полагаться на method_missing на дескрипторе базы данных и отправить имя метода базе данных как название представления, Вы могли определить все представления в базе данных загодя, затем выполнить итерации по ним для создания "viewname" методов на @dbh.
Построение точка Pistos : method_missing
, по крайней мере, порядок величины медленнее, чем обычный метод, обращающийся ко всем реализациям Ruby, которые я попробовал. Он прав ожидать, если это возможно, для предотвращения вызовов к method_missing
.
, Если Вы чувствуете себя предприимчивыми, проверьте Ruby, малоизвестный класс Delegator .