2015-12-21 53 views
1

我打開HTTParty模組,並使用下面的重新定義在運行時GET和POST類方式:紅寶石重新定義動態類的方法不會出現在包括

define_singleton_method(method_name) do |*args, &block| 
    method = method(method_name) 
    method(hook).call(*args) 
    method.call(*args, &block) 
end 

這裏,hook是另一種方法的名稱HTTParty模塊中。 method_name可以是get或post。

之後,我想包括HTTParty在TestClient的類如下:

class TestClient 
    include HTTParty 
    ... 
end 

但包括GET和POST方法的版本僅原有的。它不應該使用重新定義的方法嗎?

+0

你可以發佈你的周圍'define_singleton_method'更多的環境? 'method','hook'等是指什麼?你怎麼知道你重新定義的方法沒有被調用? –

回答

1

我認爲這是因爲當你做define_singleton_method時,接收者是HTTParty模塊,而不是它所包含的類(當調用define_singleton_method時,它不存在)。所以當你include HTTPartyTestClient,你重新定義的get已經綁定到HTTParty,並調用TestClient不會達到它。但是,如果你沒有HTTParty.get("http://google.com"),你會得到你的重新定義方法:

module HTTParty 
    %i{ get post }.each do |method_name| 
     define_singleton_method(method_name) do |*args, &block| 
     puts "redefined!" 
     end 
    end 
    end 

    class TestClient 
    include HTTParty 
    end 
    TestClient.get("http://google.com") 
    # real GET 
    TestClient.method(:get).source_location 
    # ["/Users/kitkat/.rvm/gems/[email protected]/gems/httparty-0.13.7/lib/httparty.rb", 475] 
    HTTParty.get("http://google.com") 
    # => redefined! 
    HTTParty.method(:get).source_location 
    => ["(irb)", 30] 

這裏是你如何能真正重新定義你的方法:

module HTTParty 
    def self.included(klass)   
     %i{ get post }.each do |method_name| 
     klass.define_singleton_method(method_name) do |*args, &block| 
      puts "redefined!" 
     end 
     end 
    end 
    end 

    class TestClient 
    include HTTParty 
    end 

2.0.0-p576 :058 >  TestClient.get("http://google.com") 
redefined! 
=> nil 
2.0.0-p576 :060 >   TestClient.method(:get).source_location 
=> ["(irb)", 48] 
+0

謝謝你的解釋。當HTTParty模塊被包含在TestClient中時,它的重新定義的方法也應該可以訪問,對嗎?有沒有辦法在TestClient中包含這些方法? – crashstorm

+0

是的,添加到我的答案! –

+0

我還有一些關於擴展問題的問題。 – crashstorm