From: ptkwt@...1.aracnet.com (Phil Tomson) Date: 2001-09-27T04:38:28+09:00 Subject: [ruby-talk:21748] Allowing user code within a program I've got a testing application where I use dRuby to distribute testcases to idle machines on a network. Sometimes the testcases already exist, but in other cases, for added flexibility, I want to allow for users to generate testcases programatically with Ruby code. I have a class called Pool which in the constructor makes two lists: 1) a list of files in the Pool directory which have extensions for existing testcases (.rfl in this case) and 2) a list of files with the extenstion ..rbgen which contain user code which is used to generate testcases. Pool also has a 'each' iterator method which iterates through the testcases in each list. In the first list, each testcase is yield'ed. In the second list, each rbgen file is first load'ed - the rbgen file must contain a module function called: TCGen.generate - after the rbgen is load'ed, the TCGen.generate function is called. Here's the code (I've not included the TestCase class for brevity): #pool.rb Pool - # initialize makes two lists: 1) a list of files with extenstion .rfl # 2) a list of files with extenstion .rbgen # .rbgen files are ruby files which generate testcases. This allows # 'server-side' flows which can generate testcases class Pool def initialize(name) @name = name #the name of the pool #find the list of .rfl files in the pool @rflList = Dir["#@name/*.rfl"] #look for rbgen files @rbgenList = Dir["#@name/*.rbgen"] end #initialize def each @rflList.each {|x| name = File.basename(x,".rfl") location = File.dirname(x) yield TestCase.new(name,location) } @rbgenList.each {|rbgen| name = File.basename(rbgen,".rbgen") puts "name is : #{name}" puts "load #{rbgen}" load "#{rbgen}" TCGen.generate {|tc| yield tc } } end #each end #how to use it: if $0 =~ __FILE__ pool = Pool.new("pool") #look in a subdir called 'pool' pool.each { |testcase| puts "#{testcase}" #send testcase to next available machine } end #end pool.rb Here's an example of an .rbgen file: #this is aa.rbgen which resides in the subdir 'pool' require "ftools" require "testcase" module TCGen def TCGen.generate #a contrived example: list = Dir["*.*"] list.each {|file| name = File.basename(file) location = File.dirname(file) File.copy(file,"/home/phil/ruby_stuff/testcases") yield TestCase.new(name,location) } end end #module TCGen In this case the TCGen.generate function just copies files in the current directory to a specific location, but a more realistic TCGen.generate function would actually produce a set of files to be run as testcases - after each testcase is 'generated' the testcase is yield'ed. Anyway, if you're still with me... I'm wondering if this method of 'load'ing a file and then calling a function defined in that external file is the best way of doing this - any opinions, other ideas? Phil