My expectations are in the comments.
require 'logger'
module Logging
attr_accessor :logger
def logger
return @logger if @logger # allow items to have own loggers
@@logger ||= Logger.new(STDERR)
puts "Instance Class REF ID#{@@logger.__id__}"
puts "Class ID #{self.class.logger.__id__}"
@@logger
end
module ClassMethods
def logger= logger
@logger = logger
end
def logger
@logger ||= Logger.new(STDERR)
puts "Class Instance REF ID #{@logger.__id__}"
@logger
end
end
def self.included(base)
base.extend(ClassMethods)
end
end
class Test
include Logging
def wow
logger.info 'wow'
end
end
t = Test.new
# should be the same
puts "Loggers are #{t.logger.__id__ == Test.logger.__id__ ? '' : 'not '}the same"
Test.logger = Logger.new('/dev/null')
# should still be the same
puts "Loggers are #{t.logger.__id__ == Test.logger.__id__ ? '' : 'not '}the same"
lg = Test.logger.__id__
t.logger = Logger.new(STDERR)
# class logger should be same
puts "Class Logger is #{Test.logger.__id__ == lg ? 'still the' : 'not'} same"
# class and instance logger should be different
puts "Loggers are #{t.logger.__id__ == Test.logger.__id__ ? '' : 'not '}the same"
When executed:
➜ sandbox irb 1.9.3-p392 :001 > load 'test_l.rb' Instance Class REF ID70203753590760 Class Instance REF ID 70203753590500 Class ID 70203753590500 Class Instance REF ID 70203753590500 Loggers are not the same # I expected to be same... :( Instance Class REF ID70203753590760 Class Instance REF ID 70203753590000 Class ID 70203753590000 Class Instance REF ID 70203753590000 Loggers are not the same # I expected to be same... :( Class Instance REF ID 70203753590000 Class Instance REF ID 70203753590000 Class Logger is still the same Class Instance REF ID 70203753590000 Loggers are not the same
I've deliberately forgotten how to use @@
variables because they are so confusing and rarely needed.
Instead, consider only using instance variables, but delegate up to the class level if needed:
module Logging
attr_writer :logger
def logger
defined?(@logger) ? @logger : self.class.logger
end
module ClassMethods
def logger=(logger)
@logger = logger
end
def logger
@logger ||= Logger.new(STDERR)
end
end
def self.included(base)
base.extend(ClassMethods)
end
end
class Test
include Logging
# ...
end