On Aug 4, 2008, at 6:30 PM, Chuck Remes wrote:

>
> On Aug 4, 2008, at 5:38 PM, Chuck Remes wrote:
>>
>> For lurkers, here is some slightly corrected code (the above  
>> doesn't compile).
>>
>> require 'logger'
>>
>> module Namespace
>> module Logger
>>  def Logger.key= *key
>>    @key = key.first unless key.empty?
>>  end
>>
>>  def Logger.key
>>   @key
>>  end
>>
>>  def Logger.instance
>>    @instances ||= Hash.new { |h,k| h[key || :default ]  
>> = ::Logger.new(STDOUT) }
>>    @instances[@key]
>>  end
>>
>>   %w( debug info warn error fatal ).each do |method|
>>    	module_eval <<-code
>>        def Logger.#{ method }(*a, &b)
>>          instance.#{ method }(*a, &b)
>>        end
>>      code
>>    end
>> end
>> end
>
> Hmmm... I puzzled through this all the way home and came to the  
> conclusion that I don't know why, or if, this works.
>
> If we are saving information in an instance variable in a class  
> method, clearly that instance variable can be overwritten by another  
> writer, yes? These class methods are visible to anyone who can this  
> module in scope, therefore the @key variable can be pretty volatile.
>
> This whole setup is predicated on WriterA calling  
> Namespace::Logger.key = <unique val> which is later used by  
> Namespace::Logger.instance as an index into a hash to lookup the  
> correct ::Logger object in @instances. However, there is no  
> guarantee that @key will remain <unique val> for WriterA. If WriterB  
> comes along and makes the same call, that writer replaces <unique  
> val> with its own value.
>
> If that didn't happen, then how would @instances store references to  
> everyone's ::Logger objects? These variables must be shared for that  
> to work.
>
> Right?
>
> If true, I'm back to square one. Each writer would have to pass in  
> their own unique key so they lookup the right ::Logger object. Now  
> instead of injecting the ::Logger object into all of my classes, I  
> have to make sure the @key value is known by all.
>
> Please correct me where I am wrong.

Here's proof it doesn't work as currently written. I'm hoping there's  
a trick I don't know about ruby that will allow this to work.

cr

require 'logger'

module Namespace
   module Logger
     def Logger.key= *key
       @key = key.first unless key.empty?
     end

     def Logger.key
       @key
     end

     def Logger.instance
       @instances ||= Hash.new { |h,k| h[k || :default ]  
= ::Logger.new(STDOUT) }
       @instances[key]
     end

     %w( debug info warn error fatal ).each do |method|
       module_eval <<-code
         def Logger.#{ method }(*a, &b)
           instance.#{ method }(*a, &b)
         end
       code
       end
   end

   class Bar
     def initialize(value)
       Namespace::Logger.key = value
     end

     def foo
       Namespace::Logger.info { "called with Logger.key  
[#{Namespace::Logger.key}] " }
     end
   end
end

a = Namespace::Bar.new 17
b = Namespace::Bar.new 24

a.foo
b.foo


-- output --

I, [2008-08-04T19:06:50.597418 #91765]  INFO -- : called with  
Logger.key [24]
I, [2008-08-04T19:06:50.598877 #91765]  INFO -- : called with  
Logger.key [24]