加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 为什么包含此模块不会覆盖动态生成的方法?

发布时间:2020-12-16 21:37:33 所属栏目:百科 来源:网络整理
导读:我试图通过包含一个模块来覆盖动态生成的方法. 在下面的示例中,Ripple关联向表添加rows =方法.我想调用那个方法,但之后还要做一些额外的事情. 我创建了一个模块来覆盖该方法,认为模块的row =能够调用super来使用现有方法. class Table # Ripple association
我试图通过包含一个模块来覆盖动态生成的方法.

在下面的示例中,Ripple关联向表添加rows =方法.我想调用那个方法,但之后还要做一些额外的事情.

我创建了一个模块来覆盖该方法,认为模块的row =能够调用super来使用现有方法.

class Table

  # Ripple association - creates rows= method
  many :rows,:class_name => Table::Row

  # Hacky first attempt to use the dynamically-created
  # method and also do additional stuff - I would actually
  # move this code elsewhere if it worked
  module RowNormalizer
    def rows=(*args)
      rows = super
      rows.map!(&:normalize_prior_year)
    end
  end
  include RowNormalizer

end

但是,我的新行=永远不会被调用,事实证明,如果我在其中引发异常,则没有任何反应.

我知道该模块已被包含在内,因为如果我把它放入其中,我的异常会被提升.

included do
        raise 'I got included,woo!'
      end

此外,如果不是rows =,则模块定义somethingelse =,该方法是可调用的.

为什么我的模块方法不会覆盖动态生成的模块?

解决方法

我们来做一个实验:
class A; def x; 'hi' end end
module B; def x; super + ' john' end end
A.class_eval { include B }

A.new.x
=> "hi" # oops

这是为什么?答案很简单:

A.ancestors
=> [A,B,Object,Kernel,BasicObject]

B在祖先链中的A之前(您可以将其视为B在A内).因此A.x总是优先于B.x.

但是,这可以解决:

class A
  def x
    'hi'
  end
end

module B
  # Define a method with a different name
  def x_after
    x_before + ' john'
  end

  # And set up aliases on the inclusion :)
  # We can use `alias new_name old_name`
  def self.included(klass)
    klass.class_eval {
      alias :x_before :x 
      alias :x :x_after
    }
  end
end

A.class_eval { include B }

A.new.x #=> "hi john"

使用ActiveSupport(以及Rails),您可以将此模式实现为alias_method_chain(target,feature)http://apidock.com/rails/Module/alias_method_chain:

module B
  def self.included(base)
    base.alias_method_chain :x,:feature
  end

  def x_with_feature
    x_without_feature + " John"
  end
end

更新Ruby 2附带了Module#prepend,它确实覆盖了A的方法,使得这个别名hack对大多数用例来说都是不必要的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读