6

私はRubyv1.9.2とRubyonRailsv3.2.2gemを使用しています。私は次のモジュールを持っていました

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

つまり、全体で使用できるメソッドModuleを追加するために、クラスを何らかの方法で拡張することを考えました。ただし、それを機能させ、すべてのRubyonRailsアプリケーションで使用できるようにしたいと思います。alias_class_methodMyModule

  1. ModuleクラスのRubyコア拡張子に関連するファイルをどこに置くべきですか?たぶんRubyonRailslibディレクトリにありますか?
  2. Moduleコア拡張ファイルのクラスを適切に「拡張」するにはどうすればよいですか?
  3. 続行するのは正しい方法ですか?つまり、たとえば、別のクラス(、、、、 ...)ではなく「拡張」する必要がObjectありBasicObjectますKernelModule?または、前述のコア拡張機能の実装をまったく避ける必要がありますか?

しかし、もっと重要なのは、クラスを拡張する必要がないように、私が達成しようとしていることを実現するRuby機能がありますか?

4

3 に答える 3

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アプリのイニシャライザーに入れると、準備が整います...

于 2012-10-16T16:57:16.923 に答える
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
于 2013-09-06T21:21:56.173 に答える
1

受け入れられた答えは紛らわしく、機能しませんでした。

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"
于 2015-03-10T07:42:00.353 に答える