Suppose I make a module as follows:
m = Module.new do
class C
end
end
Three questions:
Other than a reference to m
, is there a way I can access C
and other things inside m
?
Can I give a name to the anonymous module after I've created it (just as if I'd typed "module ...")?
How do I delete the anonymous module when I'm done with it, such that the constants it defines are no longer present?
Three answers:
Yes, using ObjectSpace
. This code makes c
refer to your class C
without referencing m
:
c = nil
ObjectSpace.each_object { |obj|
c = obj if (Class === obj and obj.name =~ /::C$/)
}
Of course this depends on there being no other classes named C
anywhere in the program, but you get the idea.
Yes, sort of. If you just assign it to a constant, like M = m
, then m.name
will return "M"
instead of nil
, and references like M::C
will work. Actually, when I do this and type M::C
in irb, I get #<Module:0x9ed509c>::C
, but maybe that's a bug.
m
or C
, and m
is set to a different value or goes out of scope. If you assigned it to a constant as in the above point, you would need to change it to a different value too (though changing constants is generally ill-advised).Once way to handle this is to define your own kind of module that can be initialized with a name.
class NamedModule < Module
attr_accessor :name
def initialize(name, &block)
super(&block)
self.name = name
end
def to_s
[self.class.name, name, object_id].join(':')
end
end
Then you can do this:
piracy = NamedModule.new("Piracy") do
def berate
puts "Yer a #{adjectives.sample} #{nouns.sample}!"
end
private
def adjectives
%w[yella-bellied landlubbing]
end
def nouns
%w[scallywag bilge-drinker]
end
end
Sailor = Class.new
Sailor.send(:include, piracy)
Sailor.new.berate #=> "Yer a yella-bellied scallywag!"
Defining to_s
gives you nice output in ancestors
:
Sailor.ancestors
#=> [Sailor, NamedModule:Piracy:70169997844420, Object, Kernel, BasicObject]
After my colleague and I had experimented with this, he wrote a small gem implementation. Check out the Named gem - Rubygems and Github.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With