Lloyd Zusman wrote:

>>>  class Bar
>>>    include Intercept
>>>    def initialize
>>>      puts "performing Bar#initialize"
>>>    end
>>>  end
>>>
>>>In other words, simply by including the "Intercept" module in a class,
>>>I'd like to intercept that class's call to "initialize" and have the
>>>Intercept module's code get invoked first, and _then_ the containing
>>>class's "initialize" method should be called as it normally would.
>>
>>I think the only way of doing that without putting the include() behind
>>the initialize def would be using a method_added hook...
> 
> Could you explain how this could be done with a method_added hook?

Like this:

   require 'thread'

   module Intercept
     def self.included(other)
       install_initialize = lambda do
         other.class_eval do
           alias :old_initialize :initialize

           def initialize(*args, &block)
             intercept_initialize
             old_initialize(*args, &block)
           end
         end
       end

       class << other; self; end.class_eval do
         alias :old_method_added :method_added

         ignore = false
         define_method(:method_added) do |name|
           return if ignore

           case name
             when :initialize then
               Thread.exclusive do
                 ignore = true
                 install_initialize.call
                 ignore = false
               end
             else
               old_method_added(name)
           end
         end
       end

       install_initialize.call
       super
     end

     def intercept_initialize
       puts "performing Intercept#intercept_initialize"
     end
   end

   class Bar
     include Intercept
     def initialize
       puts "performing Bar#initialize"
     end
   end

   Bar.new

But note that in that case the user could still redefine 
Bar.method_added() and circumvent the restore logic. I think adding a 
singleton_method_added handler would fix that.

I'm also not sure if the Thread.exclusive stuff can be done in a cleaner 
way...