Ruby: запись HTTP-запросов внутри собственного метода

Я пытаюсь настроить запись 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

Проблема в том, что мне нужно было alias_method внутри Net::HTTP класс и определение класса внутри метода не допускается.

Вот определение метода.

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

1 ответ

Решение

С этим подходом вы сразу же столкнетесь с множеством других проблем, поскольку эта конкретная проблема преодолена, но ответьте на поставленный вопрос: alias_method это просто метод класса:

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

вышеупомянутое будет отлично работать. Но ваш код никогда не " смещает " его обратно (восстанавливает оригинальный метод), следовательно, любой последующий вызов Net::HTTP#request в свою очередь вызовет псевдоним.

Чтобы избежать этого, можно установить переменную экземпляра в классе Net::HTTP или как, чтобы сохранить состояние и маршрут к псевдониму или исходному методу.

Sidenote: начиная с Ruby2 мы имеем Module#prepend для этой цели использование такого псевдонима выглядит как наследие.

Другие вопросы по тегам