モジュール内のクラスメソッドにエイリアスを付けるにはどうすればよいですか?
概要
私は 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 の別名を付けたかったのです。そこで、次の(機能しない)コードを記述しました。
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
言い換えれば、MyModule 全体で使用できる alias_class_method メソッドを追加するために、何らかの方法で Module クラスを拡張しようと考えました。ただし、これを動作させ、すべての Ruby on Rails アプリケーションで利用できるようにしたいと考えています。
しかし、より重要なことは、クラスを拡張する必要がないように、私が達成しようとしているものを実現する Ruby の機能はあるのかということです。
解決策
次のように、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アプリのイニシャライザに入れれば準備完了です…