Choosing a module name at runtime

My application chooses at runtime the input format of some data, for
example :xml or :mysql. Then, the app instantiates a DataManager. The
DataManager class should ‘include’ the appropriate Module (either
DataIOXML or DataIOMySQL).
I tried to use include in the initialize method of DataManager, but that
doesn’t work.
Can I include a module in the initialize method of the class? If yes,
how?
If no: Any other ways how I can choose the correct module to include at
runtime?

Important: All the information about Modules and file names is stored in
the DataManager class. My app only knows the DataManger class itself,
not the names of the modules (so I can’t subclass separate IO classes
from DataManager, and instantiate them directly from my app).

Here’s the example code for the app, the DataManger class, and the :xml
Module:

#! /usr/bin/ruby -w

main app

here, only the name ‘DataManager’ and the IO format (:xml or :mysql)

is known,

not the name of the format-specific module.

require “DataManager.rb”
dm = DataManager.new(:xml)
dm.say_something

DataManager.rb

class DataManager

theDataManager class knows all possible IO formats, and the

corresponding Module names:

@@io_mixins = {
:xml => ‘DataIOXML’,
:mysql => ‘DataIOMySQL’,
}

def initialize(format=:xml)

unless @@io_mixins.include? format
  raise NotImplementedError, "IO Format #{format} unknown"
end

require @@io_mixins[format]+".rb"
# the next line causes an error
include DataIOXML

end
end

DataIOXML.rb

XML-specific module

module DataIOXML
def say_something
puts “I’m DataIOXML”
end
end

On Sep 12, 2009, at 3:26 PM, John Smirnoff wrote:

at
runtime?

You want the “extend” method, not the “include” method:

module A
def foo
“A: foo”
end
end

module B
def foo
“B: foo”
end
end

class C
def initialize which
extend(which == :a ? A : B)
end

def metaclass; class << self; self end end
end

p C.new(:a).metaclass.ancestors
p C.new(:b).metaclass.ancestors

Hope that helps.


Aaron P.
http://tenderlovemaking.com

Aaron P. wrote:

You want the “extend” method, not the “include” method:

Thanks!