From: ptkwt@... (Phil Tomson) Date: 2005-11-23T12:12:24+09:00 Subject: pattern: auto-running module init code Maybe you've run into this problem: you have a module and you want to make sure that certain intialization code is run in that module. Of course a module can have an initialize method like so: module Foo def initialize(a,b) @a=a @b=b end end and then when you include the Foo module in your class later on that becomes the initialize for your class: class Bar include Foo end Now Bar's new takes two arguments a and b. However, what if you either want to define initialize in your class (to do some class-specific things) or what if you have a module that sets up some sort of connection, perhaps a Rinda tuplespace, for example: module Broadcaster PROTOCOL = "druby" HOST = "localhost" PORT = 9999 def setup_connection @uri = "#{@protocol||PROTOCOL}://#{@host||HOST}:#{@port||PORT}" #set up the shared tuplespace: DRb.start_service(@uri,Rinda::TupleSpace.new) puts "#{$0}: setting up broadcaster..." #now set up broadcaster: @ts = Rinda::TupleSpaceProxy.new(DRbObject.new(nil,@uri)) end #other related methods that access the tuplespace end Now if you want your class to also be a Broadcaster you could do the following: class Thing include Broadcaster def initialize(*args) #... setup_connection end end However, what if the user forgets to include the call to 'setup_connection' in their constructor? The connection won't be setup and 'Thing' won't really be doing any broadcasting. How can we get setup_connection to be called automatically when 'Thing' is extended with Broadcaster? Add the following methods to the Broadcaster module: module Broadcaster def self.extended(obj) obj.setup_connection end def self.included(mod) warn "Be sure to run #{self}.setup_connection somewhere in #{mod}'s\ initialize method!" warn "OR: instead of 'include #{self}', use 'extend #{self}' in \ #{mod}'s initialize method and it will be called automatically." end end #module Then instead of 'include Broadcaster' use 'extend' like so: class Thing def initialize(*args) #... extend Broadcaster # setup_connection called automagically end end What are the pros & cons of this approach? Is there really any advantage to doing things this way? (I can think of one con: if setup_connection took arguments this approach would not work) It does seem advantagous to call the setup code automatically this way, but it comes at the cost of using extend instead of include (and include tends to be used a lot more than extend ). Phil