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:
- What’s the correct way to doing this?
- I would have thought the non-qualified class references would have
generated exceptions.
- What is the warning message trying to convey.
- 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
- I would have thought the non-qualified class references would have
generated exceptions.
Very intriguing. I would have expected the same
DMisener wrote:
- What’s the correct way to doing this?
- I would have thought the non-qualified class references would have
generated exceptions.
- 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
Drew O. wrote:
DMisener wrote:
- What’s the correct way to doing this?
- I would have thought the non-qualified class references would have
generated exceptions.
- 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