Hi, I'm just now getting into Ruby's OO-ness, and could use some advice.
I'm trying to create an object, but which specific class needs to be
determined at runtime. I figured out how to do this by creating a
string and executing it using the "eval" command, but I know there must
be an easier way. My first guess was to do something like #{answer}.new
but that didn't work.
Here's my code:
class Foo
def method1
end
end
class Bar
def method2
end
end
# Pretend this was determined at runtime
answer = "Foo"
# There must be a better way of doing this:
myobj = Object.new # Needs to exist in this scope
mystring = "myobj = #{answer}.new"
eval mystring
puts "I just created a #{myobj.class} object."
Any advice is appreciated. Thanks in advance!
Todd.
klass = answer.split('::').inject(Object) { |klass,const| klass.const_get const }
myobj = klass.new
In longer terms:
answer.split('::') # for Foo::Bar::Baz nested classes/modules
answer.split('::').inject(Object) do |klass, const| # namespaces start from Object
klass.const_get const # #inject passes the value of this expression in
# as the first arg to the block, so use that namespace
# to find the next part of the namespace
end
klass = answer.split [...] # #inject returns the last result, which will
# be a class, provided answer references a class
myobj = klass.new # instantiate an instance of the class
You can also do things like this:
KLASSES = { 'html' => HTMLWriter, 'pdf' => PDFWriter, 'plain-text' => TextWriter }
output = ARGV.shift
raise "invalid output type" unless KLASSES.include? output
writer = KLASSES[output].new
···
On 03 Dec 2004, at 10:44, Bradley, Todd wrote:
Hi, I'm just now getting into Ruby's OO-ness, and could use some advice.
I'm trying to create an object, but which specific class needs to be
determined at runtime. I figured out how to do this by creating a
string and executing it using the "eval" command, but I know there must
be an easier way. My first guess was to do something like #{answer}.new
but that didn't work.
Here's my code:
class Foo
def method1
end
end
class Bar
def method2
end
end
# Pretend this was determined at runtime
answer = "Foo"
# There must be a better way of doing this:
myobj = Object.new # Needs to exist in this scope
mystring = "myobj = #{answer}.new"
eval mystring
puts "I just created a #{myobj.class} object."
"new" is just a class method, and you can call class methods on classes that aren't bound at the time of interpretation. For example:
instance = MyClass.new
is the same as
a_class = MyClass
instance = a_class.new
So you can do things like:
irb(main):001:0> classes = [ String, Hash, Array ]
=> [String, Hash, Array]
irb(main):002:0> grab_bag = classes.collect { |a_class| a_class.new }
=> ["", {}, ]
···
On Dec 3, 2004, at 1:44 PM, Bradley, Todd wrote:
Hi, I'm just now getting into Ruby's OO-ness, and could use some advice.
I'm trying to create an object, but which specific class needs to be
determined at runtime. I figured out how to do this by creating a
string and executing it using the "eval" command, but I know there must
be an easier way. My first guess was to do something like #{answer}.new
but that didn't work.
Here's my code:
class Foo
def method1
end
end
class Bar
def method2
end
end
# Pretend this was determined at runtime
answer = "Foo"
# There must be a better way of doing this:
myobj = Object.new # Needs to exist in this scope
mystring = "myobj = #{answer}.new"
eval mystring
puts "I just created a #{myobj.class} object."
Any advice is appreciated. Thanks in advance!
Todd.
Francis Hwang
Bradley, Todd wrote:
Hi, I'm just now getting into Ruby's OO-ness, and could use some advice.
I'm trying to create an object, but which specific class needs to be
determined at runtime. I figured out how to do this by creating a
string and executing it using the "eval" command, but I know there must
be an easier way. My first guess was to do something like #{answer}.new
but that didn't work.
Here's my code:
class Foo
def method1
end
end
class Bar
def method2
end
end
# Pretend this was determined at runtime
answer = "Foo"
# There must be a better way of doing this:
myobj = Object.new # Needs to exist in this scope
mystring = "myobj = #{answer}.new"
eval mystring
puts "I just created a #{myobj.class} object."
You could do:
myobj = eval("Foo.new")
or
myobj = eval("Foo").new
or even
myobj = Object.const_get( "Foo" ).new
I prefer the second option listed, since it is easier to pass arguments to constructor, and less verbose than the third option.
- Jamis
···
Any advice is appreciated. Thanks in advance!
Todd.
--
Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck.org/jamis
Bradley, Todd wrote:
Hi, I'm just now getting into Ruby's OO-ness, and could use some advice.
I'm trying to create an object, but which specific class needs to be
determined at runtime. I figured out how to do this by creating a
string and executing it using the "eval" command, but I know there must
be an easier way. My first guess was to do something like #{answer}.new
but that didn't work.
Here's my code:
class Foo
def method1
end
end
class Bar
def method2
end
end
# Pretend this was determined at runtime
answer = "Foo"
# There must be a better way of doing this:
myobj = Object.new # Needs to exist in this scope
mystring = "myobj = #{answer}.new"
eval mystring
puts "I just created a #{myobj.class} object."
Any advice is appreciated. Thanks in advance!
Todd.
class GMClassManager
@@classHash = { 'CLASS_ROOM_DEFAULT' => GMRoom,
'CLASS_ROOM_LOGIN' => GMLoginRoom,
}
def GMClassManager.getRoomObject( valueClassId )
tmpClass = @@classHash[ valueClassId ]
if not tmpClass == nil
tmpClass.new
else
nil
end
end
end
This works for me
Daneel van Tonder wrote:
class GMClassManager
@@classHash = { 'CLASS_ROOM_DEFAULT' => GMRoom,
'CLASS_ROOM_LOGIN' => GMLoginRoom,
}
Using a constant instead would be nicer, I think.