如何在模块中对类方法进行别名?

Bac*_*cko 6 ruby metaprogramming ruby-on-rails core extending

我正在使用Ruby v1.9.2和Ruby on Rails v3.2.2 gem.我有以下模块

module MyModule
  extend ActiveSupport::Concern

  included do
    def self.my_method(arg1, arg2)
      ...
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我想为类方法 添加别名my_method.所以,我说了以下(不工作)代码:

module MyModule
  extend ActiveSupport::Concern

  included do
    def self.my_method(arg1, arg2)
      ...
    end

    # Note: the following code doesn't work (it raises "NameError: undefined
    # local variable or method `new_name' for #<Class:0x00000101412b00>").
    def self.alias_class_method(new_name, old_name)
      class << self
        alias_method new_name, old_name
      end
    end

    alias_class_method :my_new_method, :my_method
  end
end
Run Code Online (Sandbox Code Playgroud)

换句话说,我想在Module某种程度上扩展这个类,以便添加一个alias_class_method可用的方法MyModule.但是,我想让它工作并在我的所有Ruby on Rails应用程序中可用.

  1. 我应该把文件放在与Module类的Ruby核心扩展相关的文件中?也许在Ruby on Rails lib目录中?
  2. 我应该如何正确地"扩展" Module核心扩展文件中的类?
  3. 这是正确的方法吗?也就是说,例如,要我"扩展"另一个类(Object,BasicObject,Kernel,...),而不是Module?或者,我是否应该完全避免实施上述核心扩展?

但是,更重要的是,是否有一个Ruby功能可以实现我想要完成的功能,这样我就不必扩展它的类了?

Vap*_*ire 3

您可以使用define_singleton_method新名称来包装旧方法,如下所示:

module MyModule
  def alias_class_method(new_name, old_name)
    define_singleton_method(new_name) { old_name }
  end
end

class MyClass
  def my_method
    puts "my method"
  end
end

MyClass.extend(MyModule)
MyClass.alias_class_method(:my_new_method, :my_method)
MyClass.my_new_method     # => "my method"
Run Code Online (Sandbox Code Playgroud)

回答您的评论,您不必手动扩展每个类。这define_singleton_method是在Object班级中实施的。所以你可以简单地扩展Object类,所以每个类都应该有可用的方法......

Object.extend(MyModule)
Run Code Online (Sandbox Code Playgroud)

将其放入 Rails 应用程序的初始化程序中,您应该可以开始了...