From: why the lucky stiff Date: 2002-10-17T06:54:04+09:00 Subject: Re: Plugin autoregistration (inherited method call) Wejn (lists+rubytalk@box.cz) wrote: > # --- begin ----------------------------------------------------------------- > class Transport > @@transports = {} > def Transport.registered_transports > ar = [] > @@transports.each_key { |x| ar << x } > ar > end > def Transport.inherited(sub) > @@transports[sub.new.proto_id] = sub > end > end > > class TCPTransport < Transport > def proto_id > 'tcp' > end > end > > puts "Registered transports: " + Transport.registered_transports.join(', ') > # --- end ----------------------------------------------------------------- > > but it just doesn't work ... :( I believe Transport.inherited is called before the TCPTransport class definition is complete. At that point the 'proto_id' method doesn't exist yet. See: class Transport def Transport.inherited( sub ) p sub.new end end class TCPTransport < Transport def initialize @test = 1 end end p TCPTransport.new Prints: # # The 'sub.new' call inside Transport.inherited issues a TCPTransport object before TCPTransport#initialize has actually been defined. So you'll need to simply store the class constant and call 'proto_id' later. You have plenty of options for getting around this. I've been working on some apps which use similiar ideas for plugins. Part of the decision lies in how you actually will be loading the plugins. If you have a list files which contain plugins, then you could wrap them inside a TransportPlugin module when they are loaded. Then, loop through the TransportPlugin constants, searching for those which are valid plugin classes. If you want to go the inheritance route, rather than using Class.inherited, you should try giving your inheritance class a couple of toplevel singleton methods for use during class definitions. Your examples modified: class Transport @@transports = {} def Transport.add( addr, tgt ) @@transports[ addr ] = tgt end def Transport.registered_transports @@transports.keys end class << self def def_proto_id( pid ) Transport.add( pid, self.class ) end end end class TCPTransport < Transport def_proto_id 'tcp' end puts "Registered transports: " + Transport.registered_transports.join(', ') Good luck. _why