从模块设置类变量

Mr.*_*ils 5 ruby logging ruby-on-rails

我希望我的应用程序有单独的日志。我创建了以下模块:

module MyApp
  module MyLog
    def self.included(base)
      base.extend(ClassMethods)
    end

    module ClassMethods
      def logger
        @@logger ||= Logger.new("#{Rails.root}/log/#{self.name.underscore}.log")
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

然后,在我的任何模型中,我可以添加:

include MyApp::MyLog
Run Code Online (Sandbox Code Playgroud)

并将其用作(日志文件将出现在.../log/cat.log):

Cat.logger.info 'test'
Run Code Online (Sandbox Code Playgroud)

我尝试在和模型included上使用此方法,得到以下结果:CatDog

Cat.new.logger
# => #<Logger:0x007fe4516cf0b0 @progname=nil, ... @dev=#<File:/.../log/cat.log>, ... 
Dog.new.logger
# => #<Logger:0x007fe4516cf0b0 @progname=nil, ... @dev=#<File:/.../log/cat.log>, ... (the same)
Run Code Online (Sandbox Code Playgroud)

如果我尝试首先使用我的记录器进行Dog模型,我将有一个名为dog( /dog.log) 的日志文件。

如何使用@@logger正确的初始化记录器为每个类设置模块中的类变量?

Ner*_*min 4

不要使用类变量,使用instance_variable附加到类的变量。

module MyApp
  module MyLog

    def self.included(base)
      base.extend(ClassMethods)
    end

    module ClassMethods
      def logger
        @logger ||= Logger.new("#{Rails.root}/log/#{self.name.underscore}.log")
      end
    end

  end
end
Run Code Online (Sandbox Code Playgroud)

例子:

module A
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods

    def logger
      puts @logger
      @logger ||= name
    end
  end
end

class B
  include A
end

class C
  include A
end

B.logger
#
B.logger
# B
C.logger
#
B.logger
# B
C.logger
# C
Run Code Online (Sandbox Code Playgroud)

第一次调用该方法时nil,它是空行,第二次调用该方法时,该值等于类名,B如果在新类上调用,则再次调用nil,请检查此答案

Ruby 类实例变量与类变量