我正在使用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
我希望为类方法 my_method
添加别名。所以,我说了以下( not working )代码:
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
换句话说,我想在某处扩展Module
课程,以便在整个alias_class_method
中添加MyModule
方法。但是,我想在所有Ruby on Rails应用程序中使工作和可用。
Module
类的Ruby核心扩展名中?也许在Ruby on Rails lib
目录?Module
类?Object
,BasicObject
,Kernel
,...)而不是Module
?或者,我是否应该完全避免实施上述核心扩展?但是,更重要,是否有一个Ruby功能可以实现我想要完成的功能,这样我就不必扩展它的类了?
答案 0 :(得分: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"
回答你的评论,你不必手动扩展每一堂课。 define_singleton_method
在Object
类中实现。所以你可以简单地扩展Object
类,所以每个类都应该有可用的方法......
Object.extend(MyModule)
将它放在Rails应用程序的初始化程序中,你应该好好去......
答案 1 :(得分:1)
我在这个网站上找到了答案:http://engineering.lonelyplanet.com/2012/12/09/monitoring-our-applications-ruby-methods/
解决方案是将class_eval
与块一起使用。这样就可以使用封闭范围内的变量。
module Alias
def trigger
@trigger = true
end
def method_added(name)
if @trigger
@trigger = false
with_x = "#{name}_with_x"
without_x = "#{name}_without_x"
define_method(with_x) do
"#{send(without_x)} with x"
end
alias_method without_x, name
alias_method name, with_x
end
end
def singleton_method_added(name)
if @trigger
@trigger = false
with_x = "#{name}_with_x"
without_x = "#{name}_without_x"
define_singleton_method(with_x) do
"singleton #{send(without_x)} with x"
end
singleton_class.class_eval do
alias_method without_x, name
alias_method name, with_x
end
end
end
end
class TestAlias
extend Alias
trigger
def self.foo
'foo'
end
trigger
def bar
'bar'
end
end
TestAlias.foo # => 'singleton foo with x'
TestAlias.new.bar # => 'bar with x'
如果您没有singleton_class
,那么您应该升级您的Ruby版本。如果那是不可能的,你可以这样做:
class Object
def singleton_class
class << self
self
end
end
end
答案 2 :(得分:0)
接受的答案令人困惑,但没有奏效。
class Module
def alias_class_method(new_name, old_name)
define_singleton_method(new_name, singleton_method(old_name))
end
end
module MyModule
def self.my_method
'my method'
end
end
MyModule.alias_class_method(:my_new_method, :my_method)
MyModule.my_new_method # => "my_method"