From: Zach Dennis Date: 2005-07-21T02:12:19+09:00 Subject: Re: Variable class (newb question) David A. Black wrote: > Hi -- > > On Thu, 21 Jul 2005, Zach Dennis wrote: > >> The only thing I don't like about the above solution is potential >> insecurity if someone passes in " ; B" , the >> would execute. This could changed to be more secure if you were always >> using toplevel classes... >> >> >> def get_class_for_string( class_name ) >> eval("#{class_name}.new") if Object.constants.include?( class_name ) >> end >> >> Which the above code makes sure that the passed in class_name has been >> defined on the top-level Object otherwise it will return nil. This >> won't work for things like "MyModule::B" or "MyClass::InnerClass:B", >> although you could change it to work. And here is the modified version >> to make it work across the board: >> >> def get_class_for_string( class_name ) >> last_constant = Object >> class_name.split( /::/ ).each do |cons_str| >> if last_constant.constants.include?( cons_str ) >> last_constant = eval( "last_constant::#{cons_str}" ) >> else >> return nil >> end >> end >> eval("#{last_constant}.new") >> end > > > A more concise and eval-free way to do that is: > > class Module > def deep_const_get(str) > str.split("::").inject(Object) {|a,b| a.const_get(b) } > end > end > > "Traditional", as they say for folk songs :-) I've written it and > others have too -- I don't know who first. > > Note that there's no need to test for failure; it will fail if any > call to const_get fails. > Very beautiful! And thank you for the more concise and better implemented code, I will have to add this to my repertoire. Zach