Forum: Ruby Dynamic Object Instantiation

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Fb899458ee6c4ae4884bc3b88da57a1b?d=identicon&s=25 Troy Denkinger (Guest)
on 2006-03-02 00:30
(Received via mailing list)
I'm sure this question has been asked and answered in the past, but
googling
and searching the list archives isn't getting me much.  It's probably a
case
of me not searching correctly.  So, if someone has a pointer on that
front,
let me know.

Basically, I want a class to dynamically load and instantiate objects.
Here's the code that is supposed to do that:

ComponentGatherer.rb
---------------------------------

class ComponentGatherer

  def initialize()
    @@components = []
    Dir.foreach( File.dirname( __FILE__ ) ){|x|
      next unless x =~ /component.rb$/i
      x.gsub!( ".rb", "" )
      require "#{x}"
      @@components.push( x )
    }
  end

  def components
    @@components.each{ |x|
        test = x.new()
       # Blah, blah, blah
    }
  end
end


Locating and requring the files seems to be working fine, it's when the
component() call is made that I'm a bit lost.  I have to
*Component.rbfiles, they look like this:

MyOtherComponent.rb
--------------------------------
class MyOtherTestComponent

  attr :test

  def initialize()
    self.test = 2
  end
end

The error I get from the components() method is:

  undefined method `new' for "MyOtherTestComponent":String
(NoMethodError)

I understand what the error is saying, but I'm not sure how to call
new() on
"x" above such that it returns an object of the requested class.  Any
help
is appreciated.

Regards,

Troy Denkinger
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-03-02 01:29
(Received via mailing list)
Troy Denkinger wrote:
>
>   end
> Locating and requring the files seems to be working fine, it's when the
>     self.test = 2
>
> Regards,
>
> Troy Denkinger
>

If there is a way to map from the file name to the class name (in this
example, it would map "MyOtherComponent.rb" to "MyOtherTestComponent"),
then you can do this first, and then use const_get to get the class:

  x = "MyOtherComponent.rb"
  x.gsub(/.rb$/, "")
  x.gsub(/Component/, "TestComponent")
  cl = Kernel.const_get x
  obj = cl.new

But it's sometimes difficult to enforce this filename/classname
consistency.

I prefer something like this:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/...

It still uses const_get, but it wraps the component inside a module, so
that the global namespace doesn't get polluted, and you can query for
the class that was defined in a file without mucking around with the
file name.

HTH.
Fb899458ee6c4ae4884bc3b88da57a1b?d=identicon&s=25 Troy Denkinger (Guest)
on 2006-03-03 19:17
(Received via mailing list)
Thanks for the followup.  I also figured out how to search and found
this:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/...

Which also helps.

Thanks.
This topic is locked and can not be replied to.