Как работает этот устаревший метод?

Я пытался понять этот призыв:

deprecate :new_record?, :new?

который использует этот устаревший метод:

   def deprecate(old_method, new_method)
      class_eval <<-RUBY, __FILE__, __LINE__ + 1
        def #{old_method}(*args, &block)
          warn "\#{self.class}##{old_method} is deprecated," + 
                "use \#{self.class}##{new_method} instead"
          send(#{new_method.inspect}, *args, &block)
        end
      RUBY
    end

Я не очень понимаю метапрограммирование, которое здесь используется. Но является ли это просто еще одним способом псевдонимов метода new_record?, так что, по сути, new_record? все еще доступен, но выдает предупреждение при его использовании? Кто-нибудь хочет объяснить, как это работает?


person Hola    schedule 21.06.2009    source источник


Ответы (1)


Итак, здесь происходит то, что вся функциональность old_method была перемещена программистом в new_method. Чтобы оба имени указывали на одну и ту же функциональность, но учитывали устаревание, программист помещает в строку deprecate. Это приводит к тому, что строка, указанная в ‹-RUBY heredoc (http://en.wikipedia.org/wiki/Heredoc), который будет интерпретироваться как код (оцениваемый) на уровне класса. Интерполяции строк работают так же, как и в обычных рубиновых строках.

Тогда код выглядит примерно так (если бы мы расширили метапрограммирование)

class SomeClass
  def new?; true; end

  deprecate :new_record?, :new? # this generates the following code

  def new_record?(*args, &block)
    warn "SomeClass#new_record? is deprecated," + 
            "use SomeClass#new? instead"
    send(:new?, *args, &block)
  end
end

Надеюсь это имеет смысл

person Ben Hughes    schedule 21.06.2009
comment
Да, спасибо. В этом есть смысл. Только одного я до сих пор не понимаю - этого синтаксиса: ‹‹-RUBY, FILE, LINE + 1 Если ‹‹-RUBY запускает heredoc, то что остальное за? Эта часть: FILE, LINE + 1 - person Hola; 21.06.2009
comment
Если я изменю определение с deprecate на: alias_method :new_record?, :new?, будет ли это иметь тот же эффект, что и выше, за исключением того, что я не получу предупреждение? - person Hola; 21.06.2009
comment
насколько мне известно, да. Информация FILE и LINE являются необязательными аргументами позиционирования для class_eval. Если бы они отсутствовали и возникло исключение, обратная трассировка включала бы что-то вроде (eval):3 new_record?. FILE — это текущий исходный файл, а LINE — номер текущей строки, поэтому в случае сбоя трассировка укажет на место, где был определен оператор eval. - person Ben Hughes; 21.06.2009
comment
Я думал, что все после начала heredoc (‹‹-RUBY) будет рассматриваться как часть строки/heredoc. Но я приму ваше объяснение как данность. - person Hola; 21.06.2009
comment
heredocs довольно забавны в рубине. На самом деле они не начинаются до следующей строки. Вы можете делать с ними еще более забавные вещи log.gmarik. info/2007/12/rubys-here-document-heredoc-mini.html (последний пример). - person Ben Hughes; 21.06.2009
comment
Ах вот почему! Спасибо за ссылку. Да, последний пример довольно причудливый :) - person Hola; 21.06.2009
comment
нет проблем. Ruby начинает почти обретать смысл спустя достаточно долгое время, обещаю! - person Ben Hughes; 21.06.2009
comment
Будет разница в использовании alias_method. С alias_method вы получаете два идентичных, но независимых метода. Если вы измените поведение нового метода, он не изменит старый. Но с этой устаревшей реализацией старый метод просто выдает предупреждение и вызывает новый. - person Chuck; 21.06.2009