Get caller class

前端 未结 3 1149
小蘑菇
小蘑菇 2021-02-19 09:38

I\'m writing Logger and got problem with automatic adding class name, from which I called print_log method. For example something like this:

class Logger
  def s         


        
相关标签:
3条回答
  • 2021-02-19 09:50

    After futzing about with caller for a while, it's probably not going to do it for you, and neither is caller_locations. It's possible to track the classes of the last objects instantiated on the current thread, e.g.

    class Class
      alias :_new :new
      def new *args
        Thread.current.thread_variable_set :classes, ((Thread.current.thread_variable_get(:classes) || []) << self).last(10)
        _new *args
      end
    end
    

    This retains the classes of the last 10 objects, but this isn't directly equivalent to a hierarchy e.g.

    class X
      def initialize
        puts Thread.current.thread_variable_get(:classes)
      end
    end
    
    class Y
    end
    
    class Z
      def initialize
        @y = Y.new
        @x = X.new
      end
    end
    

    X.new outputs the following (in a console session)

    RubyToken::TkNL
    RubyToken::TkEND
    RubyToken::TkNL
    RubyToken::TkCONSTANT
    RubyToken::TkDOT
    RubyToken::TkIDENTIFIER
    RubyToken::TkNL
    Y
    Z
    X
    
    0 讨论(0)
  • 2021-02-19 10:14

    I am not sure if it is possible to get the class name like you want. I would create a logger instance for this to which you can pass in the class name when creating it.

    class Logger
      def initialize(class_name)
        @class_name = class_name
      end
    
      def print_log(message)
        puts Time.now.strftime('%T | ') + @class_name + ' - ' + message
      end
    end
    
    class MyClass
      def initalize
        @logger = Logger.new self.class.name
        @logger.print_log 'called .new() method'
      end
    end
    

    More verbose than you would like maybe but explicit code that is easy to understand.

    For any serious work I recommend using the standard library logger. You may have to wrap it in your own call to get the log messages as you want it but you'll get log rotating and file handling as it should be.

    0 讨论(0)
  • 2021-02-19 10:15

    You can use module like that (Rails style):

    module Loggable
      extend ActiveSupport::Concern
    
      def log_prefix
        @log_prefix ||= (self.class == Class ? "#{self.to_s}" : "#{self.class.to_s}").freeze
      end
    
      included do
        [:debug, :info, :warn, :error, :fatal].each do |level|
          define_method level do |str = nil|
            caller = caller_locations(1,1)[0].label
            prefix = "[#{log_prefix}##{caller}] "
            prefix << level.to_s.upcase[0]
            str = "#{prefix}: #{str}"
            puts str if ENV["DEBUG"]
            Rails.logger.send(level, str)
          end
        end
      end
    end
    

    and you code will be:

    class MyClass
      include Loggable
      extend Loggable
    
      def instance_method
        debug "Hello"
      end
    
      def self.klass_method
        debug "Klass"
      end
    end
    
    0 讨论(0)
提交回复
热议问题