Подтвердить что ты не робот

Ruby on Rails: alias_method_chain, что именно он делает?

Я пробовал читать через различные сообщения в блоге, которые пытаются объяснить alias_method_chain и причины использовать его, а не использовать. В частности, я обратил внимание на:

http://weblog.rubyonrails.org/2006/4/26/new-in-rails-module-alias_method_chain

и

http://yehudakatz.com/2009/03/06/alias_method_chain-in-models/

Я все еще не вижу практического использования для alias_method_chain. Кто-нибудь сможет объяснить несколько вещей.

1 - он все еще используется?
2 - когда вы используете alias_method_chain и почему?

4b9b3361

Ответ 1

1 - все еще используется?

По-видимому, да, alias_method_chain() все еще используется в Rails (начиная с версии 3.0.0).

2 - когда вы будете использовать alias_method_chain и почему?

( Примечание: следующее в основном основано на обсуждении alias_method_chain() в Метапрограммирование Ruby Паоло Перротта, что является отличной книгой, в которой вы должны получить свои руки.)

Начнем с базового примера:

class Klass
  def salute
    puts "Aloha!"
  end
end

Klass.new.salute # => Aloha!

Теперь предположим, что мы хотим окружить Klass#salute() логическим поведением. Мы можем сделать то, что Perrotta вызывает вокруг псевдонима:

class Klass
  def salute_with_log
    puts "Calling method..."
    salute_without_log
    puts "...Method called"
  end

  alias_method :salute_without_log, :salute
  alias_method :salute, :salute_with_log
end

Klass.new.salute
# Prints the following:
# Calling method...
# Aloha!
# ...Method called

Мы определили новый метод под названием salute_with_log() и перенесили его на salute(). Код, который использовался для вызова salute(), все еще работает, но он также получает новое поведение ведения журнала. Мы также определили псевдоним оригинала salute(), поэтому мы все еще можем приветствовать без регистрации:

Klass.new.salute_without_log # => Aloha!

Итак, salute() теперь называется salute_without_log(). Если мы хотим вести журнал, мы можем назвать либо salute_with_log(), либо salute(), которые являются псевдонимами того же метода. Смущенный? Хорошо!

По словам Перротты, этот тип псевдонима очень распространен в Rails:

Посмотрите на другой пример Rails решая проблему по-своему. Немного версии назад, код Rails содержал многие примеры одной и той же идиомы: Around Alias ​​(155) был использован для добавления функции к методу, и старый версия метода была переименована в что-то вроде method_without_feature(). Помимо имена методов, которые меняли каждый времени, код, который сделал это, был всегда то же самое, дублируется во всем место. На большинстве языков вы не может избежать такого рода дублирования. В Ruby вы можете посыпать некоторые метапрограммирование магии над вашим шаблона и извлечь его в свой собственный метод... и таким образом родился alias_method_chain().

Другими словами, вы предоставляете оригинальный метод foo() и расширенный метод foo_with_feature(), и вы получаете три метода: foo(), foo_with_feature() и foo_without_feature(). Первые два включают функцию, а третья - нет. Вместо дублирования этих псевдонимов все вокруг alias_method_chain(), предоставляемые ActiveSupport, делает все наложение на вас.

Ответ 2

Я не уверен, что он вышел из стиля с Rails 3 или нет, но он все еще активно используется в версиях до этого.

Вы используете его для ввода некоторых функций до (или после) вызывания метода без изменения места, вызывающего этот метод. См. Этот пример:

module SwitchableSmtp
  module InstanceMethods
    def deliver_with_switchable_smtp!(mail = @mail)
      unless logger.nil?
        logger.info  "Switching SMTP server to: #{custom_smtp.inspect}" 
      end
      ActionMailer::Base.smtp_settings = custom_smtp unless custom_smtp.nil?
      deliver_without_switchable_smtp!(mail = @mail)
    end
  end
  def self.included(receiver)
    receiver.send :include, InstanceMethods
    receiver.class_eval do
      alias_method_chain :deliver!, :switchable_smtp
    end
  end
end

Это дополнение к ActionMailer, позволяющее менять параметры SMTP при каждом вызове deliver!. Вызвав alias_method_chain, вы можете определить метод deliver_with_switchable_smtp!, в котором вы делаете свой собственный материал, и вызывать deliver_without_switchable_smtp! оттуда, когда вы закончите.

alias_method_chain добавляет старый deliver! к вашему новому настраиваемому методу, поэтому остальная часть вашего приложения даже не знает, что deliver! теперь тоже делает ваши собственные вещи.

Ответ 4

он вообще используется?

Кажется, так. Это обычная практика среди разработчиков Rails

когда вы используете alias_method_chain и почему?

Несмотря на предупреждения, alias_method_chain по-прежнему остается основной стратегией, используемой при внедрении функциональности существующего метода, по крайней мере, в Rails 2.x, за которым следуют многие люди, расширяющие ее. Yehuda должен удалить alias_method_chain из rails 3.0, чтобы сказать из своих сообщений и комментариев в Rails-билетах. Он по-прежнему используется многими расширениями, которые добавляют пользовательское поведение в определенные моменты выполнения, такие как регистраторы, репортеры ошибок, бенчмаркинг, ввод данных и т.д.

ИМО, лучшей альтернативой является включение модуля, таким образом, у вас есть украшение над делегированием. (Например, следуйте примеру 4 в этот пост). Таким образом, вы можете изменить объекты даже индивидуально, если хотите, без загрязнения методов класса. Недостатком этого является то, что цепочка поиска метода увеличивается для каждого вводимого модуля, но это то, что модули в любом случае.

Очень интересный вопрос, будет смотреть на то, что другие люди думают об этом.