class C
def self.inherited(klass)
klass_name = klass.name[/[^:]+$/]
klass.to_s.split(/::/)[0...-1].inject(Object) { |const, name|
const.const_get name
}.send :remove_const, klass_name
C.const_set klass_name, klass
end
end
NB: Don't do this.
Yes! Why haven't I thought of this solution?!
Thanks for that one.
Are the any non obvious reasons as why not to do this type of trick
(code obfuscation, maintance hell etc.)?
Yes, there's a reason: it does not work:
10:17:43 Temp$ ruby mod.rb
initial
after remove
after set
10:17:51 Temp$ cat mod.rb
module A
class X
end
end
$cl = ::X
puts "initial", $cl, $cl.name
A.send :remove_const, 'X'
puts "after remove", $cl, $cl.name
module B
end
B.send :const_set, 'Y', $cl
puts "after set", $cl, $cl.name
10:18:08 Temp$
Here's one way to do it:
class Root
# features all objects of dsl share
class Object
def my_name
# silly example
self.class.name
end
end
class <<self
def class_def(name, parent = Object, &b)
parent = const_get(parent) unless Module === parent
cl = Class.new parent
const_set name, cl
cl.class_eval(&b)
cl
end
end
end
def Object.const_missing(sym)
Root.send :const_get, sym
end
def dsl(&b)
Root.class_eval(&b)
end
dsl {
class_def :Base do
def hello() puts "Hello, I am #{my_name}." end
end
class_def :Derived, Base do
# nothing here
end
Derived.new.hello
p Derived.ancestors
}
Cheers
robert
···
2008/10/19 Adam Skobi <dxm997@gmail.com>:
A::X
A::X
A::X
A::X
A::X
A::X
--
remember.guy do |as, often| as.you_can - without end