Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get caller class

Tags:

ruby

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 self.print_log(string)
    puts Time.now.strftime('%T | ') + *caller_class_name_here* + ' - ' + string 
  end
end

class MyClass
  def initialize
    Logger.print_log 'called .new() method'
  end
end

As result of calling MyClass.new method I wanna see in output:

14:41:23 | MyClass - called .new() method

I'm sure it's possible to do using caller, but yet can't find how

like image 461
Hroft Avatar asked Oct 30 '13 10:10

Hroft


People also ask

How can I get the class name that calls my method?

You can use StackFrame of System. Diagnostics and MethodBase of System. Reflection . StackFrame(Int32, Boolean) initializes a new instance of the StackFrame class that corresponds to a frame above the current stack frame, optionally capturing source information.

How do you call all methods in a class?

Write the callAll() method to actually call each method explicitly without reflection. This allows for flexibility in subclassing. It also allows you to deal with methods which have parameters. It also allows you to bypass methods which don't apply.

How do I find my current class name in Testng?

If you want to get super class name you can use getSuperClass(). If an answer to another question can be used here, please do not answer the question and flag it as a duplicate (if you have enough privileges).


2 Answers

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
like image 188
Vlad Avatar answered Sep 19 '22 13:09

Vlad


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.

like image 21
froderik Avatar answered Sep 17 '22 13:09

froderik