编写一个小 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,然后转换为文件。我确实在某处看到了有关更改 Ruby 的 $stdout 全局变量的建议,该变量会将输出重定向到 STDOUT 以外的其他位置,但这似乎很 hacky。
谢谢!