From: Nasir Khan Date: 2007-04-01T05:10:56+09:00 Subject: Re: Find the fully qualified name of a class from a string ------=_Part_58980_20339899.1175371854599 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Here is an abridged (out of context) version of my original solution. (whic= h I am using now) ----- nasir@sparkle:misc>cat find_class_name.rb module EmptyModule def EmptyModule.clear_all constants.each {|x| remove_const(x.to_sym)} end end @my_classes =3D [] def class_from_string(str) EmptyModule.clear_all # clean the slate EmptyModule.module_eval(str) end cstr =3D <ruby find_class_name.rb B::D B::C B::A ---------------- I guess I will stick with this solution. set_trace_func usage is very interesting but as I could have potentially several such evaluations going on in parallel, I would go with the solution above. Comments criticisms welcome. ~ nasir On 3/31/07, Rick DeNatale wrote: > > On 3/30/07, Kristoffer Lund=E9n wrote: > > On 3/31/07, Nasir Khan wrote: > > > Anyway, there could be several uses for such a thing. Simplest use > case > > > would be a RAILS like (but not RAILS) situation where a controller is > > > deployed on a running server which (controller) optionally comes as a > string > > > enveloped in a protocol message, this string is evaled and the > controller is > > > instatiated but the system also needs to maintain meta information > including > > > the name of the controller just deployed, which defaults to the fully > > > qualified name of the class. > > > My use case is similar. > > > > > > > Here's one way to capture that info as it's evaled. Not thread-safe > > as-is. Not even sure if it's useful at all, but I was a bit curious. > > There's more ways to do this, of course, especially depending on when > > you want to capture this info. > > > > str =3D < > module A > > class B > > def b > > puts "hello" > > end > > end > > end > > EOF > > > > set_trace_func proc {|event, file, line, id, binding, classname| > > return unless event =3D=3D 'class' > > name =3D eval('self.class =3D=3D Class && Module.nesting[0]', binding= ) > > if name > > # Do something with name > > end > > } > > > > eval(str) > > > > set_trace_func(nil) > > I like his idea of evaluating the string in the context of a 'sandbox' > module, here's a refinement which does that. It strips off the > throwaway module since I assume that he's doing this to pre-flight > check actually re-running the code again after scanning it. > > I also check to see if the trace function is running on the > originating thread, there are still thread safety issues since another > thread might also be using set_trace_func. Another way to approach > this would be to set and reset Thread.critical, but it doesn't solve > the second problem since there doesn't seem to be a way to stack trace > functions. > > rick@bill:/public/rubyscripts$ cat find_classes.rb > def classes_defined_in(str) > begin > this_thread =3D Thread.current > result =3D [] > set_trace_func(lambda do |event, file, line, id, binding, classname| > return unless Thread.current =3D=3D this_thread > return unless event =3D=3D 'class' > name =3D eval('self.class =3D=3D Class && Module.nesting[0]',bindin= g) > result << name.to_s.split(/::/,2)[1] if name > end) > ensure > Module.new.module_eval(str) > set_trace_func(nil) > end > result > end > > str =3D < module M1 > class C1 > def c > puts "hello" > end > end > > module M2 > class C2 > end > end > end > module M3 > class C3 > end > end > EOF > > p classes_defined_in(str) > rick@bill:/public/rubyscripts$ ruby find_classes.rb > ["M1::C1", "M1::M2::C2", "M3::C3"] > > -- > Rick DeNatale > > My blog on Ruby > http://talklikeaduck.denhaven2.com/ > > ------=_Part_58980_20339899.1175371854599--