alias_method, alias_method_chain и self.included

У меня есть небольшие трудности с пониманием alias_method/alias_method_chain, У меня есть следующий код:

module ActionView::Helpers
  module FormHelper

    alias_method :form_for_without_cherries, :form_for

    def form_for(record, options = {}, &proc)
      output = 'with a cherry on top'.html_safe
      output.safe_concat form_for_without_cherries(record, options = {}, &proc)
    end
  end
end

Это делает именно то, что я хочу - добавить "с вишенкой на вершине" к вершине любого form_for вызов.

Но я понимаю, что это не очень хороший код по нескольким причинам. Во-первых, он не будет цепляться в любых других переопределениях form_for(?) так что если бы я написал вторую form_for метод, который добавлен "и еще одна вишня сверху", это не показывало бы. И во-вторых, alias_method а также alias_method_chain Сорта устарели решения, и я должен использовать self.included и отправка в модуль вместо.

Но я не могу получить self.included называть это form_for метод - он просто продолжает вызывать родительский. Вот что я пытаюсь:

module CherryForm
  def self.included(base)
    base.extend(self)
  end

  def form_for(record, options = {}, &proc)
    output = 'with a cherry on top'.html_safe
    output.safe_concat super(record, options = {}, &proc)
  end 
end

ActionView::Helpers::FormHelper.send(:include, CherryForm)

Мое вышеупомянутое решение работает, но у меня есть подозрение, что это неправильный способ действий. Если бы какие-нибудь ветераны рубина могли показать мне более изящный способ сделать это - и / или почему второе решение не вызывается - я был бы благодарен.

1 ответ

Решение

Когда вы что-то исправляете, вы должны переопределить метод, потому что нет супер-объекта для наследования (поэтому вы не можете использовать второй фрагмент кода).

Копирование текущей реализации метода и добавление вашей собственной просто вызывает проблемы, так что здесь вступает alias_method.

alias_method :form_for_without_cherries, :form_for

Это фактически создает клон к оригинальному методу, который вы можете использовать вместо super. Тот факт, что вы не можете связать патчи обезьяны, это не ошибка, это особенность.

Метод rails alias_method_chain действительно устарел, но только потому, что с самого начала это была плохая идея. Тем не менее, alias_method - это чистый метод ruby, и при правильном использовании он может обеспечить элегантный способ обезопасить ваш код, поэтому я уверен, что он не исчезнет в ближайшее время.

Другие вопросы по тегам