2017-11-22 9 views
0

net/httpにパッチを適用しようとしていて、1つのサービスクラスにのみ適用されています。洗練された方法があるようです。下のサルパッチは機能しますが、洗練されていません。これは名前空間の問題ですか?このプロジェクトは、Ruby 2.3.0で動作していますが、2.4.1でも試してみました。サルのパッチだけが適用されるようです。モンキーパッチで詳細と名前空間

module NetHttpPatch 
    refine Net::HTTPGenericRequest do 
    def write_header(sock, ver, path) 
     puts "refined!" 
     # patch stuff... 
    end 
    end 
end 

class Service 
    using NetHttpPatch 
end 

Service.new.make_request 
# :(

UPDATE:

module Net 
    class HTTPGenericRequest 
    def write_header(sock, ver, path) 
     puts "monkey patched!" 
     # patch stuff... 
    end 
    end 
end 

Service.new.make_request 
# monkey patched! 

洗練された

これは賢明同様の範囲であると思われますか? net/httpがリクエストを行うと、明らかにもっと複雑なことが起きています。

module TimeExtension 
    refine Fixnum do 
    def hours 
     self * 60 
    end 
    end 
end 

class Service 
    using TimeExtension 

    def one_hour 
    puts 1.hours 
    end 
end 

puts Service.new.one_hour 
# 60 

のUPDATE UPDATE:

NVM、私は今何が起こっているかを見る:)ミックスインがどのように働くかとまでusingの混合からあなたの脳を維持する必要があります。

module TimeExtension 
    refine Fixnum do 
    def hours 
     self * 60 
    end 
    end 
end 

class Foo 
    def one_hour 
    puts 1.hours 
    end 
end 


class Service 
    using TimeExtension 

    def one_hour 
    puts 1.hours 
    end 

    def another_hour 
    Foo.new.one_hour 
    end 
end 

puts Service.new.one_hour 
# 60 
puts Service.new.another_hour 
# undefined method `hours' for 1:Fixnum (NoMethodError) 

答えて

2

これは、名前空間の問題ですか?

これは範囲の問題です。 Refinements are lexically scoped:当初

class Service 
    using NetHttpPatch 
    # Refinement is in scope here 
end 

# different lexical scope, Refinement is not in scope here 

class Service 
    # another different lexical scope, Refinement is *not* in scope here! 
end 

、すなわちリファインメントは、スクリプトの全体の残りの範囲にあった、唯一main::using、スクリプトスコープであったがありました。 Module#usingは後で来て、洗練を語彙クラス定義体にスコープします。

+0

新しいインスタンスから呼び出されたときに詳細を追加する、より簡単な例で質問を更新しました。何か不足している可能性があります:) – kreek