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,为什么?

randombits asked 2020-01-23T02:06:51Z
4个解决方案
104 votes

1-仍然使用吗?

显然,是的,Rails中仍使用alias_method_chain()(从3.0.0版开始)。

2-什么时候使用   alias_method_chain,为什么?

(注意:以下内容主要基于Paolo Perrotta撰写的元编程Ruby中的alias_method_chain()的讨论,这是一本非常好的书,您应该动手操作。)

让我们从一个基本的例子开始:

class Klass
  def salute
    puts "Aloha!"
  end
end

Klass.new.salute # => Aloha!

现在假设我们想用记录行为包围alias_method_chain()。 我们可以做到Perrotta所谓的around别名:

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

我们定义了一个名为alias_method_chain()的新方法,并将其别名为foo_with_feature()。用于调用foo()的代码仍然有效,但它也获得了新的日志记录行为。 我们还为原始foo_with_feature()定义了一个别名,因此我们仍然可以在不登录的情况下致敬:

Klass.new.salute_without_log # => Aloha!

因此,现在将alias_method_chain()称为foo_with_feature()。如果要记录日志,可以调用foo()foo_with_feature(),它们是同一方法的别名。 困惑? 好!

根据Perrotta的说法,这种环绕别名在Rails中很常见:

再看一下Rails的另一个例子   用自己的方式解决问题。 一些   在以前的版本中,包含了Rails代码   同一习语的许多实例:   在Alias周围(155)用于添加   方法的特点,和旧的   该方法的版本已重命名为   就像是   alias_method_chain().除了   方法名称,每   时间,执行此操作的代码是   总是一样,到处重复   这个地方。 在大多数语言中,您   无法避免这种重复。   在Ruby中,您可以撒一些   元编程魔术对您的影响   模式并将其提取到自己的   方法...因此诞生了   foo_with_feature()

换句话说,您提供了原始方法alias_method_chain()和增强方法foo_with_feature(),最后得到了三种方法:foo()foo_with_feature()foo_without_feature()。前两个包括功能,而第三个不包含功能。 ActiveSupport提供的alias_method_chain()不会到处都复制这些别名,而是为您完成所有别名。

Yaser Sulaiman answered 2020-01-23T02:07:52Z
8 votes

在Rails 5中已弃用alias_method_chain,而建议使用Module#prepend

拉取请求:[https://github.com/rails/rails/pull/19434]

变更日志:[https://github.com/rails/rails/blob/b292b76c2dd0f04fb090d49b90716a0e6037b41a/guides/source/5_0_release_notes.md#deprecations-4]

jokklan answered 2020-01-23T02:08:21Z
5 votes

我不确定它是否在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的补充,允许在每次调用alias_method_chain时交换出SMTP设置。通过调用deliver!,您可以定义一种执行自定义内容的方法deliver!,并在完成后从那里调用deliver_without_switchable_smtp!

alias_method_chain将旧的deliver!别名为您的新自定义方法,因此您的应用程序的其余部分甚至都不知道deliver!现在也可以进行自定义。

tfe answered 2020-01-23T02:08:55Z
3 votes

完全用了吗?

似乎如此。 这是Rails开发人员的普遍做法

什么时候使用alias_method_chain,为什么?

尽管有警告,但alias_method_chain仍然是向现有方法注入功能时使用的主要策略,至少在Rails 2.x中是这样,随后许多人对其进行了扩展。 Yehuda应该从Rails 3.0中删除alias_method_chain,以便从他在Rails票证中的帖子和评论中说出来。 许多扩展程序仍在使用它,这些扩展程序在执行的某些点添加了自定义行为,例如记录器,错误报告器,基准测试,数据注入等。

IMO,最好的替代方法是包括一个模块,这样就可以对委派进行修饰。 (例如,按照本文中的示例4)。 这样,即使您愿意也可以单独更改对象,而不会污染类的方法。 不利的一面是,对于您注入的每个模块,方法查找链都会增加,但是无论如何,这就是模块的作用。

一个非常有趣的问题,将让我们看看其他人对此的看法。

Chubas answered 2020-01-23T02:09:38Z
translate from https://stackoverflow.com:/questions/3695839/ruby-on-rails-alias-method-chain-what-exactly-does-it-do