2011-06-28 6 views
0

私は、次のしている:メソッドディスパッチの直後で、メソッドが呼び出される前にメソッドを実行する方法はありますか?

class Foo 
    def bar 
    puts "#{__method__} was called and found within #{self}" 
    end 

    def method_missing(meth, *args, &blk) 
    puts "#{meth} was called and was not found within #{self}" 
    end 
end 

foo = Foo.new 
foo.bar 
# => bar was called and found within #<Foo:0x100138a98> 
foo.baz 
# => baz was called and was not found within #<Foo:0x100138a98> 

私は方法が発見された場合、メソッドディスパッチは、ビットそうのようになっていることを前提としています

foo.bar was asked to be called 
Search methods defined within #<Foo:0x100138a98> 
Method `bar` found 
Call the `bar` method 

見つからないメソッドのために:

foo.baz was asked to be called 
Search methods defined within #<Foo:0x100138a98> 
Method `baz` not found 
Search methods defined within the parent of #<Foo:0x100138a98> 
Method `baz` not found 
And so on until it hits the parent that has no parent 
Loop back around and see if #<Foo:0x100138a98> has a `method_missing` method defined 
Method `method_missing` found 
Call the `method_missing` method 

私はこのようにステップしたいと思います:

foo.bar was asked to be called 
Search methods defined within #<Foo:0x100138a98> to see it has a `method_dispatched` method 
Method `method_dispatched` found 
Calling `method_dispatched` 
Search methods defined within #<Foo:0x100138a98> 
... 

これにより、開発者は以下のような何かをできるようになる:

class Foo 
    def bar 
    puts "#{__method__} was called and found within #{self}" 
    end 

    def method_missing(meth, *args, &blk) 
    puts "#{meth} was called and was not found within #{self}" 
    end 

    def method_dispatched(meth, *args, &blk) 
    puts "#{meth} was called within #{self}..." 
    puts "continuing with the method dispatch..." 
    end 
end 

foo = Foo.new 
foo.bar 
# => bar was called within #<Foo:0x100138a98>... 
# => continuing with the method dispatch... 
# => bar was called and found within #<Foo:0x100138a98> 
foo.baz 
# => bar was called within #<Foo:0x100138a98>... 
# => continuing with the method dispatch... 
# => baz was called and was not found within #<Foo:0x100138a98> 

これは質問に私をもたらします。..

これは可能ですか?

+1

クラスとその親だけではなく、メソッドを見つける方法があります。 http://blog.rubybestpractices.com/posts/gregory/030-issue-1-method-lookup.html – Jeremy

+0

@ c00lryguy:あなたが私に答えたので私にdownvotingしていますか?最初に尋ねた質問ですか? –

+0

それはちょうど質問に関連していませんでした。私はタイトルを変更しました。あなたがタイトルを読んで、その本文をスキップして答えたようでした。 – RyanScottLewis

答えて

0

私はあなたが探しているもののコールバックを認識していません。 Ruby Delegatorsで、私が下に描いたものよりもエレガントな可能な解決法を読んでいます。

オブジェクトをラップし、method_missingで代行受信することができます。

class A 
    def foo 
    puts "hi there, I'm A" 
    end 
end 

maybe have B inherit A? 
class B 
    def initialize 
    @a = A.new 
    end 

    def method_missing(m, *args, &block) 
    puts "hi there, I'm in B" 
    @a.send(m, *args, &block) if @a.respond_to? m 
    puts "all done" 
    end 
end 
0

ここでRubyの初心者を選んでください。しかし、私はいくつかの解決策があります。だから何かがルビーエスクではないと思うなら、コードにコメントしてください。

あなたが持っているメソッドのエイリアスを作成し、元のメソッドをundef_methodすることです。これにより、すべてのインスタンスメソッドのエイリアスが作成されます。次に、method_dispatchedを呼び出してから実際のメソッドを呼び出すことができるmethod_missingを作成できます。

class Test 
     def foo 
       "foo" 
     end 

     def method_dispatched(meth, *args, &blk) 
       puts "#{meth} was called within #{self}..." 
       puts "continuing with the method dispatch..." 
     end 

     def method_missing(name, *args, &block) 
       method_dispatched(name, args, block) #Calls your standard dispatcher 

       if (respond_to?('_' + name.to_s)) # Check if we have a aliased method 
         send('_' + name.to_s) 
       else 
         "undef" #Let the caller know that we cant handle this. 
       end 
     end 

     instance_methods(false).each do |meth| 
       if meth != 'method_missing' and meth != 'method_dispatched' 
         alias_method "_#{meth}", meth 
         remove_method(meth) 
       end 
     end 

end 

t = Test.new 
puts t.foo() 
puts t.undefined_method() 
+0

ちょうど好奇心。これを試してみる機会がありましたか? – rajasaur

関連する問題