从模块设置类变量

时间:2016-02-08 14:22:31

标签: ruby-on-rails ruby logging

我想为我的应用设置单独的日志。我创建了以下模块:

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

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

include MyApp::MyLog

并将其用作(日志文件将显示在.../log/cat.log中):

Cat.logger.info 'test'

我尝试在includedCat模型上使用此方法Dog,我有这样的结果:

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)

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

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

1 个答案:

答案 0 :(得分:3)

不要使用类变量,请使用附加到类的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

实施例

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

第一次调用方法时它是nil,因此是空行,第二次调用方法时,值等于类名B,如果调用新类,则再次{ {1}},请同时查看此答案

Ruby class instance variable vs. class variable