[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How to create a class in callers context??

DMisener

3/5/2008 7:50:00 PM

Here's a simple example of my predicament:

class Factory
def self.generate name,_binding
_name=name.to_s.capitalize
eval %[
class #{_name}
def to_s
"#{_name}"
end
end
],_binding
end
end

def Factory_generate what
Factory.generate what,binding
end

Factory_generate :Thing
puts Factory::Thing.new rescue puts "Can't
Factory::Thing.new" # warning
puts Thing .new rescue puts "Can't Thing.new"

class Universe
def initialize
Factory_generate :Planet
puts Universe::Planet.new rescue puts "Can't
Universe::Planet.new" # warning
puts Planet .new rescue puts "Can't Planet.new"
end
end

Universe.new

puts Universe::Planet.new rescue puts "Can't
Universe::Planet.new" # warning
puts Planet .new rescue puts "Can't Planet.new"

---------------------------------------------
results in the following surprising output:

C:/Work/class_eval.rb:20: warning: toplevel constant Thing referenced
by Factory::Thing
Thing
Thing
C:/Work/class_eval.rb:26: warning: toplevel constant Planet referenced
by Universe::Planet
Planet
Planet
C:/Work/class_eval.rb:33: warning: toplevel constant Planet referenced
by Universe::Planet
Planet
Planet
----------------------------------------------
Questions:

1) What's the correct way to doing this?
2) I would have thought the non-qualified class references would have
generated exceptions.
3) What is the warning message trying to convey.
3 Answers

Rubén Medellín

3/6/2008 1:35:00 AM

0


> 1) What's the correct way to doing this?

Don't know the "correct" way, there is always more than one form to do
it. This is what I would do

class Class
def generate(name)
klass = Class.new
klass.class_eval <<-EVAL
def to_s
"I'm a #{name}"
end
EVAL
const_set(name, klass)
end
end

class Universe
generate :Planet
puts Planet.new
puts Universe::Planet.new
end

puts Planet.rescue "No Planet!"
puts Universe::Planet.new

_______
I'm a Planet
I'm a Planet
No Planet!
I'm a Planet
_______

alternatively you could do

klass = Class.new do
def foo
#...
end
end

but then you can't pass a reference to the variable name. Don't know
if there's a way do do it, though.

If I wanted that to stick on a method, I would pass the binding as
well

class Factory
def self.generate(name, _binding)
eval <<-EVAL, _binding
class #{name}
def to_s
"Hello from #{name}"
end
end
EVAL
end
end

> 2) I would have thought the non-qualified class references would have
> generated exceptions.

Very intriguing. I would have expected the same

Drew Olson

3/6/2008 5:16:00 AM

0

DMisener wrote:
> 1) What's the correct way to doing this?
> 2) I would have thought the non-qualified class references would have
> generated exceptions.
> 3) What is the warning message trying to convey.

Here's my crack at this, not sure this is what you're trying to do:

def generate &name
eval("self",name.binding).class.class_eval <<-EOS
class #{name.call}
def to_s
name.call
end
end
EOS
end

class Universe
def initialize
generate{:Planet}
puts Universe::Planet
end
end

generate{:Thing}

Universe.new
puts Thing
--
Posted via http://www.ruby-....

Drew Olson

3/6/2008 5:26:00 AM

0

Drew Olson wrote:
> DMisener wrote:
>> 1) What's the correct way to doing this?
>> 2) I would have thought the non-qualified class references would have
>> generated exceptions.
>> 3) What is the warning message trying to convey.
>
> Here's my crack at this, not sure this is what you're trying to do:

Had a small typo, here's the fixed example:

def generate &name
eval("self",name.binding).class.class_eval <<-EOS
class #{name.call}
def to_s
"#{name.call}"
end
end
EOS
end

class Universe
def initialize
generate{:Planet}
end
end

generate{:Thing}

Universe.new

puts Universe::Planet.new
puts Thing.new
--
Posted via http://www.ruby-....