0

コードを DRY に保つために、ロギング用の mixin を作成しようと考えました。これはどのように見えるかです:

# Mixin that provides shortcuts for logging methods.
module Logging
  def self.included(base)
    base.class_exec {
      @logger_name = base.to_s
      @subloggers = []
      @logger = Logger.new(STDOUT)
      @logger.level = Logger::FATAL
    }
  end

  def logger=(logger)
    @logger = logger
    @subloggers.each { |obj| obj.logger = logger }
  end

  def debug(&block)
    @logger.debug(@logger_name, &block)
  end

  def info(&block)
    @logger.info(@logger_name, &block)
  end

  def warn(&block)
    @logger.warn(@logger_name, &block)
  end

  def error(&block)
    @logger.error(@logger_name, &block)
  end

  def fatal(&block)
    @logger.fatal(@logger_name, &block)
  end
end

理論的には、私は今これを行うことができるはずです:

class SomeClass
  include Logging

  def foo_bar
    debug { "foo_bar is being executed" }
    fatal { "IT'S A TRAP" }
  end
end

問題は、明らかにミックスインが含まれるinitializeに呼び出され、これが失敗することです:

class SomeClass
  include Logging

  def initialize
    @cache = CacheClass.new
    @subloggers << @cache   # @subloggers is nil
  end
end

そして、私はそれを回避する方法を想像することはできません. 私は常にコンストラクターで依存関係を作成します。その時点で Logging mixin を使用できるようにする必要があります。何か案は?

4

2 に答える 2

0

これは間違っています:

問題は、ミックスインが含まれる前に明らかに初期化が呼び出され、これが失敗することです:

あなたが書いたことに反して、initialize呼び出されません。@subloggersインスタンスに対して初期化されていませんSomeClass。コンストラクターからアクセスしているのと同じ変数に@subloggers割り当てられていると思いますか? そうであってはなりません。インスタンス自体の作成前にインスタンス変数を作成することはできません。Logging.included(base)@subloggersSomeClass

于 2013-06-11T10:51:14.630 に答える