2011-06-28 158 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:你是否因爲我回答你最初問的問題? –

+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的初學者在這裏的,但我有一些可行的解決方案。因此,如果您認爲某些東西不是ruby-esque,請對代碼進行評論。

這個想法是別名你有的方法和undef_method原始方法。這將爲您的所有實例方法創建一個別名。然後你可以有一個method_missing,它可以調用method_dispatched,然後調用實際的方法。

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

相關問題