0

モジュールの名前だけを使用してサブクラスにアクセスしたいと思います。

module MyModule
    class UselessName
        include OtherModel
        # only self method
        def self.x
        end
    end
    # No other class
end

そして、私は書きたいのですがMyModule.xMyModule::UselessName.x

モジュールをクラスで変換することはできますが、RoRヘルパーを使用しているので、MyModuleをクラスではなくモジュールのままにしておくことをお勧めします。

これを行う方法はありますか?ありがとう ;)

4

2 に答える 2

1

OK、問題を2つに分けましょう-そのようなメソッドのリストを取得し、モジュールでプロキシを作成します。

リストを取得するのは少し難しいかもしれません:

MyModule::UselessName.public_methods(false) - MyModule::UselessName.superclass.public_methods(false)

ここでは、すべてのパブリッククラスメソッドのリストから始めて、そこからすべてのスーパークラスのパブリッククラスメソッドのリストを差し引きます。

ここで、メソッドの名前がわかっていると仮定して、プロキシメソッドを作成する必要があります。

metaclass = class << MyModule; self; end
metaclass.send(:define_method, :x) do |*args, &block|
  MyModule::UselessName.send(:x, *args, &block)
end

このコードは、実行時に次の定義と同等になります。

module MyModule
  def x(*args, &block)
    MyModule::UselessName.send(:x, *args, &block)
  end
end

それでは、簡単な関数にまとめましょう。

def make_proxies(mod, cls)
  methods = cls.public_methods(false) - cls.superclass.public_methods(false)
  metaclass = class << mod; self; end

  methods.each do |method|
    metaclass.send(:define_method, method) do |*args, &block|
      cls.send(method, *args, &block)
    end
  end
end

したがって、必要なモジュールとクラスに対して呼び出す必要があります。「destination」モジュールは、クラスを所有する「source」モジュールとは異なる場合があるため、すべてのメソッドを1つのモジュールにまとめることができます(名前が異なる場合、またはクラス名を使用してプレフィックスを付ける場合)。たとえば、あなたの場合は、次の電話をかけるだけです。

make_proxies(MyModule, MyModule::UselessName)
于 2012-09-19T23:26:25.823 に答える
1

わかりました、私はあなたが意味すると思うことを達成するための非常に汚い方法を見つけました:

module MyModule
  class UselessName
    include OtherModule

    # have whatever you want here
  end

  def self.x
    # whatever
  end
end

だからあなたのコードのどこかであなたはすることができます、そして私はこれを繰り返しますこれは非常に、非常に汚いです!

MyModule.methods(false).each do |m|
  # m = method

  # now you can redefine it in your class
  # as an instance method. Not sure if this
  # is what you want though
  MyModule::UselessName.send(:define_method, :m) do
    # in this NEW (it's not the same) method you can
    # call the method from the module to get the same
    # behaviour
    MyModule.send(m)
  end
end

以前にクラスにあった場合、または例外をスローした場合に、これが同じ名前のインスタンスメソッドを上書きするかどうかはわかりませんが、それを試す必要があります。

私の意見では、アプリのデザインを考え直す必要があります。これは本来あるべき姿ではないためですが、ここで説明します...

于 2012-09-19T23:06:15.890 に答える