改进和命名空间

Refinements and namespaces

正在尝试修补 net/http 并使其仅适用于一项服务 class。改进似乎是要走的路。下面的猴子补丁有效,但细化无效。这是命名空间问题吗?该项目在 ruby 2.3.0 上,但也尝试过 2.4.1,但似乎只应用了猴子补丁。

有猴子补丁:

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

Service.new.make_request
# monkey patched!

经过细化:

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
# :(

更新:

这似乎是相似的范围?显然,当 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

更新更新:

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)

Is this a namespace issue?

这是一个范围问题。 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 稍后出现,它将 Refinement 限定为词法 class 定义体。