简体   繁体   English

alias_method、alias_method_chain 和 self.included

[英]alias_method, alias_method_chain, and self.included

I'm having a little difficulty understanding alias_method / alias_method_chain .我在理解alias_method / alias_method_chain时遇到了一些困难。 I have the following code:我有以下代码:

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

This does exactly what I want to it to - append "with a cherry on top" to the top of any form_for call.这正是我想要的 - append“顶部有樱桃”到任何form_for调用的顶部。

But my understanding is this isn't good code for a few reasons.但我的理解是,由于某些原因,这不是好的代码。 Firstly, it won't chain in any other overrides of form_for(?) so if I were to write a second form_for method which appended "and yet another cherry on top", it wouldn't show.首先,它不会链接form_for(?)的任何其他覆盖,所以如果我要编写第二个form_for方法,它附加了“还有另一个 cherry on top”,它不会显示。 And secondly, alias_method and alias_method_chain are sorta outdated solutions, and I should be using self.included & sending to the module instead.其次, alias_methodalias_method_chain是有点过时的解决方案,我应该使用self.included并改为发送到模块。

But I can't get self.included to call this form_for method - it just keeps calling the parent one.但我无法让self.included调用此form_for方法 - 它只是不断调用父方法。 Here's what I'm trying:这是我正在尝试的:

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)

My above solution works, but I have a suspicion it's the wrong way of doing things.我的上述解决方案有效,但我怀疑这是错误的做事方式。 If any ruby veterans could show me a more elegant way of doing this - and/or why the second solution isn't being called - I'd be appreciative.如果任何 ruby 退伍军人可以向我展示一种更优雅的方法 - 和/或为什么不调用第二种解决方案 - 我将不胜感激。

When you monkey patch something you must redefine the method, because there's no super to inherit from (so you can't use the second code excerpt).当您修补某些东西时,您必须重新定义该方法,因为没有可继承的超级(因此您不能使用第二个代码摘录)。

Copying the current method implementation and adding your own is just asking for trouble, so this is where alias_method comes in.复制当前的方法实现并添加自己的实现只是自找麻烦,所以这就是 alias_method 的用武之地。

alias_method :form_for_without_cherries, :form_for

It actually creates a clone to the original method, which you can use instead of super.它实际上创建了原始方法的克隆,您可以使用它代替 super。 The fact that you can't chain monkey patches is not a bug, it's a feature.你不能链接猴子补丁的事实不是错误,而是一个特性。

The rails alias_method_chain method was indeed deprecated, but only because it was a poor idea from the start. rails alias_method_chain 方法确实被弃用了,但这只是因为它从一开始就是一个糟糕的主意。 However alias_method is a pure ruby method, and when used correctly can provide an elegant way of monkey patching your code, that's why I'm pretty sure it's not going away any time soon.然而,alias_method 是一个纯粹的 ruby 方法,如果使用得当,可以提供一种优雅的猴子修补代码的方法,这就是为什么我很确定它不会很快消失的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM