Ruby Class logger does not work - ruby

I am use logger class but I am getting error.
Code :-
class Try
def method_missing(method_name, *args)
logger.warn "I am try to call #{method_name} with these arguments #{args}"
super
end
end
Try.new.dummy(1, "my name is rosy.")
Getting error:-
stack level too deep (SystemStackError)
Please tell us. How to solve this problem.

I'm assuming you are not in a rails app. Have you instantiated the logger instance?
require 'logger'
logger = Logger.new(STDOUT)
logger.level = Logger::WARN
logger.warn "test"

Related

Use of Logger with Ruby and RSpec

I have created logger object in "spec/logger.rb" and returned it.
I have created logger object in "spec/test1.rb" in describe method and can use it. it is working in same directory. If i need to use logger by creating logger object or by including file in different directory with and without class, then is there any way to do it ?
spec/logger.rb
class Logging
def initialize_logger()
log = Logger.new("test.log")
return log
end
end
spec/test1.rb
require 'java'
require 'rspec'
require 'logger'
require "logger.rb"
class SingleTest
describe 'Verify Single Test' do
# create logger object
logger_object = Logging.new
logger = logger_object.initialize_logger()
logger.info 'Checking Logger'
it 'Verify Single Test for logger is present' do
logger.info 'Creating logger'
end
end
end
lib/test_lib1.rb
require 'httparty'
require '../utility/logger.rb'
#logger_object = Logging.new
#logger = #logger_object.initialize_logger()
#logger.info 'Checking Logger'
def first()
#logger.info "first logger in lib"
end
def perform_url_request()
#logger.info "URL"
#logger.info "Request Method"
end
lib/test_lib2.rb
require '../utility/logger.rb'
class TestFile
def initialize()
#logger_object = Logging.new
#logger = #logger_object.initialize_logger()
#logger.info "I am intialize"
end
def test_method()
#logger.info "******"
end
end

How can ruby logger set the progname automatically based on the method

I have set up my logger using a module with the following (simplified) version:
module Logging
class << self
def logger
end
def logger=(logger)
#logger = logger
end
end
end
I would like to do something like the following (it didn't work):
Get the name of the currently executing method
def test_method
return __callee__
end
This way without the above, add logger.progname = self.test_method
So it should look like this:
module Logging
class << self
def logger
return #logger if #logger
#logger.progname = self.test_method
end
def logger=(logger)
#logger = logger
end
end
end
The end goal should be such that, with method "MyMethod":
def my_method
logger.debug "hi"
end
I get => "my_method: "hi"

logger in ruby unit test startup or setup

I am writing some tests in ruby and have this question.
class MyTest < Test::Unit::TestCase
LogFile = "test.log"
Log= Logger.new(LogFile)
def startup
#log = Log
end
def shutdown
end
def setup
end
....
end
I am trying to create a logger in startup, however, it does not work well. In the test cases, #log is nil.
I know I can put it in setup, however, I don't want to reassign it for every test case. Why it does not work? What is the correct way to do it?
startup should be used as a class method. There you could define a class variable like ##log.
If you want to use an instance variable #log you must fill it in setup.
Example:
require 'test/unit'
require 'logger'
class MyTest < Test::Unit::TestCase
LogFile = "test.log"
Log= Logger.new(LogFile)
def self.startup
##log = Log
end
def setup
#log = Log
end
def test_class_var
assert_kind_of(Logger,##log)
end
def test_instance_var
assert_kind_of(Logger,#log)
end
end

Using a singleton class in a custom logger

I currently have a logging setup that looks like this:
require 'active_support'
require 'singleton'
class Worker
def initialize(logger)
#logger = logger
end
def perform
#logger.with_context(["tag1"], "Started work")
Provider.say_hello
end
end
class Vlogger
include Singleton
attr_accessor :logger
def logger
#logger ||= ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
end
def with_context(tags, msg)
#logger.tagged(*tags) { #logger.info msg }
end
end
class Provider
def self.logger
Vlogger.instance
end
def self.say_hello
logger.with_context(["tag2"], "hello")
end
end
v = Vlogger.instance
v.logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
Worker.new(v).perform
My objective with this is to avoid having to pass around the #logger instance variable found in my Worker class. Ideally, I want the Vlogger class to be available to all classes. I'm finding that I'm having to use this pattern quite a bit in my code:
def self.logger
Vlogger.instance
end
Is there a better way to do this? Is my OO design pattern here inherently flawed? Ideally I'm trying to avoid passing around objects when really the object has no state and it should be available to various classes without introducing class or instance methods. Thoughts?

Setting up configuration settings when writing a gem

I'm writing a gem which I would like to work with and without the Rails environment.
I have a Configuration class to allow configuration of the gem:
module NameChecker
class Configuration
attr_accessor :api_key, :log_level
def initialize
self.api_key = nil
self.log_level = 'info'
end
end
class << self
attr_accessor :configuration
end
def self.configure
self.configuration ||= Configuration.new
yield(configuration) if block_given?
end
end
This can now be used like so:
NameChecker.configure do |config|
config.api_key = 'dfskljkf'
end
However, I don't seem to be able to access my configuration variables from withing the other classes in my gem. For example, when I configure the gem in my spec_helper.rb like so:
# spec/spec_helper.rb
require "name_checker"
NameChecker.configure do |config|
config.api_key = 'dfskljkf'
end
and reference the configuration from my code:
# lib/name_checker/net_checker.rb
module NameChecker
class NetChecker
p NameChecker.configuration.api_key
end
end
I get an undefined method error:
`<class:NetChecker>': undefined method `api_key' for nil:NilClass (NoMethodError)
What is wrong with my code?
Try refactoring to:
def self.configuration
#configuration ||= Configuration.new
end
def self.configure
yield(configuration) if block_given?
end
The main issue is that you've applied too much indirection. Why don't you just do
module NameChecker
class << self
attr_accessor :api_key, :log_level
end
end
and be done with it? You could also override the two generated readers right afterwards so that they ensure the presence of the environment that you need...
module NameChecker
class << self
attr_accessor :api_key, :log_level
def api_key
raise "NameChecker really needs is't api_key set to work" unless #api_key
#api_key
end
DEFAULT_LOG_LEVEL = 'info'
def log_level
#log_level || DEFAULT_LOG_LEVEL
end
end
end
Now, the actual (technical) problem is that you are defining a class called NetChecker and while defining it you are trying to print the return value of the api_key call on an assumed Configuration object (so you are violating the law of Demeter here). This fails, because you are defining NetChecker before anyone really has had time to define any configuration. So you are in fact requesting api_key before the configure method has been called on NameChecker, so it has nil in it's configuration ivar.
My advice would be to remove the overengineering and try again ;-)

Resources