From: ara.t.howard@... Date: 2006-08-23T05:24:49+09:00 Subject: Re: Setting namespace in loaded files On Wed, 23 Aug 2006, Luke Kanies wrote: >> http://codeforpeople.com/lib/ruby/dynaload/ > > I'll look into that more closely. I've already used some of the ideas in > it, but I can't seem to understand the general idea behind it. What > problems are you solving with this? problems: - harp:~ > cat a.rb class C def m() p 'important!' end end load 'b.rb' C.new.m harp:~ > cat b.rb class C def m() p 'clobbered!' end end harp:~ > ruby a.rb "clobbered!" - harp:~ > cat a.rb module M; end load 'b.rb' harp:~ > cat b.rb class M; end harp:~ > ruby a.rb ./b.rb:1: M is not a class (TypeError) from a.rb:3 - harp:~ > cat a.rb load 'b.rb' p m harp:~ > cat b.rb m = Module.new do def self.m() 42 end end harp:~ > ruby a.rb a.rb:3: undefined local variable or method `m' for main:Object (NameError) solutions: - harp:~ > cat a.rb require 'dynaload' class C def m() p 'important!' end end loaded = Dynaload.dynaload 'b.rb' C.new.m c, metadata = loaded.classes.first c.new.m harp:~ > cat b.rb require 'dynaload' class C def m() p 'clobbered!' end end Dynaload.export C, 'the other C' harp:~ > ruby a.rb "important!" "clobbered!" - harp:~ > cat a.rb require 'dynaload' module M; end loaded = Dynaload.dynaload 'b.rb' m, metadata = loaded.modules.first p(M == m) harp:~ > cat b.rb require 'dynaload' module M; end Dynaload.export M, 'the other M' harp:~ > ruby a.rb false > Most of my dynamic loading is based on the assumption that I'm loading > someone else's code, so I want to do as much as possible for the user. I > don't want them to have to know how I'm automatically loading their files, > for instance. my too. you can skin that cat many ways. for instance, here's a distilled technique to make it totally painless for users: let's say you write a library that does this: harp:~ > cat lib.rb require 'dynaload' def m &b c = Class.new{ def self.bar() p 'forty-two' end module_eval &b } Dynaload.export c, 'c' => true end now, client code can use this lib like so: harp:~ > cat b.rb require 'lib' m{ bar def foo() p 42 end } note that 'bar' has been pre-defined for them and that no explicit exporting is going on. now, your code can load this client code, with no danger of namespace pollution, and use whatever class was defined in it using harp:~ > cat a.rb require 'dynaload' loaded = Dynaload.dynaload 'b.rb' c, meta = loaded.classes.select{|c,meta| meta.has_key? 'c'}.first c.new.foo running shows harp:~ > ruby a.rb "forty-two" 42 so the client could call 'bar' and you could call 'foo'. food for thought. cheers. -a -- to foster inner awareness, introspection, and reasoning is more efficient than meditation and prayer. - h.h. the 14th dali lama