Работа над небольшим скриптом на Ruby, который выходит в Интернет и сканирует различные сервисы. У меня есть модуль с несколькими классами внутри:
module Crawler
class Runner
class Options
class Engine
end
Я хочу поделиться одним регистратором среди всех этих классов. Обычно я просто помещаю это в константу в модуле и ссылаюсь на это так:
Crawler::LOGGER.info("Hello, world")
Проблема в том, что я не могу создать свой экземпляр регистратора, пока не узнаю, куда идет вывод. Вы запускаете сканер через командную строку, и в этот момент вы можете сказать, что хотите запустить в разработке (вывод журнала идет в STDOUT) или в производственном процессе (вывод журнала идет в файл crawler.log):
crawler --environment=production
У меня есть класс Options
, который анализирует параметры, переданные через командную строку. Только в этот момент я знаю, как создать экземпляр регистратора с правильным расположением вывода.
Итак, мой вопрос: как / где я могу поместить свой объект логгера, чтобы все мои классы имели к нему доступ?
Я мог бы передавать свой экземпляр средства ведения журнала каждому вызову new()
для каждого экземпляра класса, который я создаю, но я знаю, что должен быть лучший, Rubyish способ сделать это. Я представляю какую-то странную переменную класса в модуле, которая делится с class << self
или какой-то другой магией. :)
Немного подробнее: Runner
начинает все, передавая параметры командной строки классу Options
и возвращает объект с парой переменных экземпляра:
module Crawler
class Runner
def initialize(argv)
@options = Options.new(argv)
# feels like logger initialization should go here
# @options.log_output => STDOUT or string (log file name)
# @options.log_level => Logger::DEBUG or Logger::INFO
@engine = Engine.new()
end
def run
@engine.go
end
end
end
runner = Runner.new(ARGV)
runner.run
Мне нужен код в Engine
, чтобы иметь возможность доступа к объекту регистратора (наряду с еще парой классов, которые инициализируются внутри Engine
). Помогите!
Всего этого можно было бы избежать, если бы вы могли просто динамически изменять расположение вывода уже созданного экземпляра Logger (аналогично тому, как вы изменяете уровень журнала). Я бы создал его для STDOUT, а затем переключился бы на файл, если я в работе. Я где-то видел предложение об изменении глобальной переменной $ stdout в Ruby, которая перенаправляла бы вывод куда-то, кроме STDOUT, но это выглядит довольно глупо.
Спасибо!