我目前有一些代码一遍又一遍地重复,看起来相当糟糕。使用Ruby的元编程来清理它的最佳方法是什么?
我有一个反复出现的主题是这样的:
class Object
def some_logger
@some_logger ||= Logger.new("log/some.log")
end
def some2_logger
@some2_logger ||= Logger.new("log/some2.log")
end
end
理论上,我只想在整个Rails应用程序中调用一个任意记录器,并将这些日志转到一个单独的,易于识别的文件中。所以我可以随意打电话:
控制器或模型中的 some3_logger.info("Wooohooo!")
,无需返回初始化代码并在那里创建。
答案 0 :(得分:8)
您可以将记录器名称作为参数传递:
module CustomLogger
def custom_logger(name)
@custom_loggers ||= {}
@custom_loggers[name] ||= Logger.new("log/#{name}.log")
end
end
只需在任何需要的地方包含CustomLogger即可:
custom_logger("some3").info("Wooohooo!")
答案 1 :(得分:1)
我绝对不会把它放在Object上。将方法放在Object上只是在惹麻烦。
也许这样的事情会满足你的需求:
class MyLogger
def self.method_missing(method, *args)
if method =~ /logger$/
logger_name = method.to_s.split('_').first
symbol = "@@#{logger_name}".to_sym
unless class_variable_defined?(symbol)
class_variable_set(symbol, Logger.new("log/#{logger_name}.log"))
end
class_variable_get(symbol)
end
end
end
MyLogger.some_logger.info('This is very information.')
MyLogger.test_logger.debug('This goes into a separate file and is for debugging only.')
答案 2 :(得分:1)
将此包含在任何可获得异想天开的记录器行为的类中:
module DynoLogger
def method_missing(method, *args)
if logger_method? method
ivar = "@#{method}"
base = method.to_s
base[/_logger$/] = ""
instance_variable_get(ivar) ||
instance_variable_set(ivar, new_logger(base))
else
super
end
end
def respond_to_missing?(method, include_private)
super || logger_method?(method)
end
def logger_method?(method)
!!(method =~ /_logger$/)
end
def new_logger(name)
Logger.new "log/#{name}.log"
end
end
答案 3 :(得分:0)
由于您使用ruby-on-rails对此进行了标记,因此我假设您处于该环境中,因此按照Rails.logger.
的示例对命名空间进行命名空间也不错...如果使用rails logger是不是很好,你可以修补namesspace而不是Object。
此外,您可以将通知视为记录事物的可能方式。见http://railscasts.com/episodes/249-notifications-in-rails-3