2016-06-27 3 views
-3

で定義されていないメソッドを呼び出すメソッドは、特別なクラスとして定義された外部APIを使用しています。ほとんどの標準メソッドはxmlの構築に使用するために未定義です。ここで、#method_missingは、オブジェクト上で呼び出された欠落したメソッド名に基づいて要素を生成します。ruby​​

は、基本的にはクラス本体での効果に何かがある:

undef_method :send 

は今、私はプログラム的に名前でメソッドを呼び出したいです。私はeval "obj.#{something}"を使うことができると思うが、私は本当に好きではないeval。 メソッド#sendの未定義を元に戻すための暗部テクニックがあるはずですので、別名#__send__にエイリアスして再度定義解除することができます。そうすれば、evalなしで名前でメソッドを呼び出すことができます。例えばobj.__send__(:something, params)

だから私の質問は、#sendの方法を元に戻すために猿のパッチを適用することです。そのようなことは何も見つかりません。誰もそれについて尋ねることさえできません。

更新:私の元の問題は、とにかく方法#__send__があるので問題ではなかったが、私は#sendしか知りませんでした。問題のもう一つの部分は、未定義の方法を復元する方法でした。 @philomory asnwerの助けを借りて、ここで私が持っているものです:

[46] pry(#<CucuShift::DefaultWorld>)> class A 
[46] pry(#<CucuShift::DefaultWorld>)* def gah 
[46] pry(#<CucuShift::DefaultWorld>)*  puts "gah" 
[46] pry(#<CucuShift::DefaultWorld>)* end 
[46] pry(#<CucuShift::DefaultWorld>)* end 
=> :gah 
[49] pry(#<CucuShift::DefaultWorld>)> class C < A 
[49] pry(#<CucuShift::DefaultWorld>)* undef_method :gah 
[49] pry(#<CucuShift::DefaultWorld>)* end 
=> C 
[50] pry(#<CucuShift::DefaultWorld>)> C.new.gah 
NoMethodError: undefined method `gah' for #<C:0x000000070d7918> 
[57] pry(#<CucuShift::DefaultWorld>)> class C 
[57] pry(#<CucuShift::DefaultWorld>)* define_method :fff , A.instance_method(:gah) 
[57] pry(#<CucuShift::DefaultWorld>)* end 
=> :fff 
[58] pry(#<CucuShift::DefaultWorld>)> C.new.fff 
gah 
+0

私は混乱している:私はあなたがBasicObjectせずにルビーの以前のバージョンを使用している場合と仮定し、けれども__send__あなたはそれがこの方法を行いますか? –

+0

愚かな書式設定 - 私は '#__ send__'メソッドがあることを知らなかったので、私は' __send__'を –

+0

@FrederickCheungと意味しました。私は '#send'しか知りませんでした。私は否定的な質問の評価を説明すると思います。本当に悪いドキュメント、とにかく、あなたに感謝します。 – akostadinov

答えて

2

あなたが探している暗黒魔法はUnboundMethodクラスです。 (objがあなたのビルダーAPIオブジェクトであると仮定して)このようにそれを使用してください:もちろん

send_method = BasicObject.instance_method(:__send__) 
bound_method = send_method.bind(obj) 
bound_method.call(:method_you_are_calling_dynamically,*arguments) 

、あなたが達成しようとしているものに応じて、あなたはちょうどあなたがしたい具体的な方法を得ることができると

のように、それを直接バインド
id_method = BasicObject.intance_method(:__id__) 
bound_method = id_method.bind(obj) 
bound_method.call 

または、ビルダークラスはmethod_missingを使用しているし、あなただけの動的それに派遣したい場合は、まったく同じようsendか何かを必要としない、ちょうどobj.method_missing(:my_dynamic_method_name)


0を呼び出します

UPDATE:

それはあなたがすでにBasicObjectの一部として提供されて__send____send__ようにエイリアスsendする必要はありませんということは注目に値しますし、それを国連が、定義するために、それは非常に珍しいです。 - なぜあなたは__send__呼び出すことはできません

def obj.__send__(*args,&blk) 
    Object.instance_method(:send).bind(self).call(*args,&blk) 
end 
+0

ええと、箱からすぐに '#__ send__'メソッドがあることを知りませんでした。同じことをする '#send'メソッドを常に使いました。私の悪い! – akostadinov

+0

FYI Ruby 2.2で動作する 'BasicObject.instance_method(:__ send __)'は表示されません。できるだけ修正すると便利です。回答は、ソリューションとしてマークしても機能します。 – akostadinov

+0

2.2.2で試してみましたが、うまくいきました。どのようなエラーが表示されますか?私が書いた最初のメソッドは、実際に 'send'や' __send__'というメソッドを返すわけではありません。彼らはあなたが直接 'obj.send'または' obj .__ send__'を書いているのと同じです。 – philomory