Ruby: 在自定义方法中记录 HTTP 请求

Ruby: Recording HTTP requests inside a custom method

我正在尝试自定义记录 http 请求。这个想法是定义一个记录请求的函数。

recorded :get, :post, :patch, :delete do
  Net::HTTP.get(URI('http://www.google.com')) #will log
end

Net::HTTP.get(URI('http://news.ycombinator.com')) # will not log

问题是我需要在 Net::HTTP class 中 alias_method 并且不允许在方法中定义 class。

这是方法定义。

require 'net/http'

def recorded(*methods, &block)
  # module Net
  #   class HTTP
  #     alias_method(:orig_request, :request) unless method_defined?(:orig_request)
  #     alias_method(:orig_connect, :connect) unless method_defined?(:orig_connect)
  #
  #     def request(req, body = nil, &block)
  #       if started?
  #         puts :started
  #       end
  #
  #       @response = orig_request(req, body, &block)
  #       puts @response.code
  #       # LOGGING HERE THE REQUEST
  #
  #       @response
  #     end
  #
  #     def connect
  #       orig_connect
  #     end
  #   end
  # end

  yield block
end

当您克服了这个特定问题时,您会立即遇到许多其他问题,但回答问题:alias_method 只是一个 class 方法:

Net::HTTP.alias_method(:orig_request, :request)

以上内容将完美运行。但是你的代码永远不会“dealiases”它回来(恢复原始方法,)因此任何后续调用 Net::HTTP#request 将依次调用 别名版本。

为了避免这种情况,可以在 class Net::HTTP 上设置一个实例变量,或者类似的,以保持状态和路由到别名方法或原始方法。

旁注: 自从 Ruby2 我们有 Module#prepend 用于此目的,使用这种别名方法看起来像遗留的。