Ruby元编程,如何清理这些代码?

时间:2012-02-24 16:17:23

标签: ruby-on-rails ruby

我目前有一些代码一遍又一遍地重复,看起来相当糟糕。使用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!"),无需返回初始化代码并在那里创建。

4 个答案:

答案 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