Это типичный шаблон реализации для внутренних DSL в Ruby: вы передаете объект блоку, который затем сам принимает новые вызовы и блоки методов и, таким образом, направляет интерфейс. (На самом деле, это довольно распространено и в Java, где он используется для получения значимого завершения кода для внутренних DSL.)
Вот пример:
def respond_to
yield FormatProxy.new(@responders ||= {})
end
class FormatProxy
def initialize(responders)
@responders = responders
end
def method_missing(msg, *args, &block)
@responders[msg] = [args, block]
end
end
Теперь у вас есть отображение форматов на исполняемые фрагменты кода, хранящиеся в @responders
, и вы можете вызывать его позже и в другом месте, когда угодно и как угодно часто:
respond_to do |f|
f.myformat { puts 'My cool format' }
f.myotherformat { puts 'The other' }
end
@responders[:myformat].last.call # => My cool format
@responders[:myotherformat].last.call # => The other
Как я намекал выше, если вместо тупого прокси-объекта, который просто использует method_missing
, вы должны использовать тот, который имеет самые важные методы (xml
, html
, json
, rss
, atom
и т. Д.) Предопределенная, достаточно интеллектуальная IDE может даже дать вам значимое завершение кода.
Примечание: я абсолютно не знаю, так ли это реализовано в Rails, но как бы оно ни было реализовано, вероятно, это какой-то вариант.