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,为什么?
1 – 它还在使用吗?
显然是的, alias_method_chain()
仍然在Rails中使用 (从版本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!
现在假设我们想用logging行为来包围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()
的代码仍然有效,但它也获得了新的日志logging行为。 我们还定义了原始salute()
的别名salute()
,所以我们仍然可以在不login的情况下敬礼:
Klass.new.salute_without_log # => Aloha!
所以, salute()
现在被称为salute_without_log()
。 如果我们要logging日志,我们可以调用salute_with_log()
或salute()
,它们是同一个方法的别名。 困惑? 好!
根据Perrotta的说法,这种别名在Rails中非常常见:
看看Rails以自己的方式解决问题的另一个例子。 几个版本之前,Rails代码包含了许多相同习惯用法的实例:使用Around Alias (155)将一个特性添加到一个方法,并且旧版本的方法被重命名为类似
method_without_feature()
。 除了每次更改的方法名称之外,执行此操作的代码始终是相同的,重复遍布整个地方。 在大多数语言中,你无法避免这种重复。 在Ruby中,你可以在你的模式中添加一些元编程魔法,并将其提取到自己的方法中,从而诞生了alias_method_chain()
。
换句话说,您提供了原始方法foo()
和增强方法foo_with_feature()
,并最终提供了三个方法: foo()
, foo_with_feature()
和foo_without_feature()
。 前两个包含该function,而第三个则不包含该function。 ActiveSupport提供的alias_method_chain()
不是全部复制这些别名,而是为您完成所有别名。
我不确定Rails 3是否已经过时了,但在之前的版本中,它仍然是积极使用的。
您可以在调用方法之前(或之后)使用它来注入某些function,而不必修改任何调用该方法的地方。 看到这个例子:
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!
现在也做你的自定义的东西。
在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
它是用在所有?
似乎如此 。 这是Rails开发人员的惯常做法
你什么时候会使用alias_method_chain,为什么?
尽pipe有警告,alias_method_chain仍然是在向现有方法注入function时使用的主要策略,至less在Rails 2.x中,随后是许多人将其扩展。 耶胡达应该从Rails 3.0中删除alias_method_chain,以便在他的post和Rails票据中留言。 它仍被许多扩展使用,这些扩展在执行的某些点添加自定义行为,例如logging器,错误logging器,基准testing,数据注入等。
国际海事组织,最好的select是包括一个模块,因此你有装饰超过委托。 (例如,在本文中按照示例4)。 这样,如果你愿意的话,你甚至可以单独改变对象,而不会污染类的方法。 不利的一面是,你注入的每个模块的方法查找链会增加,但是这就是模块。
非常有意思的问题,会看看别人怎么看。